我有一个文件(可能就是这样mplayer -identify
说的)H264-ES流。
它可以使用以下gstreamer
管道播放:
gst-launch-1.0 filesrc location=vid.H264 ! h264parse ! avdec_h264 ! autovideosink
(我autovideosink
在示例中使用,但管道要复杂得多 - 这是“最小的工作示例”)它播放得非常快,可能与我的 CPU 允许的一样快。如果我使用任何需要时间戳的元素,它会失败,因为流具有 framerate 0/1
。
我认为流根本不包含任何帧速率信息。
看:
$ mplayer -identify vid.H264 2>&1 | grep -i fps
FPS not specified in the header or invalid, use the -fps option.
ID_VIDEO_FPS=0.000
我知道正确的帧率应该是多少(假设它是 25fps),并且我希望能够将正确的时间戳放入视频帧或设置正确的流帧率。
我尝试了什么:
我想我可以用videorate
这个:
gst-launch-1.0 filesrc location=vid.H264 ! h264parse ! avdec_h264 \
! videorate ! video/x-raw,framerate=25/1 ! autovideosink
但我错了 -videorate
尝试将传入的流转换为固定的帧速率,有时它看起来像我想要的那样工作,但是当下游的任何元素有最轻微的延迟时,它会产生“冻结帧”视频 - 许多重复的帧 -所以我想我可以使用drop-only=true
选项,但它根本不起作用:
$ GST_DEBUG=3 gst-launch-1.0 filesrc location=vid.H264 ! h264parse ! avdec_h264 \
! videorate drop-only=true ! video/x-raw,framerate=25/1 ! autovideosink
Setting pipeline to PAUSED ...
0:00:00.030550249 31831 0x2094e10 WARN basesrc gstbasesrc.c:3470:gst_base_src_start_complete:<filesrc0> pad not activated yet
Pipeline is PREROLLING ...
0:00:00.044233138 31831 0x207d450 WARN libav gstavcodecmap.c:2408:gst_ffmpeg_caps_to_pixfmt: ignoring insane framerate 1/0
0:00:00.045314795 31831 0x207d450 WARN GST_PADS gstpad.c:3742:gst_pad_peer_query:<avdec_h264-0:src> could not send sticky events
0:00:00.070760684 31831 0x207d450 WARN baseparse gstbaseparse.c:3262:gst_base_parse_loop:<h264parse0> error: streaming stopped, reason not-negotiated
ERROR: from element /GstPipeline:pipeline0/GstH264Parse:h264parse0: GStreamer encountered a general stream error.
Additional debug info:
gstbaseparse.c(3262): gst_base_parse_loop (): /GstPipeline:pipeline0/GstH264Parse:h264parse0:
streaming stopped, reason not-negotiated
ERROR: pipeline doesn't want to preroll.
Setting pipeline to NULL ...
Freeing pipeline ...
问题在于avdec_h264
-videorate
它不接受framerate=0/1
大写字母。
我认为我需要的是(想象中的管道):
$ GST_DEBUG=3 gst-launch-1.0 filesrc location=vid.H264 ! h264parse ! avdec_h264 \
! force_timestamps framerate=25/1 ! autovideosink
恐怕我必须force_timestamps
自己写元素,但因为我之前确实写过一些元素,这是我做过的最困难和最不愉快的事情之一,如果可能的话,我宁愿使用现有的元素。
所以我的问题是:
是否有某种方法(最好使用现有元素)以某些固定帧速率强制视频帧(或 gstreamer 缓冲区)上的时间戳?