使用 gstreamer 提取 GIF 帧
Extracting GIF frames with gstreamer
我正在尝试使用带有 AppSrc 和 AppSink 的 gstreamer 提取任何视频(包括 GIF)的帧。我在 Rust 中的最小故障管道(使用 gstreamer crate)是:
let buf = /* All in memory for the moment */;
let app_src = ElementFactory::make("appsrc", None).unwrap();
let decodebin = ElementFactory::make("decodebin", None).unwrap();
let app_sink = ElementFactory::make("appsink", None).unwrap();
let pipeline = Pipeline::new();
pipeline.add_many(&[&app_src, &decodebin, &app_sink]).unwrap();
app_src.link(&decodebin).unwrap();
let buf = GstRc::from_slice(buf).unwrap();
let app_src = app_src.downcast::<AppSrc>().unwrap();
app_src.push_buffer(buf).into_result().unwrap();
app_src.end_of_stream().into_result().unwrap();
let app_sink = app_sink.downcast::<AppSink>().unwrap();
app_sink.set_caps(Some(&Caps::from_str(&"video/x-raw")).unwrap()));
app_sink.set_sync(false);
app_sink.set_wait_on_eos(true);
let app_sink2 = app_sink.clone();
decodebin.connect_pad_added(move |decodebin, _| {
let _ = decodebin.link(&app_sink2);
});
pipeline.set_state(State::Playing).into_result().unwrap();
pipeline
.get_state(CLOCK_TIME_NONE)
.0
.into_result()
.unwrap()
/* Pull each frame through with app_sink.pull_sample() */
这适用于我测试过的各种视频甚至图像,但对于任何 GIF,它只会在 pipeline.get_state()
上出错。 GST_DEBUG=4
显示:
0:00:18.929304768 27027 0x7f48746d8050 INFO libav gstavdemux.c:1314:gst_ffmpegdemux_open:<avdemux_gif0:video_0> stream tags: taglist, video-codec=(string)"GIF\ \(Graphics\ Interchange\ Format\)";
0:00:18.929353999 27027 0x7f48746d8050 WARN libav gstavdemux.c:1603:gst_ffmpegdemux_loop:<avdemux_gif0> av_read_frame returned -5
0:00:18.929370474 27027 0x7f48746d8050 WARN libav gstavdemux.c:1590:gst_ffmpegdemux_loop:<avdemux_gif0> error: Internal data stream error.
0:00:18.929383308 27027 0x7f48746d8050 WARN libav gstavdemux.c:1590:gst_ffmpegdemux_loop:<avdemux_gif0> error: streaming stopped, reason error (-5)
0:00:18.929371274 27027 0x7f48746d8680 INFO videodecoder gstvideodecoder.c:1330:gst_video_decoder_sink_event_default:<avdec_gif0> upstream tags: taglist, video-codec=(string)"GIF\ \(Graphics\ Interchange\ Format\)";
0:00:18.929406505 27027 0x7f48746d8050 INFO GST_ERROR_SYSTEM gstelement.c:2145:gst_element_message_full_with_details:<avdemux_gif0> posting message: Internal data stream error.
0:00:18.929462537 27027 0x7f48746d8050 INFO GST_ERROR_SYSTEM gstelement.c:2172:gst_element_message_full_with_details:<avdemux_gif0> posted error message: Internal data stream error.
错误是av_read_frame returned -5
。 GST_DEBUG=5
不打印任何关于错误的更详细信息。奇怪的是,gst-launch
有效:
gst-launch-1.0 filesrc location=test.gif ! decodebin ! video/x-raw ! fakesink
运行 用 GST_DEBUG=4
并没有显示出任何令人惊讶的东西,除了没有错误。我尝试了一些不同的方法,例如在播放前进行预滚动,但我知道为什么它在这种 specific 情况下不起作用。谁能给我一些指点?
我安装了所有 gst-plugins-* 以及 gst-libav。我在 ArchLinux 上使用 gstreamer 1.14.2。
对于遇到类似问题的任何人:GIF 解码仅适用于基于拉取的 AppSrc。 GIF 似乎是唯一不适用于基于推送的 AppSrc API 的流行网络格式(如 jpg、png、webms、mp4 等)。
我正在尝试使用带有 AppSrc 和 AppSink 的 gstreamer 提取任何视频(包括 GIF)的帧。我在 Rust 中的最小故障管道(使用 gstreamer crate)是:
let buf = /* All in memory for the moment */;
let app_src = ElementFactory::make("appsrc", None).unwrap();
let decodebin = ElementFactory::make("decodebin", None).unwrap();
let app_sink = ElementFactory::make("appsink", None).unwrap();
let pipeline = Pipeline::new();
pipeline.add_many(&[&app_src, &decodebin, &app_sink]).unwrap();
app_src.link(&decodebin).unwrap();
let buf = GstRc::from_slice(buf).unwrap();
let app_src = app_src.downcast::<AppSrc>().unwrap();
app_src.push_buffer(buf).into_result().unwrap();
app_src.end_of_stream().into_result().unwrap();
let app_sink = app_sink.downcast::<AppSink>().unwrap();
app_sink.set_caps(Some(&Caps::from_str(&"video/x-raw")).unwrap()));
app_sink.set_sync(false);
app_sink.set_wait_on_eos(true);
let app_sink2 = app_sink.clone();
decodebin.connect_pad_added(move |decodebin, _| {
let _ = decodebin.link(&app_sink2);
});
pipeline.set_state(State::Playing).into_result().unwrap();
pipeline
.get_state(CLOCK_TIME_NONE)
.0
.into_result()
.unwrap()
/* Pull each frame through with app_sink.pull_sample() */
这适用于我测试过的各种视频甚至图像,但对于任何 GIF,它只会在 pipeline.get_state()
上出错。 GST_DEBUG=4
显示:
0:00:18.929304768 27027 0x7f48746d8050 INFO libav gstavdemux.c:1314:gst_ffmpegdemux_open:<avdemux_gif0:video_0> stream tags: taglist, video-codec=(string)"GIF\ \(Graphics\ Interchange\ Format\)";
0:00:18.929353999 27027 0x7f48746d8050 WARN libav gstavdemux.c:1603:gst_ffmpegdemux_loop:<avdemux_gif0> av_read_frame returned -5
0:00:18.929370474 27027 0x7f48746d8050 WARN libav gstavdemux.c:1590:gst_ffmpegdemux_loop:<avdemux_gif0> error: Internal data stream error.
0:00:18.929383308 27027 0x7f48746d8050 WARN libav gstavdemux.c:1590:gst_ffmpegdemux_loop:<avdemux_gif0> error: streaming stopped, reason error (-5)
0:00:18.929371274 27027 0x7f48746d8680 INFO videodecoder gstvideodecoder.c:1330:gst_video_decoder_sink_event_default:<avdec_gif0> upstream tags: taglist, video-codec=(string)"GIF\ \(Graphics\ Interchange\ Format\)";
0:00:18.929406505 27027 0x7f48746d8050 INFO GST_ERROR_SYSTEM gstelement.c:2145:gst_element_message_full_with_details:<avdemux_gif0> posting message: Internal data stream error.
0:00:18.929462537 27027 0x7f48746d8050 INFO GST_ERROR_SYSTEM gstelement.c:2172:gst_element_message_full_with_details:<avdemux_gif0> posted error message: Internal data stream error.
错误是av_read_frame returned -5
。 GST_DEBUG=5
不打印任何关于错误的更详细信息。奇怪的是,gst-launch
有效:
gst-launch-1.0 filesrc location=test.gif ! decodebin ! video/x-raw ! fakesink
运行 用 GST_DEBUG=4
并没有显示出任何令人惊讶的东西,除了没有错误。我尝试了一些不同的方法,例如在播放前进行预滚动,但我知道为什么它在这种 specific 情况下不起作用。谁能给我一些指点?
我安装了所有 gst-plugins-* 以及 gst-libav。我在 ArchLinux 上使用 gstreamer 1.14.2。
对于遇到类似问题的任何人:GIF 解码仅适用于基于拉取的 AppSrc。 GIF 似乎是唯一不适用于基于推送的 AppSrc API 的流行网络格式(如 jpg、png、webms、mp4 等)。