【问题标题】:ffmpeg decoder seems to drop framesffmpeg 解码器似乎丢帧
【发布时间】:2018-01-15 17:03:45
【问题描述】:

我正在使用 avcodec (c++) api 来解码视频文件帧并处理它们。我注意到解码的帧数少于预期\实际的帧数。相差16帧。 虽然 x 帧是用 ffmpeg 解码的,但 VirtualDub 说同一个文件有 x+16 帧。 使用 ffprobe,我看到该文件包含 x 帧:

$ ffprobe -v error -count_frames -select_streams v:0   -show_entries stream=nb_read_frames -of default=nokey=1:noprint_wrappers=1 inputFile.avi
10875

此外,当我尝试使用 ffmpeg 实用程序提取 x+1 帧时,我遇到了失败:

$  ffmpeg -i inputFile.avi -vf "select=eq(n\,10875)" -vframes 1 outPic.jpg
ffmpeg version N-80801-gc0cb53c Copyright (c) 2000-2016 the FFmpeg developers
  built with gcc 5.4.0 (GCC)
  configuration: --enable-gpl --enable-version3 --disable-w32threads --enable-dxva2 --enable-libmfx --enable-nvenc --enable-avisynth --enable-bzlib --enable-fontconfig --enable-frei0r --enable-gnutls --enable-iconv --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libfreetype --enable-libgme --enable-libgsm --enable-libilbc --enable-libmodplug --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-librtmp --enable-libschroedinger --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvo-amrwbenc --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxavs --enable-libxvid --enable-libzimg --enable-lzma --enable-decklink --enable-zlib
  libavutil      55. 27.100 / 55. 27.100
  libavcodec     57. 48.101 / 57. 48.101
  libavformat    57. 40.101 / 57. 40.101
  libavdevice    57.  0.102 / 57.  0.102
  libavfilter     6. 46.102 /  6. 46.102
  libswscale      4.  1.100 /  4.  1.100
  libswresample   2.  1.100 /  2.  1.100
  libpostproc    54.  0.100 / 54.  0.100
Input #0, avi, from 'inputFile.avi':
  Metadata:
    comment         : Recorder-v2
    encoder         : Lavf57.40.101
  Duration: 00:18:09.10, start: 0.000000, bitrate: 3421 kb/s
    Stream #0:0: Video: mpeg4 (Simple Profile) (xvid / 0x64697678), yuv420p, 1280x960 [SAR 1:1 DAR 4:3], 3420 kb/s, 10 fps, 10 tbr, 10 tbn, 10 tbc
[swscaler @ 00000000021100a0] deprecated pixel format used, make sure you did set range correctly
[image2 @ 0000000001f10540] Using AVStream.codec to pass codec parameters to muxers is deprecated, use AVStream.codecpar instead.
Output #0, image2, to 'outPic.jpg':
  Metadata:
    comment         : Recorder-v2
    encoder         : Lavf57.40.101
    Stream #0:0: Video: mjpeg, yuvj420p(pc), 1280x960 [SAR 1:1 DAR 4:3], q=2-31, 200 kb/s, 10 fps, 10 tbn, 10 tbc
    Metadata:
      encoder         : Lavc57.48.101 mjpeg
    Side data:
      cpb: bitrate max/min/avg: 0/0/200000 buffer size: 0 vbv_delay: -1
Stream mapping:
  Stream #0:0 -> #0:0 (mpeg4 (native) -> mjpeg (native))
Press [q] to stop, [?] for help
frame=    0 fps=0.0 q=0.0 Lsize=N/A time=00:00:00.00 bitrate=N/A speed=   0x
video:0kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown
Output file is empty, nothing was encoded (check -ss / -t / -frames parameters if used)

有趣和奇怪的部分是,将这部电影的所有帧按顺序保存会产生 x+16 个文件(VirutalDub 声称的帧数相同):

