關於在Android音視頻開發中,Google API的MediaCodeC與成熟開源編碼器X264的應用對比及使用場景

在2019年的一個大項目中,有一個功能模塊讓筆者感觸頗深,那就是實時音視頻的預覽,當然這不是普通的開開直播,畫面出來了就完了那麼簡單,如果你是一個開發者,那麼你肯定知道同樣大小的一張圖片裏,色彩豐富的圖片的像素點肯定要比顏色單調的像素點要更多且更復雜,這就涉及到了編碼算法對圖像內冗餘數據的宏觀計算,顏色豐富的肯定要比色彩單調的處理起來更復雜,原理就不做闡述了,有興趣的小夥伴可以去某度一下,幀內預測與視頻編碼原理等。

在這個項目中呢,需求是監管平臺在後臺可以實時的預覽車輛上設備的前後兩路攝像頭,是同時開啓兩路攝像頭,並且能實時進行對講和監聽,視頻的質量也是要求非常的高,預計最少在1-2M/s碼率及以上,這裏跟大家說一下這個需求與普通室內的某些直播軟件的區別。

先說普通室內的直播,這一類直播通常是在一個房間內,因爲沒有那些藍天、白雲、綠樹、過往的車輛等,它所捕捉到的畫面是非常的單一的,因爲一般只有主播在活動,其他是相對靜止的,在這種環境下計算幀內冗餘數據是非常快得,且顏色複雜程度不高,所以其幀本身質量也相對較小,自然處理速度也稍快,如果排除網絡問題,那他們的延時肯定是與實際動作相接近的,當然如果觀看的是藍光畫質,那對網絡也是非常依賴的。

接下來說筆者項目中的預覽畫面情況,首先大家應該可以想象,在車上肯定是常有顛簸並且廣角攝像頭所捕捉的畫面是非常的大的,因爲汽車行駛的過程中,其他靜止的物體都相對運動了,比如天上的白雲、高樓大廈、過往的行人車輛等,這就導致了單幀數據的質量是非常高的,且顏色程度非常複雜,也變相表示着處理它們將耗費更多的機器性能與時間,如果對質量有苛刻的要求,要達到實際需求的水平,這將是對工程師本身技術水平的考驗,也將是對機器、硬件性能的考驗。

剛開始筆者採用的是MediaCodeC硬編碼,基於MT8735的芯片,單開其中一路最高只能達到1000kpb/s,室內跑起來問題不大,畫面很流暢且畫質也還行,於是裝車去實際路上跑,結果只要是汽車顛簸或經過陽光與陰暗交替的地方就會出現超級多的馬賽克,但加大碼率沒有實際效果,這個是MediaCodeC硬編碼的坑,後面會爲小夥伴們介紹。加大碼率後不僅沒有效果,反倒畫面會變卡,單一路就這樣了,更別說直接開兩路了。

於是我在X264官網上下載了開源編碼器的代碼,簡單的熟悉了一下API,就開始上手,因爲筆者有C++基礎,所以整個過程非常順利,筆者也順利把庫編譯好,並且從NDK C++裏把接口透出來。使用X264軟編碼加大碼率是有非常明顯的效果的,但是個人感覺開一路還湊合,兩路同時開的話必炸!於是我把cpu的使用情況查了一下,發現這個X264軟編碼也是異常的消耗性能,然後我去MT查了下關於芯片的性能方面,發現MT好像有專門提供一套用於這類實時媒體要求較高的芯片,MT8665芯片,因爲價格問題公司也沒有多說什麼,然後整個項目幾乎都已經沒什麼大問題了,主要就卡在視頻這一塊,無法推動下去。

個人感覺普通的芯片是無法滿足這類高性能要求的,尤其是這個項目的要求和標準也都是當地政府定的,所以這是個很糾結的問題,它高要求的視頻質量暫且不說,兩路視頻同時編碼運算處理,那是相當耗費性能的,更別說機器發燙啥的。雖然項目進入了僵局,筆者也有換個上班環境的打算,但筆者覺得還是要寫一篇心得,分享給遇到類似問題的小夥伴們,讓你們也有個底,不要因爲用錯了東西,導致後續耗費更大的人力物力!本篇內容純手打,要是覺得筆者寫得不錯的,給個贊支持一下原創作品

 

