編輯:關於android開發
【前言】
因為這幾天在為設備從Android M升級到Android N的bringup做准備,所以一直沒寫博客。趁現在剛剛把Kernel部分的移植做完,忙裡偷閒把2周前解決的一個音頻UnderRun問題記錄一下,留作以後參考。
問題現象是:使用騰訊視頻APP播放視頻,一段時間後會出現pop-click噪音,聽起來類似“哒哒”一樣的聲音。
【排查問題】
看到這個問題的現象後,我的第一猜測就是設備出現了UnderRun。
大膽假設後還需小心求證。於是我在代碼中開啟Verbose Log打印並重新編譯系統鏡像燒寫到設備上。然後復現問題,並查看出現問題的時間點附近的Log消息。日志文件中出現了大量如下記錄:
12-08 10:09:15.565 2825 3426 V AudioFlinger: track(0xea5dda80) underrun, framesReady(1024) < framesDesired(1026)12-08 10:09:15.599 2825 3426 V AudioFlinger: mixer(0xeb440000) throttle begin: ret(4096) deltaMs(0) requires sleep 10 ms12-08 10:09:15.625 2825 3426 D AudioFlinger: mixer(0xeb440000) throttle end: throttle time(20)
果然這是個UnderRun問題,Log中的信息證實了猜想:音頻播放需要1026幀數據,但APP只准備好了1024幀。但我們也知道,Android系統對於underrun出現後是有一套默認的處理流程來消除問題的,也就是緊接著的2條和throttle相關的Log所對應的操作。
簡單介紹一下Android系統默認處理underrun問題的流程:當檢測到當前寫入音頻數據的時間與上次出現警告的時間間隔大於預定的最大時間間隔(5納秒)後,系統將判定音頻播放過程出現了underrun。然後系統會調用usleep()函數對當前PlaybackThread進行短時間阻塞,這樣上層APP就能為PlaybackThread准備好更多音頻數據。這個usleep()的時長是根據相鄰2次寫入音頻數據的時間間隔實時計算出的。
相應的代碼可以在 frameworks/av/sevices/audioflinger/Threads.cpp 中的AudioFlinger::PlaybackThread::threadLoop()函數中找到:
【解決問題】
前文貼出的Log表明,Android系統已經檢測到了UnderRun問題並進行了延時處理來讓APP准備更多的音頻數據。可是我們在使用騰訊視頻APP時依然會繼續發生UnderRun的問題,原因在於代碼中計算出的延時時間對騰訊視頻APP來說還是太短。在Log中我們可以看到需要的數據量為1026幀但實際准備好的數據為1024幀,所以我們可以稍微增加usleep()的延時時間來為PlaybackThread准備足夠的數據。經過試驗,我決定在原有延時時間上增加3毫秒。
重編系統鏡像後燒入設備進行驗證,問題得到解決。
【擴展閱讀】
[1]《音頻出現Xrun(underrun或overrun)的原因與解決辦法》
Win7下搭建安卓android開發環境,win7安卓一、下載安裝包(可執行文件) 1.JDK(JavaDevelopmentKit),官網下載最新版本即可。 2.Ecl
Android開發學習之路--傳感器之初體驗 說到傳感器,還是有很多的,有加速度啊,光照啊,磁傳感器等等。當然android手機之所以稱為智能手機,少不了這幾款傳感器
Android無線開發的幾種常用技術綜述 本文由阿裡巴巴移動安全客戶端、YunOS資深工程師Hao(嵌入式企鵝圈原創團隊成員)撰寫,是Hao在嵌入式企鵝
Android 系統API實現數據庫的增刪改查和SQLite3工具的使用,androidsqlite3在《Android SQL語句實現數據庫的增刪改查》中介紹了使用sq