如何使用gst-launchgstreamer将.mp4文件转换为不丢失帧的.yuv原始视频i420?

问题描述

我在gstreamer截断gst启动管道的yuv输出时遇到问题。简化的例子是

gst-launch-1.0 filesrc location="$input" \
               ! decodebin \
               ! 'video/x-raw,format=I420' \
               ! rawvideoparse \
               ! filesink location="$output" buffer-mode=2

当我在7680x3840的H.264视频的MP4文件上运行600帧时,它给我的文件长6280934400字节。快速算术6280934400/7680/3840/600 = 0.3549609375。每个像素大约占一个字节的三分之一。

Setting pipeline to PAUSED ...
0:00:00.354592385 16438 0x555e06766b30 WARN                 basesrc gstbasesrc.c:3600:gst_base_src_start_complete:<filesrc0> pad not activated yet
Pipeline is prerollING ...
0:00:00.536788393 16438 0x7f3f90073680 WARN                 qtdemux qtdemux_types.c:239:qtdemux_type_get: unkNown QuickTime node type uuid
0:00:00.536830878 16438 0x7f3f90073680 WARN                 qtdemux qtdemux.c:3237:qtdemux_parse_trex:<qtdemux0> Failed to find fragment defaults for stream 1
0:00:00.536861715 16438 0x7f3f90073680 WARN                 qtdemux qtdemux.c:3237:qtdemux_parse_trex:<qtdemux0> Failed to find fragment defaults for stream 2
Redistribute latency...
Redistribute latency...
Pipeline is prerollED ...
Setting pipeline to PLAYING ...
New clock: GstSystemClock
0:01:11.471563917 16438 0x7f3f8000d4a0 WARN                   libav gstavauddec.c:628:gst_ffmpegauddec_drain:<avdec_aac0> send packet Failed,Could not drain decoder
Got EOS from element "pipeline0".
Execution ended after 0:01:10.085660675
Setting pipeline to PAUSED ...
Setting pipeline to READY ...
Setting pipeline to NULL ...
Freeing pipeline ...

我期望每个像素1.5个字节(因为format = I420)。

如果我改为运行ffmpeg -i $input -c:v rawvideo -pix_fmt yuv420p $output,则会得到26542080000字节,如预期的那样是7680 * 3840 * 600 * 1.5。

我的目标管道比这要复杂得多(使用GLSL进行投影重映射),但是我希望,如果有人可以修复此琐碎的示例,那么它也将修复我的真实管道。

我该如何建立一个gst启动管道,以将文件正确转换为原始视频,而又不会地放弃整个工作的20%?

解决方法

我认为:

gst-launch-1.0 filesrc location="$input" \
               ! decodebin \
               ! filesink location="$output"

应该足够了。由于默认情况下解码器应输出I420(除非它是特殊配置文件)。之后无需解析数据(实际上可能是问题的根源,因为该元素的内部宽度和高度属性设置为320x240)。您只想将来自解码器的内容转储到磁盘。