关于在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開源編碼器
MediaCodeC由Google?Android 4.1, API16 版本首次推出
X264由X264 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,當然市面上還有其他優秀的編碼器,看小伙伴們自己怎么選擇。如果既需要高標椎的直播畫面,又沒有強勁的硬件性能,碰到這類需求,該放手時就放手,你搞不定的,相信我!好了,學習道路千萬條,走向捷徑就一條,那就是勤奮!謝謝你閱讀到這里,感謝小伙伴們一直以來對我的支持!再次感謝你們!
總結
以上是生活随笔為你收集整理的关于在Android音视频开发中,Google API的MediaCodeC与成熟开源编码器X264的应用对比及使用场景的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 凡科的ns服务器如何修改,ns怎么把服务
- 下一篇: excel版本问题解决方案