FFMPEG寻求带来音频伪像

我正在使用ffmpeg实现音频解码器。 在阅读音频甚至寻找已经有效的时候,我无法找到一种方法来清除缓冲区后寻求所以当应用程序在搜索后立即开始读取音频时我没有任何文物。

avcodec_flush_buffers似乎对内部缓冲区没有任何影响。 所有解码器(mp3,aac,wma,…)都会出现此问题,但PCM / WAV(由于未压缩音频,因此不使用内部缓冲区来保存数据以进行解码)。

代码片段很简单:

av_seek_frame(audioFilePack->avContext, audioFilePack->stream, posInTimeFrame, AVSEEK_FLAG_ANY); avcodec_flush_buffers(audioFilePack->avContext->streams[audioFilePack->stream]->codec); 

解释:

 audioFilePack->avContext = FormatContext audioFilePack->stream = Stream Position (also used to read audio packets) audioFilePack->avContext->streams[audioFilePack->stream]->codec = CodecContext for the codec used 

关于我应该做什么的任何想法,我可以寻求并获得没有剩余音频? 谢谢!

这是ffmpeg中的一个错误。 内部缓冲区没有被刷新,因此当您在刷新后获取数据包/帧时,您将获得预搜索数据。 它似乎是固定的3-16-12,所以你可以自己合并此修复程序,或升级ffmpeg。

http://permalink.gmane.org/gmane.comp.video.libav.devel/23455

作为更新,上面的错误确实是一个问题,但是AAC的第二个错误是具体的。

截至五个月前,另一位用户发现了这个错误,并且据报道已修复。 https://ffmpeg.org/trac/ffmpeg/ticket/420

修复程序是一个刷新函数添加到aacdec.c,它清除其内部缓冲区。 问题是aacdec.c中定义了两个解码器,只有一个给出了flush函数指针。 如果您使用其他(更常见的)解码器,它仍然无法正确清除。

如果您自己构建ffmpeg,修复方法是将.flush = flush添加到AVCodec ff_aac_decoder(位于文件底部)定义的底部。

我会让ffmpeg家伙知道,所以希望它可以包含在主分支中。

我从来没有写过具有搜索能力的音频播放器,但我怀疑是这样的。 每个音频包解码成原始声波的片段。 通常,这些片段顺序地彼此邻接,结果是连续波,其中一个听到的是没有伪影的音频。 当您寻找时,您强制从文件的不同部分的两个片段相互邻接。 这通常会在产生的声波中引入不连续性,耳朵会将其视为咔嗒声或砰砰声,或者您称之为(我猜测)是一种神器。

这是一个更具体的例子。 我们假设你在寻找之前已经播放了前25个音频包。 假设数据包25解码成最后一个样本为12345的波。当数据包25被渲染到扬声器时,你寻找数据包66.假设数据包66的第一个样本是-23456。 因此,数字音频流在搜索中从12345跳到-23456。 这是一个巨大的不连续性,并将作为流行音乐听到。

我认为一种解决方案是在开始搜索之前获取一个额外的数据包(在我的示例中为数据包26),将其解码为脱机缓冲区,应用淡出,然后将其放入回放队列。 找到想要的位置后,取第一个数据包(我的eaxmple中的66个),将其解码到另一个离线缓冲区,应用淡入,然后将其放入回放队列。 这应该确保平滑的声波和无伪影的搜索。

如果你聪明,你可以根据自己的需要做出淡出或淡出的时间。 我认为只需几毫秒就足以防止出现伪影。 您甚至可以应用旧包和新包的交叉淡入淡出。 在搜索之前仅注意最后一个数据包中的最后一个样本值也可能就足够了,并且在几个样本上逐渐将其降低到零,而不是立即将其拉到零。 这可能比解码额外数据包更容易。

这是我对如何解决这个问题的猜测。 这显然是一个已经解决的问题,所以我鼓励你也看一下开源音频播放器,看看它们是如何实现搜索的。 像Audacity,Totem,Banshee,RhythmBox,Amarok或VLC这样的程序,或像GStreamer这样的框架可能是值得学习的好例子。 如果您发现他们采用了显着的技术,请在此处报告主题。 我想人们会想要了解它们是什么。 祝好运!