c++gstreamerh.264decoder

GStreamer Pipeline: Decoding H.264 from Appsrc to Appsink


I need to decode an H.264 file with a single frame. The original file was encoded from NV12 format. Now, I want to decode it back to NV12 and then convert it to JPEG. I've successfully achieved this using the gst-launch-1.0 command line tool with the following pipeline:

$ gst-launch-1.0 filesrc location=input_h264.h264 ! video/x-h264, width=1920, height=1080, encoding-name=H264 ! h264parse! avdec_h264 ! videoconvert ! video/x-raw, format=NV12 ! jpegenc ! image/jpeg ! filesink location=output.jpg

This pipeline works perfectly. However, when I attempt to create a similar pipeline using GStreamer's appsrc and appsink elements, I encounter an error message:

Error: Internal data stream error.
Error received from element mysource: Internal data stream error.
Debugging information: gstbasesrc.c(3072): gst_base_src_loop (): /GstPipeline:mypipeline/GstAppSrc:mysource:
streaming stopped, reason not-negotiated (-4)

Here's the pipeline I'm trying to set up programmatically in my code:

pipeline = gst_pipeline_new("mypipeline");
appsrc = gst_element_factory_make("appsrc", "mysource");
jpegenc = gst_element_factory_make("jpegenc", "myenc");
parser = gst_element_factory_make("h264parse", "parser");
decoder = gst_element_factory_make("avdec_h264", "decode");
rawfilter = gst_element_factory_make("capsfilter", "rawfilter");
h264filter = gst_element_factory_make("capsfilter", "h264filter");
videoconvert = gst_element_factory_make("videoconvert", "myvideoconvert");
appsink = gst_element_factory_make("appsink", "mysink");

// Check if all elements were created (I've omitted error handling for brevity)
...

caps = gst_caps_new_simple("video/x-h264",
        "width", G_TYPE_INT, width, "height",
        G_TYPE_INT, height,
        "encoding-name", G_TYPE_STRING, "H264", 
        "framerate", GST_TYPE_FRACTION, 1, 1,
        "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1,
        "stream-format", G_TYPE_STRING, "avc",
        "parsed", G_TYPE_BOOLEAN, TRUE,
        "level", G_TYPE_STRING, "4",
        NULL);

// Set custom stream-id for appsrc
const gchar *customStreamId = "stream-1";
g_object_set(G_OBJECT(appsrc), "stream-id", customStreamId, NULL);
g_object_set(G_OBJECT(appsrc), "stream-type", GST_APP_STREAM_TYPE_STREAM, NULL);

    g_object_set(G_OBJECT(rawfilter), "caps", caps, NULL);
    g_object_set(G_OBJECT(h264filter), "caps", caps, NULL);
    gst_caps_unref(caps);

    // blocksize is important for jpegenc to know how many data to expect from appsrc in a single frame, too
    char szTemp[64];
    sprintf(szTemp, "%d", (int)fileSize);
    g_object_set(G_OBJECT (appsrc), "blocksize", szTemp,
            NULL);

    // Jpeg encoding quality
    g_object_set(G_OBJECT (jpegenc), "quality", quality, NULL);

    // Create gstreamer loop
    loop = g_main_loop_new(NULL, FALSE);

    // add a message handler
    bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));
    bus_watch_id = gst_bus_add_watch(bus, bus_call, loop);
    gst_object_unref(bus);
    
    // Build the pipeline , videoconvert
    gst_bin_add_many(GST_BIN(pipeline), appsrc, parser, rawfilter, decoder, h264filter,videoconvert,jpegenc, appsink, NULL); //videoconvert
    if (gst_element_link_many(appsrc, rawfilter,  parser,  decoder,videoconvert,jpegenc, appsink, NULL) != TRUE) {
        g_error("Failed to link elements");
        return NULL;
    }

I'm struggling with this issue and can't seem to figure out what's causing the "not-negotiated" error. If anyone has experience with GStreamer and can offer some guidance on how to resolve this problem, it would be greatly appreciated!