$ ffmpeg -i inputFile.avi "frames/out-%03d.jpg"
ffmpeg version N-80801-gc0cb53c Copyright (c) 2000-2016 the FFmpeg developers
  built with gcc 5.4.0 (GCC)
  configuration: --enable-gpl --enable-version3 --disable-w32threads --enable-dxva2 --enable-libmfx --enable-nvenc --enable-avisynth --enable-bzlib --enable-fontconfig --enable-frei0r --enable-gnutls --enable-iconv --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libfreetype --enable-libgme --enable-libgsm --enable-libilbc --enable-libmodplug --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-librtmp --enable-libschroedinger --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvo-amrwbenc --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxavs --enable-libxvid --enable-libzimg --enable-lzma --enable-decklink --enable-zlib
  libavutil      55. 27.100 / 55. 27.100
  libavcodec     57. 48.101 / 57. 48.101
  libavformat    57. 40.101 / 57. 40.101
  libavdevice    57.  0.102 / 57.  0.102
  libavfilter     6. 46.102 /  6. 46.102
  libswscale      4.  1.100 /  4.  1.100
  libswresample   2.  1.100 /  2.  1.100
  libpostproc    54.  0.100 / 54.  0.100
Input #0, avi, from 'inputFile.avi':
  Metadata:
    comment         : Recorder-v2
    encoder         : Lavf57.40.101
  Duration: 00:18:09.10, start: 0.000000, bitrate: 3421 kb/s
    Stream #0:0: Video: mpeg4 (Simple Profile) (xvid / 0x64697678), yuv420p, 1280x960 [SAR 1:1 DAR 4:3], 3420 kb/s, 10 fps, 10 tbr, 10 tbn, 10 tbc
[swscaler @ 00000000020600a0] deprecated pixel format used, make sure you did set range correctly
[image2 @ 0000000001d20540] Using AVStream.codec to pass codec parameters to muxers is deprecated, use AVStream.codecpar instead.
Output #0, image2, to 'frames/out-%03d.jpg':
  Metadata:
    comment         : Recorder-v2
    encoder         : Lavf57.40.101
    Stream #0:0: Video: mjpeg, yuvj420p(pc), 1280x960 [SAR 1:1 DAR 4:3], q=2-31, 200 kb/s, 10 fps, 10 tbn, 10 tbc
    Metadata:
      encoder         : Lavc57.48.101 mjpeg
    Side data:
      cpb: bitrate max/min/avg: 0/0/200000 buffer size: 0 vbv_delay: -1
Stream mapping:
  Stream #0:0 -> #0:0 (mpeg4 (native) -> mjpeg (native))
Press [q] to stop, [?] for help
frame=10891 fps=120 q=24.8 Lsize=N/A time=00:18:09.10 bitrate=N/A dup=16 drop=0 speed=  12x
video:384325kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown

计数的文件/帧数:

$ ls -l frames/* | wc -l
    10891

我在这里几乎迷路了。任何线索为什么 avcodec 解码 x 帧而不是 x+16? ffmpeg 是否会丢失帧? VirtualDub 是否可能重复 (16) 帧?

谢谢

【问题讨论】:

  • 这个视频有纯黑框吗?
  • 我不知道

标签: c++ ffmpeg libavcodec virtualdub


【解决方案1】:
  1. 您可能会在发送最后一帧后忘记刷新编码器。
  2. 或者您可能忘记在写入帧之前重新调整时间戳:

    av_packet_rescale_ts(&pkt, codec_context->time_base, stream->time_base);
    

【讨论】:

    【解决方案2】:

    可能的原因是“丢帧”,您可以使用 VirtualDub 热键“开始 -> 下一个丢帧”来检查。 FFmpeg 不会将它们视为独立帧,但您可以注意到时间码的跳跃。

    【讨论】:

    • 是的,就是这样!看起来 Vdub 通过填充最后一帧的副本来“完成”掉帧。此外,ffmpeg 在转储所有帧时可以模仿这种行为: ffmpeg -i inFile.avi "%03d.jpg"
    • 有谁知道一种方法来告诉 ffmpeg 使用 avcodec (c++) api 来填充有“洞”的重复帧,比如 virtualDub?例如,在 ffmpeg 实用程序中,它可以使用 '-vsync cfr' 开关来制作,但我需要在我的解码 c++ 代码中这样做谢谢
    • afaik 没有简单的开关。您可以观察 pts 中的空白并自己插入重复项。顺便说一句,这是在我的基于 ffmpeg 的 virtualdub 驱动程序中实现的 sourceforge.net/p/vdfiltermod/cch_input/ci/master/tree
    猜你喜欢
    • 2015-05-19
    • 2011-09-29
    • 2018-03-16
    • 2011-09-01
    • 2014-05-09
    • 1970-01-01
    • 2012-07-05
    • 2012-03-12
    • 2013-08-28
    相关资源
    最近更新 更多