Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/160.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ FFMPEG搜索带来音频伪影_C++_C_Audio_Ffmpeg_Seek - Fatal编程技术网

C++ FFMPEG搜索带来音频伪影

C++ FFMPEG搜索带来音频伪影,c++,c,audio,ffmpeg,seek,C++,C,Audio,Ffmpeg,Seek,我正在使用ffmpeg实现一个音频解码器。 当读取音频甚至搜索已经开始工作时,我想不出在搜索后清除缓冲区的方法,所以当应用程序在搜索后立即开始读取音频时,我没有任何瑕疵 avcodec\u flush\u缓冲区似乎对内部缓冲区没有任何影响。此问题发生在所有解码器(mp3、aac、wma等)上,但PCM/WAV(由于音频未压缩,因此不使用内部缓冲区保存数据进行解码)除外 代码片段很简单: av_seek_frame(audioFilePack->avContext, audioFilePac

我正在使用ffmpeg实现一个音频解码器。 当读取音频甚至搜索已经开始工作时,我想不出在搜索后清除缓冲区的方法,所以当应用程序在搜索后立即开始读取音频时,我没有任何瑕疵

avcodec\u flush\u缓冲区
似乎对内部缓冲区没有任何影响。此问题发生在所有解码器(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
我该怎么做才能找到并没有残留音频,有什么想法吗?
谢谢

我从未编写过具有搜索功能的音频播放器,但我怀疑是这样的。每个音频包解码成一段原始声波。通常情况下,这些片段顺序地彼此邻接,结果是一个连续波,人们听到的声音没有任何瑕疵。搜索时,强制文件中不同部分的两个片段彼此相邻。这通常会在产生的声波中引入不连续性,耳朵会将其视为咔嗒声或砰砰声,或者你称之为(我猜)人工制品

这里有一个更具体的例子。假设您在搜索之前播放了前25个音频包。假设包25解码成最后一个样本为12345的波。当数据包25呈现给演讲者时,您寻求数据包66。假设66包的第一个样本是-23456。因此,数字音频流在搜索过程中从12345跳到-23456。这是一个巨大的间断,将作为流行音乐被听到

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

如果你很聪明,你可以使淡出和淡入尽可能短或长。我认为只有几毫秒的时间应该足以防止伪影。您甚至可以应用新旧数据包的交叉淡入淡出。在搜索之前,只记下最后一个数据包中的最后一个样本值,然后在几个样本上逐渐将其降为零,而不是立即将其降为零,这可能就足够了。这可能比解码额外的数据包更容易


这是我对如何解决这个问题的猜测。这显然是一个已解决的问题,所以我鼓励您也看看开源音频播放器,看看它们是如何实现seeking的。像Audacity、Totem、Banshee、RhythmBox、Amarok或VLC这样的程序,或者像GStreamer这样的框架,都是值得学习的好例子。如果你发现他们使用了显著的技巧,请在这里报告主题。我想人们会想知道他们是什么。祝你好运

这是ffmpeg中的一个bug。内部缓冲区没有被刷新,因此当您在刷新后获取数据包/帧时,您将获取预寻道数据。它似乎在2012年3月16日已修复,因此您可以自己合并此修复,或升级ffmpeg

作为更新,上面的bug确实是一个问题,但是AAC还有第二个bug

五个月前,另一个用户发现了这个bug,据报道已经修复。

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

如果您能够自己构建ffmpeg,那么解决方法是添加 .flush=flush, 至AVCodec ff_aac_解码器定义的底部(位于文件底部)


我会让ffmpeg的人知道,希望它能被包括在主分支中。

请,没有想法吗?我试图修复这几乎两个星期没有任何关于什么可能导致这一点的想法。。。它应该按原样工作吗?消息还发送到ffmpeg用户官方邮件列表。仍然需要帮助。您能更详细地描述工件吗?它们是咔嗒咔嗒声还是砰嗒咔嗒声?所以原始海报希望能看到这一点非常感谢!我将重新编译它,并放弃我的替代方式。。。这是丑陋的,但工作。。。