Gstreamer-appsrc推送模型
我正在开发一个C应用程序(在linux下),该应用程序接收原始h.264流,并应使用gstreamer API可视化该流。 我是GStreamer的新手,所以可能我犯了很多愚蠢的错误,或者忽略了一些众所周知的事情,对此我很抱歉 我得到了一个原始的h264视频(我知道它和我需要的格式完全一样),并开发了一个播放它的应用程序。它在拉模式下正确地与appsrc一起工作(当调用needdata时,我从文件中获取新数据并执行pushbuffer) 现在我正试图做完全相同的事情,但在推送模式下,这基本上是因为我没有视频,而是流。因此,我的代码中有一个方法,每次新数据(以Gstreamer-appsrc推送模型,stream,h.264,gstreamer,Stream,H.264,Gstreamer,我正在开发一个C应用程序(在linux下),该应用程序接收原始h.264流,并应使用gstreamer API可视化该流。 我是GStreamer的新手,所以可能我犯了很多愚蠢的错误,或者忽略了一些众所周知的事情,对此我很抱歉 我得到了一个原始的h264视频(我知道它和我需要的格式完全一样),并开发了一个播放它的应用程序。它在拉模式下正确地与appsrc一起工作(当调用needdata时,我从文件中获取新数据并执行pushbuffer) 现在我正试图做完全相同的事情,但在推送模式下,这基本上是因
uint8\t
缓冲区的形式)到达时都会调用该方法,这是我的视频源
我在谷歌上搜索了我的问题并查看了它,但是我没有找到适用于我的用例的简单代码片段,即使它看起来很简单。我知道我必须初始化管道和appsrc,然后只有在有新数据时才推送缓冲区
我开发了两种方法:init\u stream()
用于管道/appsrc初始化,以及populate\u app(void*inBuf,size\t len)
用于在可用时发送数据。
它编译并正确运行,但没有视频:
struct _App
{
GstAppSrc *appsrc;
GstPipeline *pipeline;
GstElement *h264parse;
GstElement *mfw_vpudecoder;
GstElement *mfw_v4lsin;
GMainLoop *loop;
};
typedef struct _App App;
App s_app;
App *app = &s_app;
static gboolean bus_message (GstBus * bus, GstMessage * message, App * app)
{
GST_DEBUG ("got message %s", gst_message_type_get_name (GST_MESSAGE_TYPE (message)));
switch (GST_MESSAGE_TYPE (message)) {
case GST_MESSAGE_ERROR:
g_error ("received error");
g_main_loop_quit (app->loop);
break;
case GST_MESSAGE_EOS:
g_main_loop_quit (app->loop);
break;
default:
break;
}
return TRUE;
}
int init_stream()
{
GstBus *bus;
gst_init (NULL, NULL);
fprintf(stderr, "gst_init done\n");
/* create a mainloop to get messages */
app->loop = g_main_loop_new (NULL, TRUE);
fprintf(stderr, "app loop initialized\n");
app->pipeline = gst_parse_launch("appsrc name=mysource ! h264parse ! mfw_vpudecoder ! mfw_v4lsin", NULL);
app->appsrc = gst_bin_get_by_name (GST_BIN(app->pipeline), "mysource");
gst_app_src_set_stream_type(app->appsrc, GST_APP_STREAM_TYPE_STREAM);
gst_app_src_set_emit_signals(app->appsrc, TRUE);
fprintf(stderr, "Pipeline and appsrc initialized\n");
/* Create Bus from pipeline */
bus = gst_pipeline_get_bus(app->pipeline);
fprintf(stderr, "bus created\n");
/* add watch for messages */
gst_bus_add_watch (bus, (GstBusFunc) bus_message, app);
gst_object_unref(bus);
fprintf(stderr, "bus_add_watch done\n");
GstCaps* video_caps = gst_caps_new_simple ("video/x-h264",
"width", G_TYPE_INT, 800,
"height", G_TYPE_INT, 480,
"framerate", GST_TYPE_FRACTION, 25,
1, NULL);
gst_app_src_set_caps(GST_APP_SRC(app->appsrc), video_caps);
/* go to playing and wait in a mainloop. */
gst_element_set_state ((GstElement*) app->pipeline, GST_STATE_PLAYING);
fprintf(stderr, "gst_element_set_state play\n");
/* this mainloop is stopped when we receive an error or EOS */
g_main_loop_run (app->loop);
fprintf(stderr, "g_main_loop_run called\n");
gst_element_set_state ((GstElement*) app->pipeline, GST_STATE_NULL);
fprintf(stderr, "gst_element_set_state GST_STATE_NULL\n");
/* free the file */
// g_mapped_file_unref (app->file);
gst_object_unref (bus);
g_main_loop_unref (app->loop);
return 0;
}
void populateApp(void *inBuf , size_t len) {
guint8 *_buffer = (guint8*) inBuf;
GstFlowReturn ret;
GstBuffer *buffer = gst_buffer_new();
GstCaps* video_caps = gst_caps_new_simple ("video/x-h264",
"width", G_TYPE_INT, 800,
"height", G_TYPE_INT, 480,
"framerate", GST_TYPE_FRACTION, 25,
1, NULL);
gst_buffer_set_caps(buffer, video_caps);
GST_BUFFER_DATA (buffer) = _buffer;
GST_BUFFER_SIZE (buffer) = len;
// g_signal_emit_by_name (app->appsrc, "push-buffer", buffer, &ret);
ret = gst_app_src_push_buffer(GST_APP_SRC(app->appsrc), buffer);
gst_buffer_unref (buffer);
}
如前所述,我是GStreamer的新手,所以有很多来自互联网的剪切粘贴代码,但我不知道它应该如何工作。
您看到任何问题了吗?不清楚您是如何调用populateApp的,但您需要重复调用,因为您有数据要推送到管道中。这可以在g_main_loop_run阻止的线程之外的另一个线程中完成,或者您可以重新构造程序以避免使用GMainLoop。您真的调用过populateApp吗?很难说程序流遗漏了这么多内容。也许您可以发布一个精简的main方法来显示如何调用stream_init,然后推送数据。