Gstreamer-appsrc推送模型



我正在开发一个C应用程序(在linux下),它接收一个原始的h.264流,并且应该使用gstreamer API可视化这个流。我是GStreamer的新手,所以也许我犯了巨大的愚蠢错误或忽略了众所周知的东西,对此我感到抱歉。

我得到了一个原始的h264视频(我知道它和我需要的格式完全一样),并开发了一个播放它的应用程序。它在拉模式下正确地与appsrc一起工作(当调用需要的数据时,我从文件中获取新数据并执行推送缓冲)。

现在我正在尝试做完全相同的事情,但在推送模式下,这基本上是因为我没有视频,而是流。因此,我在代码中有一个方法,每当新数据(以uint8_t缓冲区的形式)到达时都会调用它,这就是我的视频源。

我在谷歌上搜索了我的问题,并查看了文档,但我没有发现适用于我的用例的简单代码片段,即使它看起来很简单。我知道我必须初始化管道和appsrc,然后只有当我有新数据时才推送缓冲区。

我开发了两种方法:init_stream()用于pipeline/appsrc初始化,populate_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 donen");
    /* create a mainloop to get messages */
    app->loop = g_main_loop_new (NULL, TRUE);
    fprintf(stderr, "app loop initializedn");

    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 initializedn");
    /* Create Bus from pipeline */
    bus = gst_pipeline_get_bus(app->pipeline);
    fprintf(stderr, "bus createdn");
    /* add watch for messages */
    gst_bus_add_watch (bus, (GstBusFunc) bus_message, app);
    gst_object_unref(bus);
    fprintf(stderr, "bus_add_watch donen");
    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 playn");
    /* this mainloop is stopped when we receive an error or EOS */
    g_main_loop_run (app->loop);
    fprintf(stderr, "g_main_loop_run calledn");
    gst_element_set_state ((GstElement*) app->pipeline, GST_STATE_NULL);
    fprintf(stderr, "gst_element_set_state GST_STATE_NULLn");
    /* 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的新手,所以有很多来自互联网的剪切和粘贴代码,但IMHO应该可以。你看到什么问题了吗?

目前尚不清楚您是如何调用populateApp的,但您需要重复调用它,因为您有数据要推送到管道中。这可以在一个独立于g_main_loop_run阻止的线程中完成,也可以重组程序以避免使用GMainLoop。

相关内容

  • 没有找到相关文章

最新更新