使用 ffmpeg 精确查找

Tar*_*nko 5 c audio ffmpeg

假设我有一个正在解码的音频文件ffmpeg。源格式类似于AAC将音频拆分为数据包的地方。当寻找特定时间时,很明显,大多数情况下,时间不会落在数据包边界上,而是落在数据包持续时间内的某处。我必须自己在数据包中寻找还是av_seek_frame自己完成这一切并设置解码,以便下一个解码的帧应该从我请求的位置开始?

如果我将函数av_seek_frame与 flag 一起使用AVSEEK_FLAG_BACKWARD,我假设av_read_frame返回的下一个数据包将是包含我正在寻找的时间位置的数据包。那正确吗?

如果我使用avcodec_decode_audio4解码这个数据包,返回的帧是否包含数据包开始时的音频数据,或者从我传递到av_seek_frame的时间开始?在后一种情况下,我如何找出帧/数据包时间戳以估计解码帧中要跳过的样本数?在PTS寻求后是零,DTS看起来无用要么。

是否可以使用 精确搜索特定时间ffmpeg

Tar*_*nko 6

是的,源代码确认av_seek_frame确实搜索到数据包边界。

为了在数据包内寻找,我使用 AVStream::cur_dts 时间戳,该时间戳由av_seek_frame更新以告诉它所寻找的边界。通过该值,我们可以找出数据包中要跳过的剩余样本数。这样就解决了问题。


Ron*_*tje 5

ffmpeg 中没有帧精确或音频样本精确搜索,这是应用程序级问题。原因很简单:libavformat 进行查找,并且它不知道各个解复用器返回的数据包内有什么。它只有一个带有时间戳 X 和持续时间 Y 的数据块。它对这些数据一无所知,你必须解码数据才能用它做任何有意义的事情,这是 libavcodec,而不是 libvformat。

因此,回答您的问题: av_seek_frame 寻求数据包边界,AVSEEK_FLAG_BACKWARD 意味着数据包将严格位于给定 ts 之前;对于音频,这意味着数据包很可能包含您的时间戳。然而,情况并非总是如此,因为一些解复用器基于索引进行搜索,并且并非每个数据包都可能具有索引条目。在查找后到达包含指定时间戳的数据包之前,您可能需要多次调用 av_read_frame()。

除了调用 avcodec_flush() 之外,libavcodec 不知道任何有关查找的信息,因此下一次调用 avcodec_decode_audio4 的输出将从输入数据包的开头开始。对于特定样本的搜索,应用程序必须自行删除领先样本。

  • 我同意记录下来可能会有用。您应该提交补丁。:-)。至于为什么我们没有记录它,你必须明白多媒体实际上有数万亿个特殊情况规则或像这样令人讨厌的行为,不是因为我们 - 作为 ffmpeg 开发人员 - 想要令人恼火,而是因为这项技术非常不统一,需要针对各种情况的特殊情况才能进行工作。我们可以让它根本不起作用或者记录所有特殊情况,但这会更令人困惑。了解您的技术堆栈。:-)。 (3认同)
  • 我部分同意框架精确搜索是一个应用程序级问题。由于它可以在多种编解码器/格式上使用,因此 ffmpeg 至少可以改进“av_seek_frame”的文档,指定在“AVPacket”dts 上执行查找。这很令人困惑,因为帧索引是一个与表示相关的概念。 (2认同)
  • 查找并不总是在 dts 上执行,它实际上取决于容器。如果容器时间戳为 pts,则查找以 pts 为单位;如果容器时间戳是 dts,则在 dts 中查找。 (2认同)
  • 那么它也应该被记录下来。相反,“av_seek_frame”的文档几乎没有提供任何细节。如何可靠地确定容器时间戳是否在 pts 或 dts 中打开? (2认同)