Log for the pipeline with debug level = 4.

0:00:00.099873945 274680 0x7f6b24075580 WARN               h264parse gsth264parse.c:2963:gst_h264_parse_set_caps:<parser> H.264 AVC caps, but no codec_data
0:00:00.099908490 274680 0x7f6b24075580 WARN               h264parse gsth264parse.c:2989:gst_h264_parse_set_caps:<parser> refused caps video/x-h264, width=(int)1920, height=(int)1080, encoding-name=(string)H264, framerate=(fraction)1/1, pixel-aspect-ratio=(fraction)1/1, stream-format=(string)avc, parsed=(boolean)true, level=(string)4
Read for data push
Buffer Size: 122460
0:00:00.108377141 274680 0x7f6b24075580 INFO               GST_EVENT gstevent.c:900:gst_event_new_segment: creating segment event time segment start=0:00:00.000000000, offset=0:00:00.000000000, stop=99:99:99.999999999, rate=1.000000, applied_rate=1.000000, flags=0x00, time=0:00:00.000000000, base=0:00:00.000000000, position 0:00:00.000000000, duration 99:99:99.999999999
0:00:00.108472425 274680 0x7f6b24075580 WARN               h264parse gsth264parse.c:2963:gst_h264_parse_set_caps:<parser> H.264 AVC caps, but no codec_data
0:00:00.108518647 274680 0x7f6b24075580 WARN               h264parse gsth264parse.c:2989:gst_h264_parse_set_caps:<parser> refused caps video/x-h264, width=(int)1920, height=(int)1080, encoding-name=(string)H264, framerate=(fraction)1/1, pixel-aspect-ratio=(fraction)1/1, stream-format=(string)avc, parsed=(boolean)true, level=(string)4
0:00:00.108548569 274680 0x7f6b24075580 INFO                 basesrc gstbasesrc.c:2962:gst_base_src_loop:<mysource> marking pending DISCONT
0:00:00.108589666 274680 0x7f6b24075580 WARN               h264parse gsth264parse.c:2963:gst_h264_parse_set_caps:<parser> H.264 AVC caps, but no codec_data
0:00:00.108623674 274680 0x7f6b24075580 WARN               h264parse gsth264parse.c:2989:gst_h264_parse_set_caps:<parser> refused caps video/x-h264, width=(int)1920, height=(int)1080, encoding-name=(string)H264, framerate=(fraction)1/1, pixel-aspect-ratio=(fraction)1/1, stream-format=(string)avc, parsed=(boolean)true, level=(string)4
0:00:00.108726002 274680 0x7f6b24075580 WARN                 basesrc gstbasesrc.c:3072:gst_base_src_loop:<mysource> error: Internal data stream error.
0:00:00.108749012 274680 0x7f6b24075580 WARN                 basesrc gstbasesrc.c:3072:gst_base_src_loop:<mysource> error: streaming stopped, reason not-negotiated (-4)
0:00:00.108812807 274680 0x7f6b24075580 INFO        GST_ERROR_SYSTEM gstelement.c:2153:gst_element_message_full_with_details:<mysource> posting message: Internal data stream error.
0:00:00.108890560 274680 0x7f6b24075580 INFO        GST_ERROR_SYSTEM gstelement.c:2180:gst_element_message_full_with_details:<mysource> posted error message: Internal data stream error.
Error: Internal data stream error.

Solution

  • h264parse gsth264parse.c:2963:gst_h264_parse_set_caps:<parser> H.264 AVC caps, but no codec_data
    

    This warning is saying that despite setting avc in your caps, the stream does not have the necessary codec information. This is something that was either lost or that was not included in the original stream.

    The stream should work without the avc specification in the caps. If the issue persists, I suggest simplifying the caps to the ones you tested in the gst-launch-1.0 pipeline and work your way up to what you need:

    caps = gst_caps_new_simple("video/x-h264",
            "width", G_TYPE_INT, width, "height",
            G_TYPE_INT, height,
            "encoding-name", G_TYPE_STRING, "H264",
            NULL);