01、多媒體基礎(chǔ)概念
視頻分辨率
?標(biāo)清、高清、720P…
視頻編碼
?H.264、H.265…
音頻編碼
?AAC、MP3、AC3…
視頻封裝格式
?TS、RMVB 、MKV
多媒體播放組件(Android)
?MediaPlayer、MediaCodec、OMX、Stagefright
視頻
分辨率
一幀視頻的大小,表示長寬像素個數(shù)(720x576, 1280x720, 1920x1080 …)
幀率
每秒鐘視頻幀數(shù)(24/25/30/48/60 FPS)
編碼格式
編碼:目的是壓縮數(shù)據(jù)量,采用編碼算法壓縮冗余數(shù)據(jù)
MPEG(MPEG-2, MPEG-4)
H.26X(H.263, H.264/AVC, H.265/HEVC)
封裝格式
?把編碼后的音、視頻數(shù)據(jù)以一定格式封裝到一個容器
?MKV/AVI/TS …
02、Android平臺播放器
多媒體播放器基本組成

MediaPlayer狀態(tài)周期

MediaPlayer簡介

什么是MediaCodec
在Android中用于訪問底層的媒體編解碼器的類,是Android底層多媒體基礎(chǔ)框架的一部分,通常與MediaExtractor, MediaSync, MediaMuxer, MediaCrypto, MediaDrm, Image, Surface和AudioTrack一起使用
?它本身并不是Codec,它是通過調(diào)用底層編解碼組件具有Codec能力
?適用的Android版本
?Android 4.1以后的版本(API 16+)
MediaCodec狀態(tài)

MediaCodec解碼方式
同步解碼

異步解碼(Android5.0后)

03、常見音視頻開發(fā)中的問題總結(jié)
黑屏
播放過程中黑屏
當(dāng)播放器遇到不支持的視頻格式,或者數(shù)據(jù)內(nèi)容/格式異常,則會解碼失敗,從而導(dǎo)致無解碼視頻輸出
定位:播放器播放時的報錯日志,用合適的播放模式播放。數(shù)據(jù)異常,需要分析碼流文件本身,送入解碼器的幀數(shù)據(jù)不完整,H.264 的視頻碼流,缺失了 SPS,PPS 等必要的信息頭,部分 Android 機(jī)型硬編出來的數(shù)據(jù)有額外的 NALU 頭
重新起播/進(jìn)入時黑屏
這時是由于沒有渲染出幀,進(jìn)入時黑屏,可以增加loading動畫,直到渲染出首幀,loading動畫消失,另外一種是應(yīng)用退到后臺,再回到應(yīng)界播放界面時黑屏,可以在pause時,保存視頻最后播放的幀,重新進(jìn)來時,看到時之前退出時的畫面,等播放器重新緩沖好后,開始畫面連續(xù)播放
卡頓/卡死
卡頓分網(wǎng)絡(luò)差,數(shù)據(jù)跟不上造成的卡頓,還有一種就是畫面很慢的變化卡頓??ㄋ酪话闶强ㄗ〔粍?/p>
分析:網(wǎng)絡(luò)差的卡頓,可以在播放器加入數(shù)據(jù)代理,用于緩存足夠多的數(shù)據(jù)。畫面解碼卡頓,可以降低清晰度或用其他播放模式播放。卡死,有時是調(diào)用某個方法后,一直得不到回調(diào)引起,如我們在VLC上發(fā)現(xiàn),stop時,遲遲得不到onStopped狀態(tài)。導(dǎo)致時間過長無相應(yīng)ANR
馬賽克
馬賽克,這里指局部/半局部馬賽克,常出現(xiàn)在很高畫質(zhì)視頻,給播放器播放出現(xiàn)。如果畫面偶爾出現(xiàn)馬賽克,通常是數(shù)據(jù)錯誤造成的。注意區(qū)分
分析:視頻幀中主要是一個一個宏塊組成,頻編碼算法以宏塊為單位,逐個宏塊進(jìn)行編碼,組織成連續(xù)的視頻碼流。解碼同樣也是。畫質(zhì)越高,壓縮越厲害
H.264 有四種畫質(zhì)級別
?Baseline profile
?Extended profile
?Main profile
?High profile
畫質(zhì)越高,對解碼能力要求也越高
花屏/綠屏
播放畫面出現(xiàn)圖像紊亂,像被刮花了一樣。大面積的異常顏色的方塊圖,綠屏或其他顏色現(xiàn)象
丟失參考幀導(dǎo)致, I 幀由于是幀內(nèi)壓縮,因此可以獨立解碼播放,而 B 幀,一旦丟失了 I 幀或者后面的 P 幀,則會解碼失敗,而 P 幀一旦丟失了前面的 I/B/P 幀,也會導(dǎo)致解碼失敗。不要丟棄編碼后、解碼前的視頻幀數(shù)據(jù),實在要丟,一次丟一整個 GOP(一個I幀到下一個I幀中間的數(shù)據(jù))

