GStreamer 管道:将 H.264 从 Appsrc 解码到 Appsink

问题描述 投票:0回答:1

我正在开发一个项目,需要用单帧解码 H.264 文件。原始文件是从 NV12 格式编码的。现在,我想将其解码回 NV12,然后将其转换为 JPEG。我已经使用

gst-launch-1.0
命令行工具和以下管道成功实现了这一目标:

$ 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

这条管道运行完美。但是,当我尝试使用 GStreamer 的

appsrc
appsink
元素创建类似的管道时,我遇到一条错误消息:

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)

这是我尝试在代码中以编程方式设置的管道:

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

我正在努力解决这个问题,似乎无法弄清楚是什么导致了“未协商”错误。如果有人有 GStreamer 的经验并且可以提供一些有关如何解决此问题的指导,我们将不胜感激!

调试级别 = 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.
c++ gstreamer h.264 decoder
1个回答
0
投票
WARN               h264parse gsth264parse.c:2963:gst_h264_parse_set_caps:<parser> H.264 AVC caps, but no codec_data

此警告表示,尽管在大写字母中设置了

avc
,但流没有必要的编解码器信息。这要么是丢失了,要么是没有包含在原始流中。

流应该在大写字母中没有

avc
规范的情况下工作。如果问题仍然存在,我建议将上限简化为您在
gst-launch-1.0
管道中测试的上限,并逐步达到您需要的程度:

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);
© www.soinside.com 2019 - 2024. All rights reserved.