目錄
- 問題描述
- 問題分析
- 問題原因
- 問題解決
- 資料
- 收獲
一躺盛、問題描述
用小米11 錄制視頻上傳后省骂,在iPhone的Safari瀏覽器或者應(yīng)用的H5中無法播放,而android設(shè)備上的確實(shí)可以正常播放劫谅。
同樣的操作绰咽,在一些其他android的手機(jī)上傳的視頻眼坏,在ios端卻可以正常的播放拂玻。
二、問題分析
拿到(能播放和不能播放)兩個視頻宰译。分析下這兩個視頻有什么差異檐蚜。
通過MediaInfo查看兩個視頻的基本信息
不能播放的視頻
{
"@type": "Video",
"StreamOrder": "1",
"ID": "2",
"Format": "AVC",
"Format_Profile": "High",
"Format_Level": "6",
"Format_Settings_CABAC": "Yes",
"Format_Settings_RefFrames": "1",
}
能播放的視頻
{
"@type": "Video",
"Format": "AVC",
"Format_Profile": "Main",
"Format_Level": "3.1",
"Format_Settings_CABAC": "Yes",
}
可以很明顯的看到兩個視頻的Profile和Level不同。
通過ffmpeg把不能播放的視頻進(jìn)行轉(zhuǎn)碼囤屹,修改profile和level的值熬甚,進(jìn)行本地快速驗證逢渔。
ffmpeg -i input.mp4 -profile:v main -level 4.2 output.mp4
ffmpeg -i input.mp4 -profile:v high -level 5.1 output.mp4
ffmpeg -i input.mp4 -profile:v high -level 6 output.mp4
發(fā)現(xiàn)只有l(wèi)evel大于等于6肋坚,在ios上就不能播放。
三、問題原因
我們先來看下Profile和Level是什么智厌?
3.1 Profile
H.264有四種畫質(zhì)級別,分別是baseline, extended, main, high:
1诲泌、Baseline Profile:基本畫質(zhì)。支持I/P 幀铣鹏,只支持無交錯(Progressive)和CAVLC敷扫;
2、Extended profile:進(jìn)階畫質(zhì)诚卸。支持I/P/B/SP/SI 幀葵第,只支持無交錯(Progressive)和CAVLC;(用的少)
3合溺、Main profile:主流畫質(zhì)卒密。提供I/P/B 幀,支持無交錯(Progressive)和交錯(Interlaced)棠赛, 也支持CAVLC 和CABAC 的支持哮奇;
4、High profile:高級畫質(zhì)睛约。在main Profile 的基礎(chǔ)上增加了8x8內(nèi)部預(yù)測鼎俘、自定義量化、 無損視頻編碼和更多的YUV 格式辩涝;
H.264 Baseline profile贸伐、Extended profile和Main profile都是針對8位樣本數(shù)據(jù)、4:2:0格式(YUV)的視頻序列怔揩。
在相同配置情況下棍丐,High profile(HP)可以比Main profile(MP)降低10%的碼率。
根據(jù)應(yīng)用領(lǐng)域的不同沧踏,Baseline profile多應(yīng)用于實(shí)時通信領(lǐng)域歌逢,Main profile多應(yīng)用于流媒體領(lǐng)域,High profile則多應(yīng)用于廣電和存儲領(lǐng)域翘狱。
維基百科上有對應(yīng)的表:
3.2 level
level是一組特定的約束秘案,表示一個profile所需的編解碼性能。指定編解碼器可能使用的最大圖像分辨率潦匈、幀率和比特率阱高。一個符合給定level的解碼器必須能夠解碼為該level和所有低level編碼的所有比特流。
在MediaCodecInfo中有定義各種類型的值
綜上茬缩,我們可以知道Profile和Level是影響著視頻編碼的質(zhì)量和效率赤惊。有些設(shè)備不支持高Profile、level的編碼凰锡。所以需要綜合考慮兼容性和視頻質(zhì)量未舟。
通過查看代碼發(fā)現(xiàn)圈暗,android端的視頻編碼時,僅對Profile做了閥值限制裕膀,Level沒有判斷處理员串,就像小米11手機(jī)對應(yīng)解碼器信息返回的Level時6,這樣編碼出來的視頻在某些不支持的該level解碼的設(shè)備上就無法解碼播放昼扛。
3.3 擴(kuò)展
另外通過查找資源寸齐,發(fā)現(xiàn)android在7.0之前的系統(tǒng),編碼時profile只能是Baseline抄谐,如果不是系統(tǒng)會強(qiáng)制的設(shè)置為Baseline渺鹦。猜測也是為了兼容性吧。雖然更高的壓縮比帶來很好的收益蛹含,但是兼容性(普適性)是優(yōu)先考慮的點(diǎn)海铆。
使用MediaCodec編碼時,通常是這樣設(shè)置的
先配置MediaCodecInfo的profile信息 然后賦給MediaFormat
codec.configure(format,null,null,MediaCodec.CONFIGURE_FLAG_ENCODE);
最后設(shè)置給MediaCodec
編碼得到的碼流都是baseline profile的
這是由于android sdk本身的限制導(dǎo)致的
ACodec.cpp里的對應(yīng)處理如下:
if (h264type.eProfile != OMX_VIDEO_AVCProfileBaseline) {
ALOGW("Use baseline profile instead of %d for AVC recording",
h264type.eProfile);
h264type.eProfile = OMX_VIDEO_AVCProfileBaseline;
}
在Android 7.0之后才移除了這段代碼挣惰。也就是說要想使用MP要求Android系統(tǒng)版本在7.0及其以上卧斟。
四、問題解決方案
4.1 方案一: 用戶上傳后先經(jīng)過服務(wù)端的轉(zhuǎn)碼后憎茂,再下發(fā)給用戶
用戶上傳的視頻可能差別很大(封裝格式珍语、編碼格式、采樣率竖幔、碼率板乙、幀率、分辨率拳氢、YUV存儲格式等等)募逞,有些播放器可能對某些視頻支持的不太好。比如:有些設(shè)備不支持HEVC的解碼馋评、有些解碼器不支持MPEG-4的編碼格式放接、有些播放器只支持YUV420P的格式、有些播放器對于幀率很高的視頻卡頓留特、有些播放器不支持播放4K等高清視頻 等等
針對上述情況纠脾,一種比較通用的做法是。用戶上傳后先經(jīng)過服務(wù)端的轉(zhuǎn)碼后蜕青,再下發(fā)給其他用戶苟蹈。進(jìn)而保證視頻再各種設(shè)備上的兼容性。
4.2 方案二右核、編碼時的profie和level設(shè)置上線閥值
profile 最大值設(shè)置為 MediaCodecInfo.CodecProfileLevel.AVCProfileHigh
Level 最大值設(shè)置為 MediaCodecInfo.CodecProfileLevel.AVCLevel52
當(dāng)從解碼器中遍歷的MediaCodecInfo.CodecProfileLevel的profie和level上述閥值時慧脱,用上述最大值。進(jìn)而保證在各種設(shè)備的兼容性贺喝。
方案1是更加通用的解決方案菱鸥,方案2則是腳痛醫(yī)腳的方案宗兼。
五、 資料
- H.264 and H.265 (HEVC)
- ffmpeg 常用命令
- H264編碼profile & level控制
- Using ffprobe to get info from a file in a nice JSON format
- Android MediaCodec參數(shù)筆記_
- Android MediaCodec h264編碼無法設(shè)為high profile
六采缚、收獲
通過本篇的學(xué)習(xí)
- 分析解決部分android設(shè)備上編碼的視頻针炉,ios不能播放的問題
- 進(jìn)一步熟悉Profile挠他、Level的意義
感謝你的閱讀
歡迎關(guān)注公眾號“音視頻開發(fā)之旅”扳抽,一起學(xué)習(xí)成長。
歡迎交流