質問

Situation:

When I'm trying to mux jpegs to mkv file I'll get a zero sized file. I must put encode and decode elements between parser and muxer for correct output. When I'm muxing a h264 video with same code I'll get correct video file, that means the time setting of buffers should be OK(duration and pts parameter). Anyway after bad buffer settings is size of file not zero. Matroskamux requires on sink pad for "image/jpeg" only "width" and "heigth" capabilities but it looks like that this is not sufficient. Jpegparse is giving correct values and the program does not work after manual setting of this capabilities too.

Example of pipeline:

This pipeline doesn't work

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

But this works

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

Example of code:

Working code, but with reencoding

    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;
    }

Question:

What I am doing wrong? Any ideas to solve this problem?

役に立ちましたか?

解決

I solved this problem with change of appsrc property "format" from GST_FORMAT_BUFFERS to GST_FORMAT_TIME. Correct timestamps on buffers is not enought.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top