You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用GStreamer Appsrc/Appsink解码H.264转JPEG协商失败求助

问题:GStreamer Appsrc构建Pipeline时出现not-negotiated错误

需要解码单帧H.264文件(由NV12编码而来),目标是解码回NV12格式后转换为JPEG。命令行gst-launch-1.0能正常实现,但用appsrc/appsink通过代码构建Pipeline时触发not-negotiated错误。

正常运行的命令行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

错误信息

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");

// 省略元素创建检查逻辑...

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

// 设置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
char szTemp[64];
sprintf(szTemp, "%d", (int)fileSize);
g_object_set(G_OBJECT (appsrc), "blocksize", szTemp, NULL);

// 设置JPEG质量
g_object_set(G_OBJECT (jpegenc), "quality", quality, NULL);

// 创建主循环与总线监听
loop = g_main_loop_new(NULL, FALSE);
bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));
bus_watch_id = gst_bus_add_watch(bus, bus_call, loop);
gst_object_unref(bus);

// 添加并链接元素
gst_bin_add_many(GST_BIN(pipeline), appsrc, parser, rawfilter, decoder, h264filter,videoconvert,jpegenc, appsink, NULL);
if (gst_element_link_many(appsrc, rawfilter,  parser,  decoder,videoconvert,jpegenc, appsink, NULL) != TRUE) {
    g_error("Failed to link elements");
    return NULL;
}

调试日志(级别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.

问题根源与修复方案

核心问题分析

从日志警告可以定位到几个关键错误:

  1. Caps配置冲突:手动设置parsed=true和stream-format=avc,但appsrc输出的是原始H.264字节流,h264parse的作用就是解析原始流,这两个参数会导致解析器拒绝Caps。
  2. 元素链接顺序错误:冗余添加了h264filter且未使用,同时将rawfilter(CapsFilter)放在appsrc和h264parse之间,位置不合理。
  3. 参数类型错误:appsrc的blocksize是整数类型,代码中传入字符串导致设置无效。
  4. 缺少NV12格式约束:命令行中明确指定了解码后转NV12,但代码中未添加对应CapsFilter。

修复步骤

1. 修正H.264 Caps配置

移除parsed=true和stream-format=avc,让h264parse自动处理原始字节流:

GstCaps *h264_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,
        "level", G_TYPE_STRING, "4",
        NULL);

2. 调整元素结构与链接顺序

  • 移除冗余的h264filter
  • 添加约束NV12格式的CapsFilter
  • 直接给appsrc设置Caps,无需额外的CapsFilter在appsrc和解析器之间
  • 修正元素链接顺序,对齐命令行逻辑
// 添加NV12格式约束的CapsFilter
GstElement *nv12_filter = gst_element_factory_make("capsfilter", "nv12filter");
GstCaps *nv12_caps = gst_caps_new_simple("video/x-raw",
        "format", G_TYPE_STRING, "NV12",
        NULL);
g_object_set(G_OBJECT(nv12_filter), "caps", nv12_caps, NULL);
gst_caps_unref(nv12_caps);

// 给appsrc直接设置H.264 Caps
g_object_set(G_OBJECT(appsrc), "caps", h264_caps, NULL);
gst_caps_unref(h264_caps);

// 修正元素添加与链接
gst_bin_add_many(GST_BIN(pipeline), appsrc, parser, decoder, videoconvert, nv12_filter, jpegenc, appsink, NULL);
if (!gst_element_link_many(appsrc, parser, decoder, videoconvert, nv12_filter, jpegenc, appsink, NULL)) {
    g_error("Failed to link elements");
    return NULL;
}

3. 修正Blocksize参数设置

直接传入整数类型:

g_object_set(G_OBJECT(appsrc), "blocksize", (guint)fileSize, NULL);

4. 调整Appsrc流类型

单帧文件适合使用随机访问类型:

g_object_set(G_OBJECT(appsrc), "stream-type", GST_APP_STREAM_TYPE_RANDOM_ACCESS, NULL);

5. 确保数据推送流程正确

推送数据到appsrc时,需要按顺序发送流事件、段事件、数据Buffer和EOS事件:

// 发送流开始事件
GstEvent *start_event = gst_event_new_stream_start("stream-1");
gst_element_send_event(appsrc, start_event);

// 发送段事件
GstSegment segment;
gst_segment_init(&segment, GST_FORMAT_TIME);
gst_segment_set_start(&segment, GST_FORMAT_TIME, 0);
gst_segment_set_stop(&segment, GST_FORMAT_TIME, GST_CLOCK_TIME_NONE);
GstEvent *seg_event = gst_event_new_segment(&segment);
gst_element_send_event(appsrc, seg_event);

// 推送H.264数据Buffer
GstBuffer *buffer = gst_buffer_new_allocate(NULL, fileSize, NULL);
gst_buffer_fill(buffer, 0, file_data, fileSize);
gboolean ret;
g_signal_emit_by_name(appsrc, "push-buffer", buffer, &ret);
gst_buffer_unref(buffer);

// 推送EOS事件
g_signal_emit_by_name(appsrc, "end-of-stream", &ret);

内容的提问来源于stack exchange,提问作者Abdul Rehman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 00:52:01