FFmpeg Android 硬件編解碼現(xiàn)狀及展望
一、功能特性
自FFmpeg 6.0版本開始,F(xiàn)Fmpeg對Android硬件編解碼的支持逐步完善了,當(dāng)前支持的功能特性包括:
通過JNI調(diào)用Java MediaCodec
直接調(diào)用NDK MediaCodec
解碼:H264、H265、MPEG2、MPEG4、VP8、VP9、AV1
編碼:H264、H265、MPEG4、VP8、VP9、AV1
輸入輸出方式
Surface/ANativeWindow作為編碼器輸入,作為解碼器輸出
Buffer輸入輸出:YUV420P/NV12格式的AVFrame
值得一提的是,Java MediaCodec和NDK MediaCodec兩套編解碼的實現(xiàn)是共存的,運行時可以通過參數(shù)控制選擇用哪一個,并且在獲取不到JVM時,自動選擇NDK MediaCodec的實現(xiàn)。
基于NDK MediaCodec的實現(xiàn)一方面性能更好,另一方面是可以脫離JVM環(huán)境運行:
你可以在adb命令行里執(zhí)行FFmpeg命令做硬件編解碼,做推流
你也可以在App程序里直接調(diào)用FFmpeg命令行
Android上運行FFmpeg命令行,當(dāng)前有兩大熱門的應(yīng)用場景:
termux https://github.com/termux/termux-app
ffmpeg-kit https://github.com/arthenica/ffmpeg-kit
二、亮點功能
做Android音視頻開發(fā)的同學(xué)熟悉,MediaCodec編碼器對非16整數(shù)倍分辨率的視頻有兼容性問題,特別是早期華為麒麟的芯片,容易crash。我在FFmpeg里實現(xiàn)MediaCodec硬件編碼時,通過FFmpeg自帶的bsf(bit stream filter)解決了和分辨率相關(guān)的兼容性問題。簡單來說,就是自動做align,再通過bsf修改輸出的碼流,修改SPS中的crop部分,裁切掉多余的padding。
三、已知缺陷
當(dāng)前編碼器支持YUV420P和NV12兩種pixel format輸入。但是,某些芯片只支持NV12格式,配置YUV420P格式會報錯。
1、設(shè)備支持哪種pixel format,Android只提供了Java的API,沒有NDK API,沒有JVM時就沒法查詢
2、即使能夠查詢,也得要知道MediaCodec編碼器的名字,知道MediaCodec編碼器的名字是在avcodec open之后,設(shè)置pixel format是在avcodec open之前
3、編碼器的pixel format是用戶設(shè)定的,不像解碼器有個get_format回調(diào)能夠協(xié)商
以上種種困難導(dǎo)致的后果就是,如果你設(shè)置編碼器輸入格式是YUV420P,打開編碼器可能失敗。
NV12基本都支持,一般建議用NV12格式。之所以提供YUV420P作為一個選項,是在輸入圖像本身是YUV420P的情況下,省去一道YUV420P到NV12的轉(zhuǎn)換,提升性能。
最近發(fā)現(xiàn)的另一個問題是:有個Vivo手機,用的聯(lián)發(fā)科天璣9000的CPU,AMediaFormat_getRect返回圖像的right/bottom信息錯亂了,結(jié)果是解碼正常,但是按照crop信息輸出,圖像只剩一小塊了。可能要加黑名單,忽略掉聯(lián)發(fā)科芯片返回的crop信息。
四、展望
未來我會重點放在NDK MediaCodec上,通過JNI調(diào)用Java MediaCodec實在繁瑣,只做基本維護,不做開發(fā)了。
高版本Android提供了異步的NDK MediaCodec接口,我在編碼器上實現(xiàn)了一個版本,性能提升挺明顯的,patch還沒合并到FFmpeg倉庫里,打算再多做些測試。解碼器也會加上異步方式,只是原有的解碼器實現(xiàn)比較亂,收拾起來要花更多時間。
等給FFmpeg MediaCodec加上異步的支持之后,再支持鴻蒙的硬件編解碼基本水到渠成了,因為看公開的API,基本上只是把Android MediaCodec的API換了個鴻蒙的前綴。現(xiàn)在沒有開發(fā)測試環(huán)境,等有條件再說吧!
關(guān)于10bit的編解碼支持,當(dāng)前可以用Surface/ANativeWindows做輸入輸出來實現(xiàn),Android沒提供可用的10bit的pixel format。HDR編碼的支持,看Android API情況和應(yīng)用場景而定,對我而言優(yōu)先級不高。類似的還有tunneled 模式,支持起來也許不難,但是構(gòu)造測試場景麻煩。
肯定還有其他場景我沒考慮到的,歡迎來聊。