音畫不同步
遇到log中大量打印“Past duration XXX too large”且伴有frame drop相關(guān)信息的打印
分析方法:將輸入視頻包的時間戳信息打印出來,發(fā)現(xiàn)一些視頻幀未設(shè)置DTS/PTS,這些視頻幀攜帶的時間戳都是默認(rèn)值為AV_NOPTS_VALUE,代碼中對該值的定義如下
?#define AV_NOPTS_VALUE ((int64_t)UINT64_C(0x8000000000000000))
而這些幀在編碼輸出之前會被Drop掉,為了滿足設(shè)定的幀率,后面的有效時間戳的幀會提前輸出,導(dǎo)致視頻提前而音頻滯后
解決方法:由于我們?yōu)檫@些未設(shè)置時間戳的輸入幀填充有效時間戳不是一件很容易的
04、播放方案
1、ExoPlayer
ExoPlayer 是一個Google開源項目,它不屬于Android framework,獨立于Android SDK
Android支持通過MediaExtractor和MediaCodec實現(xiàn)自定義播放。ExoPlayer介于MediaPlayer和自定義播放器之間的播放器,比MediaPlayer更強的擴(kuò)展能力
ExoPlayer可以通過進(jìn)一步擴(kuò)展來處理多種媒體格式
由于它是內(nèi)置于app中,所以可以隨著app進(jìn)行升級事(需要結(jié)合輸入視頻是否采用B幀等),因此在輸入輸出幀率相同時,我們可以將這些攜帶無效時間戳的幀正常送至編碼器編碼并輸出,而不是丟棄
ExoPlayer優(yōu)點
?支持 Dynamic Adaptive Streaming over HTTP (DASH) 和SmoothStreaming,更多支持請參閱支持的格式)詳細(xì)信息頁面。
?支持高級 HLS (HTTP Live Streaming)功能,如正確處理 #EXT-X-DISCONTINUITY的標(biāo)簽
?ExoPlayer缺點
?ExoPlayer的音頻和視頻組件依賴Android的 MediaCodec接口,該接口發(fā)布于Android4.1(API 等級16)。因此它不能工作于之前的Android版本
?ExoPlayer
?YouTube(Android平臺客戶端)使用ExoPlayer
?資料
?http://developer.android.com/guide/topics/media/exoplayer.html
?https://github.com/google/ExoPlayer
2、Ijkplayer
是基于ffmpeg開源的輕量級視頻播放器,跨平臺
封裝ffplay、MediaPlayer,MediaCodec,ExoPlayer
支持幾乎所有視頻封裝格式
音頻AudioTrack,OpenSL ES
Ijkplayer

Ijkplayer應(yīng)用
B站和主流直播軟件都在使用
資料
?https://github.com/Bilibili/ijkplayer
?可以重點關(guān)注issue區(qū)
3、VLC
VLC(Video Lan Client)是一個完整的多媒體框架,最大特點是可以根據(jù)需要動態(tài)加載許多插件模塊,支持視頻傳輸,封裝和編碼格式??蚣芎诵氖抢贸绦?qū)⒏髂K鏈接起來。對輸入媒體數(shù)據(jù),經(jīng)過各模塊處理后輸出
?可在所有平臺運行:Windows, Linux, Mac OS X, Unix, iOS, Android ..
?支持Dolby,及多音軌,多字幕
?內(nèi)置MediaCodec,ffmpeg,有自己專門的Demuxing,和自己接入OpenMax組件
VLC

小米Android ROM集成VLC作為播放器
資料
?git://git.videolan.org/vlc.git
名人語錄:
格局,布局,步局。心中有多大,舞臺就有多大。 —— 郭臺銘