使用gstreamer将jpeing jpeg复制到mkv

时间:2013-11-26 02:58:44

标签: c++ jpeg gstreamer mux matroska

情况:

当我尝试将jpegs复制到mkv文件时,我会得到一个零大小的文件。我必须在解析器和多路复用器之间放置编码和解码元素以获得正确的输出。当我使用相同的代码复用h264视频时,我将获得正确的视频文件,这意味着缓冲区的时间设置应该是正常的(持续时间和pts参数)。无论如何,错误的缓冲区设置后文件大小不为零。 Matroskamux需要在接收器垫上“image / jpeg”只有“width”和“heigth”功能,但看起来这还不够。 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;
    }

问题:

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

1 个答案:

答案 0 :(得分:0)

我通过将appsrc属性“format”从GST_FORMAT_BUFFERS更改为GST_FORMAT_TIME来解决了这个问题。没有提供缓冲区上正确的时间戳。