Skip to content

Instantly share code, notes, and snippets.

@tetkuz
Last active March 18, 2020 20:54
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tetkuz/a2140f671e9cbdcd960bbd02afe3bd5c to your computer and use it in GitHub Desktop.
Save tetkuz/a2140f671e9cbdcd960bbd02afe3bd5c to your computer and use it in GitHub Desktop.
GST_MESSAGE_ELEMENT Sample
#include <gst/gst.h>
static void
fakesink_handoff (GstElement* object, GstBuffer* arg0, GstPad* arg1, gpointer data)
{
static gint cnt=0;
GstElement *pipeline = GST_ELEMENT(data);
(void)object;
(void)arg0;
(void)arg1;
if (cnt%30 == 0) {
gst_bus_post (
gst_pipeline_get_bus (GST_PIPELINE (pipeline)),
gst_message_new_element (
GST_OBJECT_CAST (object), gst_structure_new ("fakesink", NULL, NULL)));
}
cnt++;
}
static gboolean
bus_message_handler (GstBus * bus, GstMessage * message, gpointer data)
{
static gint handled_cnt = 0;
GMainLoop *loop = (GMainLoop *)data;
(void)bus;
switch (message->type) {
case GST_MESSAGE_ELEMENT:
{
handled_cnt++;
g_message ("get message %d: %s", handled_cnt,
gst_structure_get_name (gst_message_get_structure(message)));
if (handled_cnt >= 3) {
g_message ("g_main_loop_quit ()");
g_main_loop_quit (loop);
}
break;
}
case GST_MESSAGE_EOS:
g_message ("got EOS");
g_main_loop_quit (loop);
break;
case GST_MESSAGE_WARNING:
case GST_MESSAGE_ERROR:
{
GError *gerror;
gchar *debug;
if (message->type == GST_MESSAGE_ERROR)
gst_message_parse_error (message, &gerror, &debug);
else
gst_message_parse_warning (message, &gerror, &debug);
gst_object_default_error (GST_MESSAGE_SRC (message), gerror, debug);
g_error_free (gerror);
g_free (debug);
g_main_loop_quit (loop);
break;
}
default:
break;
}
return TRUE;
}
int main(int argc, char *argv[])
{
GMainLoop *loop;
GstElement *pipeline;
GstElement *sink;
GstBus *bus;
gst_init (&argc, &argv);
loop = g_main_loop_new (NULL, FALSE);
pipeline = gst_parse_launch ("videotestsrc ! video/x-raw,framerate=30/1 ! "
"fakesink sync=true name=fakesink signal-handoffs=true", NULL);
sink = gst_bin_get_by_name (GST_BIN(pipeline), "fakesink");
g_signal_connect (sink, "handoff", G_CALLBACK(fakesink_handoff), pipeline);
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
gst_bus_add_watch (bus, bus_message_handler, loop);
gst_element_set_state (pipeline, GST_STATE_PLAYING);
g_main_loop_run (loop);
gst_element_set_state (pipeline, GST_STATE_NULL);
gst_object_unref (pipeline);
gst_object_unref (bus);
return 0;
}

めも

Streaming thread をトリガーとして pipeline を操作(再生/停止などを)したい場合は、 Message を使って Application thread へ伝え、Application thread から pipeline を操作するのがベター

GST_MESSAGE_ELEMENT を使った場合の実装がこのコードです。

ちなみに、Streaming thread から gst_element_set_state()gst_element_seek() などの pipeline を操作する関数を呼ぶとデッドロックが発生します。

まとめ

pipeline に対する操作は、基本的に Application thread から行なうべき。

さんこう

キレイな実装ではないですが、同様のことは signal を使っても実装可能です。

[Application thread]
|
|                      application <----- kill(SIGUSR1) ---+
|                          |                               |
|                          v                               |
|                    signal_handler ()                     |
|                          |                               |
|                          | gst_element_seek ()           |
|                          |                               |
`------------------------- | ----------------------------- | --------
[Streaming thread]         |                               |
|                          v                               |
|                      Pipeline                            |
|                      `- filesrc ! filter !  fakesink     |
|                                                |         |
|                                                v         |
|                                             fakesink_handoff ()
|
`--------------------------------------------------------------------
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment