我正在开发一个项目,需要用单帧解码 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.
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);