1.出處介紹

先簡單的介紹一下MediaCodeC以及X264開源編碼器

MediaCodeCGoogle Android 4.1, API16 版本首次推出

X264X264 Team的10名左右的成員在2003年發起,經過幾年的開發,x264逐漸成爲了最好的視頻編碼器

 

2.參數介紹

MediaCodeC硬編碼下常用的幾個參數

MediaFormat.KEY_BIT_RATE                         碼率

MediaFormat.KEY_FRAME_RATE                 幀率

MediaFormat.KEY_COLOR_FORMAT           輸入格式

MediaFormat.KEY_I_FRAME_INTERVAL    關鍵幀間隔

MediaFormat.KEY_BITRATE_MODE             碼率模式 (在MT8735上沒有實際作用)

MediaFormat.KEY_PROFILE                           視頻品質 (這個KEY個人覺得沒什麼用,問題還多,後面會介紹具體原因)

MediaFormat.KEY_LEVEL                               視頻複雜程度,該值越大相對的碼率、分辨率等也會較高

 

X264軟編碼下常用的幾個參數

b_repeat_headers                                              是否在每個關鍵幀前面添加SPS/PPS,0不加,1加

b_sliced_threads                                                並行或切片編碼,爲1時單幀圖像被切分成多片,爲0並行且x264自動計算編碼線程

i_width                                                                  編碼後的輸出畫面分辨率寬

i_height                                                                編碼後的輸出畫面分辨率高

i_bitrate                                                                輸出視頻碼率

i_rc_method                                                        碼率模式選擇,ABR模式(平均碼率)、CQP(恆定質量)、CRF(恆定碼率)

i_fps_num                                                            視頻幀率分子

i_fps_den                                                             視頻幀率分母

i_keyint_max                                                       GOP,關鍵幀間隔*視頻幀率分子,假設2S一個I幀,幀率24,那GOP爲48

i_threads                                                             編碼線程數,默認數爲 i_threads = x264_cpu_num_processors() * (h->param.b_sliced_threads ? 2 : 3) / 2

b_vfr_input                                                           ABR模式(平均碼率)下達不到設置碼率時,將此值置爲0

i_qp_constant                                                     CQP模式(恆定質量)下,0代表無損壓縮,QP值越小編碼質量越好,默認23

f_rf_constant                                                       CRF模式(恆定碼率)下,值越大圖像越花,值越小越清晰

f_rf_constant_max                                             CRF模式(恆定碼率)下,恆定碼率最大值

 

3.方法與函數介紹

MediaCodeC硬編碼常用方法介紹

getInputBuffers                                                   獲取輸入緩衝區

getOutputBuffers                                                獲取輸出緩衝區

dequeueInputBuffer                                           從輸入緩衝區獲取有效數據的索引,此方法相同值不同設備表現也不同,問題特別多

queueInputBuffer                                               向輸入緩衝區隊列傳遞具體的長度、偏移等參數

dequeueOutputBuffer                                        從輸出緩衝區獲取有效數據的索引

releaseOutputBuffer                                          釋放輸出緩衝區

 

X264軟編碼常用函數介紹

x264_param_default_preset                            設置X264編碼器的tune,一共有8種,直播的話默認填zerolatency

x264_param_apply_profile                              設置X264編碼器的質量,實際項目中baseline、main、high運用較多

x264_encoder_open                                         打開X264編碼器

x264_encoder_encode                                     進行編碼

x264_encoder_close                                        關閉X264編碼器

 

4.簡單的優缺點對比

MediaCodeC硬編碼優點:使用非常方便Google已經封裝好的現成接口對於直播質量與門檻要求較低的需求可以從容不迫的處理數據且延時相對較低

MediaCodeC硬編碼缺點:同一分API在不同的硬件、芯片上使用時兼容性差,會有各種千奇百怪的問題爆出來極大的增加了開發難度,同時也表現出了他的可移植性差

X264軟編碼優點:同一份代碼可以放在不同的Android芯片上使用,降低了後期開發的成本,對於視頻的質量等參數可以有效的把控,維護起來也只有一套代碼非常的nice,可移植性非常強

