2011-11-03 71 views
6

我正在使用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 

上我應該做的,所以我可以尋求和獲得無殘留的音頻任何想法? 謝謝!

+0

請問,沒有想法?我試圖解決這個問題近2個星期沒有任何想法可能會導致這種情況...應該如何工作? –

+0

消息也發送到ffmpeg用戶的官方郵件列表。幫助仍然需要。 –

+0

你能更詳細地描述工件嗎?他們是否點擊並彈出? –

回答

3

我從來沒有寫過一個具有搜索功能的音頻播放器,但我懷疑正在發生的是這樣的。每個音頻包都解碼成原始聲波的片段。通常情況下,這些片段依次彼此相鄰,結果是連續的波形,這種波形聽起來沒有任何僞影。當你尋求時,你強迫文件的不同部分的兩個片段彼此鄰接。這通常會在所產生的聲波中引入一個不連續性,耳朵會將其視爲咔嗒聲或流行音樂,或者當您稱之爲(我猜測)一個神器時。

下面是一個更具體的例子。假設您在尋找之前播放了前25個音頻包。假設數據包25解碼爲最後一個樣本爲12345的波形。當數據包25正在呈現給揚聲器時,您尋找數據包66.假設數據包66的第一個樣本是-23456。因此,數字音頻流在搜索中從12345跳到-23456。這是一個巨大的不連續性,並將作爲流行音樂被聽到。

我認爲一種解決方案是在開始尋找之前抓取一個額外的數據包(在我的示例中爲數據包26),將其解碼爲離線緩衝區,應用淡出,然後將其放入播放隊列。在你尋找你想要的位置之後,取第一個數據包(我的eaxmple中的66),將它解碼到另一個離線緩衝區,應用淡入,然後將它放入回放隊列。這應該確保平穩的聲波和無僞影尋找。

如果您很聰明,可以根據需要將淡出和淡入淡入或淡入。我認爲只有幾毫秒應該足以防止失真。您甚至可以應用舊數據包和新數據包的交叉淡入淡出。在查找之前僅記下最後一個數據包中的最後一個樣本值就足夠了,並且在幾個樣本上逐漸降低到零,而不是立即將其拉到零。這可能比解碼額外的數據包更容易。

這是我對這個問題如何解決的猜測。這顯然是一個解決的問題,所以我鼓勵你也看看開放源代碼的音頻播放器,看看它們如何實現尋找。 Audacity,Totem,Banshee,RhythmBox,Amarok或VLC等程序或GStreamer等框架可能是很好的例子。如果你發現他們採用了顯着的技術,請在這裏報告主題。我想人們會想知道他們是什麼。祝你好運!

3

這是ffmpeg中的一個bug。內部緩衝區沒有被刷新,因此當你在沖洗後得到一個數據包/幀時,你會得到預搜索數據。它似乎是固定的3-16-12,所以你可以自己加入這個修復,或升級ffmpeg。

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

作爲更新,錯誤上面確實是一個問題,但有一個與AAC第二錯誤特別。

從五個月前,另一個用戶發現了這個錯誤,據報道它是固定的。 https://ffmpeg.org/trac/ffmpeg/ticket/420

該修復程序是一個flush函數被添加到aacdec.c清除其內部緩衝區。 問題是在aacdec.c中定義了兩個解碼器,並且只有一個被賦予了flush函數指針。如果您使用其他(更常見的)解碼器,它仍然不會被正確清除。

如果您在建立自己的ffmpeg的位置的時候,解決方法是添加 .flush =平齊, 到avcodec中ff_aac_decoder定義的底部(這是在文件的底部。)

我會讓ffmpeg傢伙知道如此希望它可以包含在主分支中。

+0

碰撞讓原來的海報有希望看到這個 – JHawkZZ

+0

非常感謝!我會重新編譯它,並放棄我的另一種方式......這是醜陋的,但工程... –