Filter ffmpeg中的比特流过滤器是什么?

Filter ffmpeg中的比特流过滤器是什么?,filter,ffmpeg,bitstream,Filter,Ffmpeg,Bitstream,经过仔细阅读,我仍然不明白他们到底是为了什么 该文档说明过滤器: 在不执行解码的情况下执行比特流级修改 有人能进一步向我解释一下吗?用例将极大地澄清问题。此外,还有明显不同的过滤器。它们有何不同?让我举例说明。FFmpeg视频解码器通常通过将每次调用的一个视频帧转换为avcodec_decode_video2来工作。因此,预计输入的是相当于“一个图像”的比特流数据。让我们考虑这个问题,从一个文件(一个字节的磁盘数组)到一秒钟的图像。 对于“原始”(附录B)H264(.H264/.bin/.264

经过仔细阅读,我仍然不明白他们到底是为了什么

该文档说明过滤器:

在不执行解码的情况下执行比特流级修改


有人能进一步向我解释一下吗?用例将极大地澄清问题。此外,还有明显不同的过滤器。它们有何不同?

让我举例说明。FFmpeg视频解码器通常通过将每次调用的一个视频帧转换为avcodec_decode_video2来工作。因此,预计输入的是相当于“一个图像”的比特流数据。让我们考虑这个问题,从一个文件(一个字节的磁盘数组)到一秒钟的图像。 对于“原始”(附录B)H264(.H264/.bin/.264文件),单个nal单元数据(sps/pps头比特流或cabac编码的帧数据)以nal单元序列连接,中间有一个起始代码(00 00 01 XX),其中XX是nal单元类型。(为了防止nal数据本身包含00 01数据,它是RBSP转义的。)因此a可以简单地在开始代码标记处剪切文件。它们搜索以00 01开始并包括00 01的连续数据包,直到并排除下一次出现的00 01。然后,它们解析nal单元类型和切片报头,以找到每个数据包属于哪个帧,并将组成一个帧的一组nal单元作为输入返回给数据包

但.mp4文件中的H264数据不同。您可以想象,如果muxing格式中已经有长度标记,那么00 01开始代码可以被认为是冗余的,mp4就是这样。因此,为了每帧节省3个字节,它们删除了00 01前缀。他们还将PPS/SPS放在文件头中,而不是在第一帧前加上前缀,而且这些文件也缺少00 01前缀。所以,如果我把它输入h264解码器,它需要所有nal单元的前缀,它就不会工作了。比特流过滤器通过识别文件头的提取部分中的pps/SP(ffmpeg称之为“extradata”)来解决这一问题,使用起始码从单个帧包中预编此和每个nal,并在将其输入h264解码器之前将其连接回一起

您现在可能会觉得“解析器”和“比特流过滤器”之间有着非常细微的区别。这是真的。我认为官方定义是解析器获取一系列输入数据并将其拆分为帧,而不丢弃任何数据或添加任何数据。解析器所做的唯一事情就是更改数据包边界。另一方面,允许位流过滤器实际修改数据。我不确定这个定义是否完全正确(参见下面的vp9),但这是概念上mp4toannexb是BSF而不是解析器的原因(因为它添加了00 01前缀)

其他情况下,此类“比特流调整”有助于保持解码器的简单和统一,但允许我们支持所有碰巧存在于野外的文件变体:

  • mpeg4(divx)(为了获得像IBP这样的B帧序列,在AVI中编码为IPB,并获得正确的时间戳,人们提出了B帧打包的概念,其中I-B-P/I-P-B打包在帧中,即第三个包是空的,第二个包有两个帧。这意味着在解码阶段与P和B帧关联的时间戳是正确的。It还意味着一个数据包有两帧的输入数据,这违反了ffmpeg的一帧入一帧出的概念,因此我们编写了一个bsf将数据包拆分为两个,同时删除表示数据包包含两个帧的标记,因此是一个bsf而不是解析器,然后再将其输入到解码器中VP9也做同样的事情(称为超帧),但在中拆分帧,因此解析器/BSF拆分在理论上并不总是完美的;也许VP9应该称为BSF)
  • hevc mp4至附录B的转换(同上,但适用于hevc)
  • aac转换(与h264/hevc附录B与mp4基本相同,但适用于aac音频)

请注意,比特流过滤器和解析器不同于常规视频和音频过滤器,因为它们对编码(正常压缩)的比特流进行操作,而常规视频和音频过滤器对未压缩的视频和音频进行操作。与mark4o所说的类似,请注意,当运行ffmpeg而不执行streamcopy时(即,实际转码视频)比特流过滤器在重新编码后应用。比特流过滤器是否与流提取有关?例如,它们是否有助于更快地从视频容器中提取字幕或音频流?有(或如何)此类信息可以[正式]找到?经过很长时间的搜索后得出了这个答案。几乎所有的解组/解码示例都不包括比特流过滤和数据包解析。我非常困惑于这样一个事实,即我必须为我能遇到的每种可能的视频格式找出一些特殊的技巧——而我正试图使用ffmpeg“为你照顾所有的辛苦工作”只是为了避免所有这些东西…(我的背景:我正在尝试用ffmpeg分解视频文件,并将帧数据传递给NVDEC进行解码)如果您使用ffmpeg工具或标准的libavformat/avcodec API,它将为您解决这一问题。在使用正式的read_frame()和send_packet()时,会自动插入位流过滤器并自动使用解析器但是,如果您使用自己的解复用器,则需要确保解复用器的输出格式与解码器的预期输入格式相同,这就是为什么还会公开各个BSF/解析器API的原因。