X264軟編碼缺點:對於新手上手難度過大需要花很多時間理解其中具體某個函數乃至變量的用途,即使看API也得耗費大量的時間去閱讀,編碼運算依賴CPU,如果是高強度的運算會導致機器的耗電量明顯加大,機器也會發燙

 

5.實際運用中踩過的坑

先說說MediaCodeC硬編碼,這個API看似Google都已經把該做的都已經做好了,但實際卻不盡人意,爲何這麼說呢?因爲使用過的小夥伴們都知道這裏面的坑有多少,乃至現在Android都出到10幾的版本了,這些問題我估計依然存在,因爲Android機型繁雜,所以很多小夥伴抱怨在某個機器上沒問題但在另一些機器上直接crash。就拿dequeueInputBuffer這個方法來說,相信被坑的不在少數吧?筆者覺得視頻質量一般,於是看了一下API,發現MediaFormat.KEY_PROFILE可以控制視頻的質量,於是我把質量設置到high,發現根本沒什麼用,於是找了一下資料發現這也是個坑爹貨,Android7.0以下默認baseline,不管你怎麼設置都是默認baseline,於是又找來7.0以上的機器,無濟於事,這也是前面提到的爲什麼加大碼率沒有實際效果!這讓我徹底放棄了MediaCodeC硬編碼,繼而轉向X264、FFMPEG、openH264等這些成熟的開源編碼器,因爲FFMPEG H264編碼最終也是調X264的庫,所以筆者直接打算找X264看。

使用X264的過程也很順利,在clone了源代碼之後,我按照X264編譯命令寫了3個編譯架構支持的shell腳本,分別是arm64-v8a、armeabi-v7a、x86三個架構,然後把源碼和腳本一同打包到我的Linux服務器,安裝完編譯插件跟NDK後,執行腳本後編譯出了三個架構的點a靜態庫,在copy到Androidstudio進行so集合編譯,都完美通過了。筆者把相關的編碼參數全部從NDK透出來,以便後續調試時不用再次編譯so庫了。關於X264的坑筆者只遇到了一個,就是頻繁的開關會導致編譯器內存紊亂回收不及時,某些變量已經被回收,其他邏輯塊卻還持有它的引用,導致NDK直接報錯進而引發機器ANR,最後通過一個pause接口完美規避了這個問題,還有就是看issue上有小夥伴說長時間開直播會出現黑屏現象,這個筆者倒是沒有遇到過,因爲我測的時候都是一兩小時的開着。

 

6.入手推薦

筆者個人覺得要入手的話建議入手X264,因爲畢竟是H264編碼的老大哥了!等你玩熟悉了,去面試的時候,在你的簡歷上寫上一條有音視頻直播開發經驗或開源X264二次開發難道它不香嘛,那真的是加分不少!因爲你能玩轉這個,也側面說明你有NDK開發經驗,無疑爲你增加很多加分項,加上目前抖音、快手、西瓜視頻、各類直播等東西的火爆,你也應該知道音視頻在未來的5年乃至10年都是相當重要的!如果小夥伴沒有C/C++基礎,建議也多看看這類入門的學習視頻,畢竟時間不等人,別讓自己過了30了,還在爲自己跳槽是否找不找得到工作而發愁,爲了房貸車貸而不敢跟領導說NO

 

7.使用推薦

說了那麼多,那到底用MediaCodeC還是用X264呢?其實筆者前面已經給出答案,就是優缺點嘛!對於直播畫面質量要求較低的需求,我們完全可以採用MediaCodeC進行編碼,省時省力!如果直播畫面要求相對較高時,並且機器性能給力的前提下,當然推薦你用X264,FFMPEG太過龐大,且其h264編碼實質也是調用的X246,當然市面上還有其他優秀的編碼器,看小夥伴們自己怎麼選擇。如果既需要高標椎的直播畫面,又沒有強勁的硬件性能,碰到這類需求,該放手時就放手,你搞不定的,相信我!好了,學習道路千萬條,走向捷徑就一條,那就是勤奮!謝謝你閱讀到這裏,感謝小夥伴們一直以來對我的支持!再次感謝你們

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章