Я уже запустил работающий конвейер gstreamer во встроенном приложении на C linux. Конвейер выглядит следующим образом:
appsrc-> queue -> h264encode -> queue -> h264parse -> mp4mux -> filesink
Источником является буфер видеопамяти, который помещается в appscrэлемент, использующий стандартный метод "need-data".
Код похож на примеры gstreamer и выглядит следующим образом:
static void
cb_need_data (GstElement *appsrc,
guint unused_size,
gpointer user_data)
{
static gboolean white = FALSE;
static GstClockTime timestamp = 0;
GstBuffer *buffer;
guint size;
GstFlowReturn ret;
size = 1024 * 768 * 2;
buffer = gst_buffer_new_and_alloc (size);
/* this makes the image black/white */
memset (buffer->data, white ? 0x55 : 0xaa, size);
white = !white;
GST_BUFFER_TIMESTAMP (buffer) = timestamp;
GST_BUFFER_DURATION (buffer) = gst_util_uint64_scale_int (1, GST_SECOND, 2);
timestamp += GST_BUFFER_DURATION (buffer);
g_print("push-buffer\n");
//g_signal_emit_by_name (appsrc, "push-buffer", buffer, &ret);
ret = gst_app_src_push_buffer(GST_APP_SRC(appsrc), buffer);
if (ret != GST_FLOW_OK) {
/* something wrong, stop pushing */
g_print("ret fail\n");
g_main_loop_quit (loop);
}
}
gint
main (gint argc,
gchar *argv[])
{
GstElement *pipeline, *appsrc;
/* init GStreamer */
gst_init (&argc, &argv);
loop = g_main_loop_new (NULL, FALSE);
/* setup pipeline */
pipeline = gst_parse_launch("appsrc name=mysource ! fakesink silent=0", NULL);
appsrc = gst_bin_get_by_name_recurse_up (GST_BIN (element), "source");
GstCaps *caps = gst_video_format_new_caps(GST_VIDEO_FORMAT_UYVY, 1024, 768, 0, 1, 4, 3);
gst_app_src_set_caps(GST_APP_SRC(appsrc), caps);
/* setup appsrc */
g_object_set (G_OBJECT (appsrc),
"stream-type", 0,
"format", GST_FORMAT_TIME, NULL);
g_signal_connect (appsrc, "need-data", G_CALLBACK (cb_need_data), NULL);
/* play */
gst_element_set_state (pipeline, GST_STATE_PLAYING);
g_print("PLAY\n");
g_main_loop_run (loop);
/* clean up */
gst_element_set_state (pipeline, GST_STATE_NULL);
gst_object_unref (GST_OBJECT (pipeline));
g_main_loop_unref (loop);
return 0;
}
Теперь мне нужно запустить несколько одинаковых конвейеров параллельно. Поскольку элементы конвейера будут идентичны, я планирую создать структуру данных, содержащую все необходимые элементы gstreamer, например, я должен иметь возможность создавать различные экземпляры одного и того же типа конвейера:
appsrc1-> ...... -> filesink1
appsrc2-> ...... -> filesink2
appsrc3-> ...... -> filesink3
.....
Вопрос:
Проблема в том, что я не знаю, как создать функцию обратного вызова cb_need_data
для каждого из различных элементов appsrc
, возможно ли создать эту функцию? Или мне нужно создать копию для каждого конвейера? (cb_need_data1, cb_need_data2, ... и т. д.)