【问题标题】:muxing jpeg to mkv using gstreamer使用 gstreamer 将 jpeg 复用到 mkv
【发布时间】:2013-12-11 01:00:12
【问题描述】:

情况:

当我尝试将 jpeg 多路复用到 mkv 文件时,我会得到一个零大小的文件。我必须在解析器和复用器之间放置编码和解码元素以获得正确的输出。当我用相同的代码混合 h264 视频时,我会得到正确的视频文件,这意味着缓冲区的时间设置应该是好的(持续时间和 pts 参数)。无论如何,在缓冲区设置错误之后,文件的大小不为零。 Matroskamux 只需要接收器上的“image/jpeg”“宽度”和“高度”功能,但看起来这还不够。 Jpegparse 给出了正确的值,并且在手动设置此功能后程序也无法运行。

管道示例:

此管道不起作用

appsrc ! "image/jpeg" ! jpegparse ! matroskamux ! filesink location=mjpeg.mkv

但是这行得通

appsrc ! "image/jpeg" ! jpegparse ! avdec_mjpeg ! x264enc ! matroskamux ! filesink location=mjpeg.mkv

代码示例:

工作代码,但需要重新编码

    app = new _App();

    app->src = (GstAppSrc*)gst_element_factory_make ("appsrc", "source");

    if(IsH264Frame(codecType))
        app->parser = gst_element_factory_make("h264parse", "parser");
    else if(codecType == IMAGE_MJPEG_FRAME)
        app->parser = gst_element_factory_make("jpegparse", "parser");

        //additional code
    app->decoder = gst_element_factory_make("avdec_mjpeg", "decoder");
    app->encoder = gst_element_factory_make("x264enc", "encoder");

    app->muxer = gst_element_factory_make("matroskamux", "muxer");
    app->sink = (GstAppSink*)gst_element_factory_make ("filesink", "sink");


    if (!app->pipeline || !app->src || !app->decoder || !app->encoder || !app->muxer || !app->sink || !app->parser)
        return;



    app->bus = gst_pipeline_get_bus (GST_PIPELINE (app->pipeline));
    g_assert(app->bus);
    gst_bus_add_watch (app->bus, (GstBusFunc) BusMessage, this);


    gst_bin_add_many (GST_BIN (app->pipeline), (GstElement*)app->src, app->decoder, app->encoder, app->muxer, app->sink, app->parser
        ,NULL);


            /*          SETUP ELEMENTS          */


    g_object_set(app->src,
        "stream-type", 0,
        "format", GST_FORMAT_BUFFERS, 
        "is-live", true,
        "block", true,
        NULL);

    if(IsH264Frame(codecType)){

        g_object_set(app->src, "caps", gst_caps_new_simple("video/x-h264",
            NULL), NULL);

    } else if(codecType == IMAGE_MJPEG_FRAME) {

        g_object_set(app->src, "caps", gst_caps_new_simple("image/jpeg",
            "framerate",GST_TYPE_FRACTION,(int)framerate,1, 
            NULL), NULL);

        //additional code

        g_object_set(app->decoder, "caps", gst_caps_new_simple("video/x-raw",
            NULL), NULL);

        g_object_set(app->encoder, "caps", gst_caps_new_simple("video/x-h264",
            NULL), NULL);

    }


    g_signal_connect(app->src, "need-data", G_CALLBACK(StartFeed), this);
    g_signal_connect(app->src, "enough-data", G_CALLBACK(StopFeed), this);


    g_object_set (app->sink, 
        "location", GenerateFileName().c_str(),
        "buffer-mode", 0,
        NULL);


      /*            LINKING         */


    GstPad *padDecSrc, *padMuxSink, *parserSrc,
    GstPadTemplate *mux_sink_pad_template;

    mux_sink_pad_template = gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (app->muxer), "video_%u");
    padMuxSink = gst_element_request_pad (app->muxer, mux_sink_pad_template, NULL, NULL);

    parserSrc = gst_element_get_static_pad (app->parser, "src");
    padEncSrc = gst_element_get_static_pad (app->encoder, "src");


    if(!gst_element_link( (GstElement*)app->src,  app->parser))
            return;

    if(IsH264Frame(codecType)){

        if(gst_pad_link (parserSrc, padMuxSink) != GST_PAD_LINK_OK)
            return;

    } else if(codecType == IMAGE_MJPEG_FRAME){ 

        //additional code
        if(!gst_element_link( app->parser,  app->decoder))
            return;

        if(!gst_element_link( app->decoder,  app->encoder))
            return;

        if(gst_pad_link (padDecSrc, padMuxSink) != GST_PAD_LINK_OK)
            return;

    }

    if(!gst_element_link( app->muxer,  (GstElement*)app->sink))
        return;


            /*          PLAY            */


    GstStateChangeReturn ret = gst_element_set_state (app->pipeline, GST_STATE_PLAYING);

    if (ret == GST_STATE_CHANGE_FAILURE) 
    {
        gst_object_unref (app->pipeline);
        return;
    }

问题:

我做错了什么?有什么想法可以解决这个问题吗?

【问题讨论】:

  • 您找到解决方案了吗?可以在 matroska 容器中创建 MJPEG 文件吗?
  • 只有这种肮脏的重新编码“解决方案”。我打算调试 matroskamux 元素以检查出了什么问题,但我现在没有时间。也许一个好主意是在重新编码之前和之后分析 jpeg 图像并检查差异。如果您找到解决方案,请在此处告诉我。
  • 您没有发布足够的代码来重现您的问题 - 您需要提供实际上将缓冲区通过 appsrc 推送到管道中的代码。由于缓冲区中未设置时间戳,您可能会从 matroskamux 收到 Invalid buffer timestamp; dropping buffer 错误。

标签: c++ jpeg gstreamer mux matroska


【解决方案1】:

我通过将appsrc 属性“格式”从GST_FORMAT_BUFFERS 更改为GST_FORMAT_TIME 解决了这个问题。缓冲区上的正确时间戳是不够的。

【讨论】:

    猜你喜欢
    • 2021-02-14
    • 1970-01-01
    • 2017-10-01
    • 2017-05-27
    • 2013-11-12
    • 2013-08-10
    • 2013-05-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多