音視頻開發(fā)總結(jié)之二Android平臺(tái)相關(guān)

一. 音視頻采集流程

串聯(lián)整個(gè)音視頻錄制流程,完成音視頻的采集、編碼、封包成 mp4 輸出。


流程圖

通過(guò)攝像頭和麥克風(fēng)獲得實(shí)時(shí)的音視頻數(shù)據(jù);

  • 播放流程: 獲取流—>解碼—>播放。
  • 錄制播放路程: 錄制音頻視頻—>視頻處理—>編碼—>上傳服務(wù)器->別人播放。
  • 直播過(guò)程 : 錄制音視頻—>編碼—>流媒體傳輸—>服務(wù)器—>流媒體傳輸?shù)狡渌蛻舳恕?gt;解碼—>播放。

視頻采樣數(shù)據(jù) : 一般都是 YUV 或 RGB 格式。

音頻采樣數(shù)據(jù) :一般都是PCM格式。


二.音頻采集

1.Android如何采集音頻

Android SDK對(duì)于音頻采集提供兩套API:MediaRecorder和AudioRecorder。

AudioRecord

AudioRecord輸出是PCM語(yǔ)音數(shù)據(jù),得到原始的一幀幀PCM音頻數(shù)據(jù)。如果保存成音頻文件,是不能夠被播放器播放的,所以必須先寫代碼實(shí)現(xiàn)數(shù)據(jù)編碼以及壓縮。
一般直播技術(shù)采用的就是 AudioRecorder 采集音頻數(shù)據(jù)。
PCM(Pulse Code Modulation)也被稱為脈沖編碼調(diào)制。PCM音頻數(shù)據(jù)是未經(jīng)壓縮的音頻采樣數(shù)據(jù)裸流,它是由模擬信號(hào)經(jīng)過(guò)采樣、量化、編碼轉(zhuǎn)換成的標(biāo)準(zhǔn)的數(shù)字音頻數(shù)據(jù)。

MediaRecorder

MediaRecorder是偏上層的一個(gè)API,可以直接把手機(jī)麥克風(fēng)錄入的音頻數(shù)據(jù)進(jìn)行編碼壓縮為AMR,MP3等并保存文件。

MediaRecorder和AudioRecord的區(qū)別
  • MediaRecorder和AudioRecord都可以錄制音頻,區(qū)別是MediaRecorder錄制的音頻文件是經(jīng)過(guò)壓縮后的,需要設(shè)置編碼器。并且錄制的音頻文件可以用系統(tǒng)自帶的Music播放器播放。而AudioRecord錄制的是PCM格式的音頻文件,需要用AudioTrack來(lái)播放,AudioTrack更接近底層,PCM經(jīng)過(guò)編碼壓縮可以為 amr MP3 AAC。
  • 當(dāng)要簡(jiǎn)單的把數(shù)據(jù)采集為音頻文件,就使用MediaRecorder,如果要對(duì)音頻做進(jìn)一步的算法處理就使用AudioRecorder。
MediaRecorder和AudioRecord的優(yōu)缺點(diǎn):

AudioRecord:
主要是實(shí)現(xiàn)邊錄邊播以及對(duì)音頻的實(shí)時(shí)處理,這個(gè)特性讓他更適合在語(yǔ)音方面有優(yōu)勢(shì);
優(yōu)點(diǎn):語(yǔ)音的實(shí)時(shí)處理,可以用代碼實(shí)現(xiàn)各種音頻的封裝。
缺點(diǎn):輸出是PCM格式文件,如果保存成音頻文件,是不能夠被播放器播放的,所以必須先寫代碼實(shí)現(xiàn)數(shù)據(jù)編碼以及壓縮。
MediaRecorder:
已經(jīng)集成了錄音、編碼、壓縮等,支持少量的錄音音頻格式,大概有,aac,amr,3gp等
優(yōu)點(diǎn):集成,直接調(diào)用相關(guān)接口即可,代碼量小
缺點(diǎn):無(wú)法實(shí)時(shí)處理音頻;輸出的音頻格式不是很多,例如沒(méi)有輸出mp3格式文件

MediaRecorder和AudioRecord的應(yīng)用:

如果只是想簡(jiǎn)單地做一個(gè)錄音機(jī),錄制音頻文件,就使用 MediaRecorder,而如果需要對(duì)音頻做進(jìn)一步的算法處理、或者采用第三方的編碼庫(kù)進(jìn)行壓縮、以及網(wǎng)絡(luò)傳輸、直播等應(yīng)用,則建議使用 AudioRecord。

三.視頻采集

和音頻一樣,也有高層和低層的 API,高層就是Camera 和 MediaRecorder,可以快速實(shí)現(xiàn)編碼,低層就是直接使用Camera,然后將采集的數(shù)據(jù)進(jìn)行濾鏡、降噪等前處理,處理完成后由 MediaCodec 進(jìn)行硬件編碼,最后采用 MediaMuxer 生成最終的視頻文件。
在 Android 系統(tǒng)下有兩套 API 可以進(jìn)行視頻采集,Camera 和 Camera2。Camera是以前老的 API ,從 Android 5.0(21)之后就已經(jīng)放棄了。如今主要使用 Camera2 進(jìn)行視頻的采集。

直播開發(fā)中經(jīng)常需要獲取視頻原始幀數(shù)據(jù)然后前置處理例如:美顏、水印、特效等然后通過(guò)編碼在通過(guò)rtmp或者rtsp等協(xié)議方式推流出去,可以完成實(shí)時(shí)圖像傳遞。
那么如何獲取原始視頻幀數(shù)據(jù)?android camera api有一個(gè)設(shè)置回調(diào)的方法,可以將可以通過(guò)它來(lái)獲取原始視頻數(shù)據(jù)如nv21 、 nv12 、 yv12 等。

MediaRecorder實(shí)現(xiàn)視頻采集優(yōu)缺點(diǎn)

優(yōu)點(diǎn):
使用方便,得到就是編碼和封裝好的音視頻文件,可以直接使用。

缺點(diǎn):
無(wú)法獲取原始數(shù)據(jù),從而無(wú)法對(duì)原始數(shù)據(jù)添加一些自己的處理。

Camera實(shí)現(xiàn)視頻采集步驟

  1. 通過(guò)MediaCodec創(chuàng)建一個(gè)用于輸入的Surface
  2. 通過(guò)通過(guò)camera預(yù)覽時(shí)的上下文EGL創(chuàng)建OpenGL的環(huán)境,根據(jù)上面得到的Surface創(chuàng)建EGLSuface。
  3. 通過(guò)camera預(yù)覽時(shí)的綁定的紋理id,進(jìn)行紋理繪制。
  4. 交換數(shù)據(jù),讓數(shù)據(jù)輸入新Surface。使用AudioReocod進(jìn)行聲音的采集
  5. 通過(guò)Mediacodec編碼為h264、AAC。
  6. 通過(guò)MediaMuxer進(jìn)行數(shù)據(jù)封裝為mp4。

四. 視頻處理

視頻或者音頻完成采集之后得到原始數(shù)據(jù),為了增強(qiáng)一些現(xiàn)場(chǎng)效果或者加上一些額外的效果,我們一般會(huì)在將其編碼壓縮前進(jìn)行處理,例如:視頻美顏及變聲等操作。

1. 音頻處理

可以對(duì)音頻的原始流做處理,如降噪、回音、以及各種 filter 效果。

2. 視頻處理

現(xiàn)在抖音、美圖秀秀等,在拍攝,視頻處理方面,都提供了很多視頻濾鏡,而且還有各種貼紙、場(chǎng)景、人臉識(shí)別、特效、添加水印等。

對(duì)視頻進(jìn)行美顏和添加特效大部分都是通過(guò) OpenGL 進(jìn)行處理的。Android 中有 GLSurfaceView,這個(gè)類似于 SurfaceView,不過(guò)可以利用 Renderer 對(duì)其進(jìn)行渲染。通過(guò) OpenGL 可以生成紋理,通過(guò)紋理的 Id 可以生成 SurfaceTexture,而 SurfaceTexture 可以交給 Camera,最后通過(guò)紋理就將攝像頭預(yù)覽畫面和 OpenGL 建立了聯(lián)系,從而可以通過(guò) OpenGL 進(jìn)行一系列的操作。

美顏的整個(gè)過(guò)程無(wú)非是根據(jù) Camera 預(yù)覽的紋理通過(guò) OpenGL 中 FBO 技術(shù)生成一個(gè)新的紋理,然后在 Renderer 中的onDrawFrame() 使用新的紋理進(jìn)行繪制。添加水印也就是先將一張圖片轉(zhuǎn)換為紋理,然后利用 OpenGL 進(jìn)行繪制。添加動(dòng)態(tài)掛件特效則比較復(fù)雜,先要根據(jù)當(dāng)前的預(yù)覽圖片進(jìn)行算法分析識(shí)別人臉部相應(yīng)部位,然后在各個(gè)相應(yīng)部位上繪制相應(yīng)的圖像,整個(gè)過(guò)程的實(shí)現(xiàn)有一定的難度,人臉識(shí)別技術(shù)目前有 OpenCV、Dlib、MTCNN 等。

各種美顏和視頻添加特效的簡(jiǎn)單效果也可以基于GPUImage框架實(shí)現(xiàn)。

3. 紋理

紋理是表示物體表面的一幅或幾幅二維圖形,也稱紋理貼圖(texture)。當(dāng)把紋理按照特定的方式映射到物體表面上的時(shí)候,能使物體看上去更加真實(shí)。當(dāng)前流行的圖形系統(tǒng)中,紋理繪制已經(jīng)成為一種必不可少的渲染方法。在理解紋理映射時(shí),
可以將紋理看做應(yīng)用在物體表面的像素顏色。在真實(shí)世界中,紋理表示一個(gè)對(duì)象的顏色、圖案以及觸覺(jué)特征。紋理只表示對(duì)象表面的彩色圖案,它不能改變對(duì)象的幾何結(jié)構(gòu)。

4. OpenGL ES

OpenGL ES 是手機(jī)、PDA 和游戲主機(jī)等嵌入式設(shè)備三維 (二維也包括) 圖形處理的 API,當(dāng)然是用來(lái)在嵌入式設(shè)備上的圖形處理了,OpenGL ES 強(qiáng)大的渲染能力使其成為我們?cè)谇度胧皆O(shè)備上進(jìn)行圖形處理的優(yōu)良選擇。我們經(jīng)常使用的場(chǎng)景有:

圖片處理。比如圖片色調(diào)轉(zhuǎn)換、美顏等。
攝像頭預(yù)覽效果處理。比如美顏相機(jī)、惡搞相機(jī)等。
視頻處理。攝像頭預(yù)覽效果處理可以,這個(gè)自然也不在話下了。
3D 游戲。比如神廟逃亡、都市賽車等。

五.音視頻編碼和封裝

1. 為何要對(duì)音視頻進(jìn)行編碼?

音視頻的原始數(shù)據(jù)非常龐大,難以存儲(chǔ)和傳輸。要解決音視頻數(shù)據(jù)的存儲(chǔ)和傳輸問(wèn)題,或是為了加密等。
就需要對(duì)這些數(shù)據(jù)進(jìn)行壓縮,音視頻數(shù)據(jù)壓縮技術(shù)就是音視頻編碼
編碼的目的就是在最小圖像或音頻信息丟失情況下得到最大的壓縮,解碼是相對(duì)編碼的,其目的是最大限度的還原原始圖像或聲音信息。
編解碼的意義就是便于數(shù)據(jù)傳輸和存儲(chǔ)。

2. 編解碼種類(硬件編碼,軟件編碼)

  • 軟編碼:使用CPU進(jìn)行編碼,實(shí)現(xiàn)直接、簡(jiǎn)單,參數(shù)調(diào)整方便,升級(jí)易,但CPU負(fù)載重,性能較硬編碼低,低碼率下質(zhì)量通常比硬編碼要好一點(diǎn)。

  • 硬編碼:使用非CPU進(jìn)行編碼,如顯卡GPU、專用的DSP、FPGA、ASIC
    芯片等,性能高,低碼率下通常質(zhì)量低于軟編碼器,但部分產(chǎn)品在GPU硬
    件平臺(tái)移植了優(yōu)秀的軟編碼算法(如X264)的,質(zhì)量基本等同于
    軟編碼。

  • 軟解碼,指利用CPU的計(jì)算能力來(lái)解碼,通常如果CPU的能力不是很強(qiáng)的時(shí)候,一則解碼速度會(huì)比較慢,二則手機(jī)可能出現(xiàn)發(fā)熱現(xiàn)象。優(yōu)點(diǎn)是,由于使用統(tǒng)一的算法,兼容性會(huì)很好。

  • 硬解碼,指的是利用手機(jī)上專門的解碼芯片來(lái)加速解碼。通常硬解碼的解碼速度會(huì)快很多,但是由于硬解碼由各個(gè)廠家實(shí)現(xiàn),質(zhì)量參差不齊,非常容易出現(xiàn)兼容性問(wèn)題。

在Android 4.1之前沒(méi)有提供硬編解碼的API,所以基本都是采用開源的那些庫(kù),比如著名的FFMpeg實(shí)現(xiàn)軟編解碼。通常情況下,同一平臺(tái)同一硬件環(huán)境,硬編碼的速度快于軟件編碼,軟編碼使用CPU來(lái)進(jìn)行計(jì)算,會(huì)消耗一些app的運(yùn)算效率。在Android4.1及以上版本可以使用MediaCodec來(lái)訪問(wèn)底層的媒體編解碼器從而支持硬編碼/硬解碼。

Android API 中有個(gè) MediaCodec 的類,利用 MediaCodec 可實(shí)現(xiàn)硬編碼,高效且方便,Android API 中還有個(gè)叫 MediaMuxer 的類,可以實(shí)現(xiàn)音頻與視頻的合成,但是 MediaCodec 使用的 API 最低要求是 16,MediaMuxer 則是 18,如果使用軟編碼,那么 API 限制將不再那么苛刻。

推薦安卓4.1以上使用硬編碼,以下使用軟編碼,而iOS使用全部硬編碼。如果是使用播放解碼,不管是安卓還是iOS,都使用軟解碼方案,雖然這樣做不可避免的犧牲功耗,但是在部分細(xì)節(jié)方面表現(xiàn)會(huì)較優(yōu),且可控性強(qiáng),兼容性也強(qiáng),出錯(cuò)情況少。

3. 視頻編碼封裝的可行性方案

  • 第一個(gè)就是大家熟知的ffmpeg,將ffmpeg移植到anroid平臺(tái),編譯成so文件,由jni 調(diào)用,可以實(shí)現(xiàn)音視頻的分離、裁剪、拼合、加字幕、濾鏡等功能。

  • 第二個(gè)就是android 自帶的MediaCodec 框架,MediaCodec框架底層調(diào)用的是StageFright庫(kù),StageFright庫(kù)是默認(rèn)封裝在android系統(tǒng)里面的。

  • 第三個(gè),如果只是做視頻音頻混合的話,可以用這個(gè)開源工程mp4parser使用MediaCodec 類進(jìn)行編碼壓縮,視頻壓縮為H.264,音頻壓縮為aac,使用MediaMuxer 將音視頻合成為MP4。

4. 可行性方案的優(yōu)缺點(diǎn)

功能多少方面:

ffmpeg 無(wú)疑排第一位,他集合了視頻編解碼、視頻濾鏡、流媒體推流、音頻各種特效等等,基本上你能想到的功能都在里面。
第二位當(dāng)是Android的親兒子,MediaCodec。MediaCodec涵蓋了音視頻解復(fù)用、音頻解碼、視頻解碼、音頻編碼、視頻編碼、音視頻合并的整個(gè)流程。跟ffmpeg相比,MediaCodec 更接近底層硬件。這個(gè)方案如果想要實(shí)現(xiàn)視頻的濾鏡、字幕、拼接等功能的話,需要自己配合OpenGL ES 來(lái)實(shí)現(xiàn),另外,音視頻拼接的話,要考慮到不同音頻采樣率的重采樣問(wèn)題,音頻重采用問(wèn)題,需要懂得傅立葉變換相關(guān)的離散信號(hào)變換方法,如果要實(shí)現(xiàn)音頻特效,如變聲、均衡器的話,也需要懂得上述信號(hào)變換方法。因此,很少公司會(huì)采用。mp4praser,可以實(shí)現(xiàn)音視頻編解碼及編輯。

學(xué)習(xí)門檻:

如果只是做視頻轉(zhuǎn)碼、加文字、圖片特效等,ffmpeg和MediaCodec 旗鼓相當(dāng),mp4parser最低(但是基于mp4parser的資料比較少,其實(shí)也未必)。如果是要拼接視頻、做音頻的變聲、均衡器特效的話,MediaCodec是難度最高的,因?yàn)檫@一切需要你從底層原理做起。

運(yùn)行效率:

MediaCodec硬解硬編最快,ffmpeg硬解硬編方案稍慢(注意,2017年5月以后最新版ffmpeg已經(jīng)整合了MediaCodec,不再慢了),mp4parser(只能軟解軟編)最慢。

穩(wěn)定性:

MediaCodec和ffmpeg 的硬解硬編方案旗鼓相當(dāng),mp4parser在低配的機(jī)器上可能出現(xiàn)卡頓的問(wèn)題。

打包占用空間:

國(guó)內(nèi)最得最好的ffmpeg硬解硬編方案,其so文件在10+M,MediaCodec由于是純java 代碼,占用空間很容易做到幾百K甚至幾十K。mp4parser也是純Java,開發(fā)包同樣非常小。

5. FFmpeg

ffmpeg 是基于C語(yǔ)言的著名視頻編解碼方案。具有非常強(qiáng)大的功能包括視頻采集功能、視頻格式轉(zhuǎn)換、視頻抓圖、給視頻加水印等。國(guó)內(nèi)有也有不少的公司將ffmpeg 移植到iOS和android 平臺(tái)進(jìn)行視頻處理,例如,美拍、秒拍等。當(dāng)前眾多的視頻SDK中, 大都是封裝ffmpeg對(duì)視頻進(jìn)行轉(zhuǎn)碼, 壓縮, 裁剪的處理。優(yōu)點(diǎn)是ffmpeg發(fā)展到現(xiàn)在已經(jīng)相對(duì)成熟, 支持的視頻格式較多。但是缺點(diǎn)有:

  • 速度慢,用cpu來(lái)執(zhí)行視頻數(shù)據(jù)的處理屬于軟解碼, 效率并不高;
  • 增加包的體積,一般好的sdk(如阿里云短視頻sdk) 有20m上下, 這樣的sdk合入應(yīng)用后, 對(duì)應(yīng)用大小有一定的影響。

FFmpeg本質(zhì)上可以看做是媒體處理工具的集合,包含了很多的媒體文件處理工具,例如媒體文件格式解析工具、編解碼器等,這些工具實(shí)際上就是一個(gè)個(gè)的庫(kù),而FFmpeg的命令行程序?qū)嶋H上就是對(duì)這些庫(kù)的一種包裝,在調(diào)用命令行程序時(shí)也是通過(guò)底下的這些庫(kù)來(lái)完成操作。這些庫(kù)有的是編譯時(shí)可選的,而且FFmpeg也支持一些外部的庫(kù),例如x264、MediaCodec。FFmpeg由于提供了很多的編解碼器,而且它的媒體操作也很豐富,所以可以支持非常多的媒體類型,同時(shí)很多的處理功能也已經(jīng)由FFmpeg提供,使用者只需要去調(diào)用即可,所以不少的編輯處理功能可以相對(duì)簡(jiǎn)單地完成開發(fā)。
適用場(chǎng)景:多平臺(tái)使用(例如不同芯片廠商的手機(jī)),短時(shí)間攝像。

6. MediaCodec

MediaCodec提供的功能就相對(duì)單一,它基本上只用來(lái)完成編解碼相關(guān)的功能。以整個(gè)視頻轉(zhuǎn)碼流程舉例,大致需要幾個(gè)步驟:解封裝->解碼->濾鏡處理等操作->編碼->封裝,MediaCodec只提供編解碼功能,而其它的功能則需要其它組件,如MediaExtractor以及MediaMuxer來(lái)完成。但是MediaCodec在編解碼時(shí)提供硬件編解碼功能,其好處是非常明顯的,效率很高,且CPU占用大幅降低。如果不使用硬件編解碼的話,很多的轉(zhuǎn)碼過(guò)程的時(shí)長(zhǎng)實(shí)在長(zhǎng)得是令人無(wú)法忍受,放到APP上簡(jiǎn)直就是無(wú)法使用的功能。畢竟一段很短的視頻,轉(zhuǎn)碼要好幾分鐘,發(fā)燙還嚴(yán)重,體驗(yàn)肯定是不行的。MediaCodec的缺點(diǎn)就是一定程度上會(huì)依賴于設(shè)備,由于MediaCodec的硬解碼實(shí)際上是由廠商所提供的,同時(shí)安卓設(shè)備的硬件相互之間差異很大,所以在硬解碼實(shí)現(xiàn)上自然也有所差別,就導(dǎo)致了一樣的程序,一些設(shè)備上可以正常跑,而在另一些設(shè)備上則可能會(huì)出問(wèn)題,此時(shí)就需要自行提供兼容性上的支持。

適用場(chǎng)景:有固定的硬件方案,無(wú)需移植(例如智能家具產(chǎn)品),需要長(zhǎng)時(shí)間攝像。

7. FFmpeg和MediaCodec對(duì)比

作一個(gè)簡(jiǎn)單的比喻:FFmpeg就像一個(gè)工具箱,而MediaCodec就像一類功能強(qiáng)大,但是使用范圍相對(duì)受限且不夠靈活的工具。

  • 1.FFmpeg也有對(duì)MediaCodec的支持,在編譯出合適的庫(kù)后,可以通過(guò)FFmpeg的api來(lái)調(diào)用MediaCodec,但只能使用解碼功能。
  • 2.MediaCodec并非只代表硬編解碼,它事實(shí)上可以看做是一種服務(wù),廠商將自己的編解碼方案預(yù)先注冊(cè)于服務(wù)中,而用戶在需要時(shí)再通過(guò)服務(wù)去調(diào)用相應(yīng)的編解碼器來(lái)完成任務(wù)。MediaCodec支持硬件編解碼以及軟件編解碼,可以自行選擇需要使用的編解碼器。
  • 3.FFmpeg在使用MediaCodec時(shí),使用的方式和JAVA調(diào)用是類似的,F(xiàn)Fmpeg會(huì)通過(guò)JNI的callXXmethod去調(diào)用MediaCodec的方法,這個(gè)過(guò)程其實(shí)和JAVA中的調(diào)用沒(méi)有區(qū)別,但是FFmpeg通過(guò)封裝MediaCodec的操作,使得MediaCodec可以按照FFmpeg的編解碼流程進(jìn)行調(diào)用。
  • 4.MediaCodec它本身并不是Codec,它是通過(guò)調(diào)用底層編解碼組件具有Codec能力。

8. 開源方案

基于ffmpeg 的免費(fèi)軟解軟編方案在github.com有很多,例如:EpMedia,硬解硬編方案還沒(méi)有看到。商業(yè)收費(fèi)的方案有趣拍、美攝等。不過(guò)這些商業(yè)方案是按年收費(fèi)的有點(diǎn)小貴。

基于MediaCodec 的免費(fèi)開源方案有m4m,videotranscoder等,不過(guò)這些開源方案,表面看上去功能很強(qiáng)大,實(shí)際使用的時(shí)候會(huì)遇到不少坑,只適用于對(duì)MediaCodec的原理進(jìn)行研究。

六.音視頻解碼

image.png

解協(xié)議的作用,就是將流媒體協(xié)議的數(shù)據(jù),解析為標(biāo)準(zhǔn)的相應(yīng)的封裝格式數(shù)據(jù)。視音頻在網(wǎng)絡(luò)上傳播的時(shí)候,常常采用各種流媒體協(xié)議,例如HTTP,RTMP,或是MMS等等。這些協(xié)議在傳輸視音頻數(shù)據(jù)的同時(shí),也會(huì)傳輸一些信令數(shù)據(jù)。這些信令數(shù)據(jù)包括對(duì)播放的控制(播放,暫停,停止),或者對(duì)網(wǎng)絡(luò)狀態(tài)的描述等。解協(xié)議的過(guò)程中會(huì)去除掉信令數(shù)據(jù)而只保留視音頻數(shù)據(jù)。例如,采用RTMP協(xié)議傳輸?shù)臄?shù)據(jù),經(jīng)過(guò)解協(xié)議操作后,輸出FLV格式的數(shù)據(jù)。

1. 解封裝

解封裝的作用,就是將輸入的封裝格式的數(shù)據(jù),分離成為音頻流壓縮編碼數(shù)據(jù)和視頻流壓縮編碼數(shù)據(jù)。封裝格式種類很多,例如MP4,MKV,RMVB,TS,F(xiàn)LV,AVI等等,它的作用就是將已經(jīng)壓縮編碼的視頻數(shù)據(jù)和音頻數(shù)據(jù)按照一定的格式放到一起。例如,F(xiàn)LV格式的數(shù)據(jù),經(jīng)過(guò)解封裝操作后,輸出H.264編碼的視頻碼流和AAC編碼的音頻碼流。

2. 解碼

解碼的作用,就是將視頻/音頻壓縮編碼數(shù)據(jù),解碼成為非壓縮的視頻/音頻原始數(shù)據(jù)。音頻的壓縮編碼標(biāo)準(zhǔn)包含AAC,MP3,AC-3等等,視頻的壓縮編碼標(biāo)準(zhǔn)則包含H.264,MPEG2,VC-1等等。解碼是整個(gè)系統(tǒng)中最重要也是最復(fù)雜的一個(gè)環(huán)節(jié)。通過(guò)解碼,壓縮編碼的視頻數(shù)據(jù)輸出成為非壓縮的顏色數(shù)據(jù),例如YUV420P,RGB等等;壓縮編碼的音頻數(shù)據(jù)輸出成為非壓縮的音頻抽樣數(shù)據(jù),例如PCM數(shù)據(jù)。

3. 音頻同步

視音頻同步的作用,就是根據(jù)解封裝模塊處理過(guò)程中獲取到的參數(shù)信息,同步解碼出來(lái)的視頻和音頻數(shù)據(jù),并將視頻音頻數(shù)據(jù)送至系統(tǒng)的顯卡和聲卡播放出來(lái)。

4. 硬解碼和軟解碼

硬解

字面上理解就是用硬件解碼。通過(guò)顯卡的視頻加速功能對(duì)高清視頻進(jìn)行解碼??梢岳斫鉃橛幸粋€(gè)專門的電路板來(lái)進(jìn)行視頻的解碼工作,是依靠GPU。
調(diào)用GPU的專門模塊編碼來(lái)解碼,減少CPU運(yùn)算。顯卡核心GPU擁有獨(dú)特的計(jì)算方法,解碼效率非常高,這樣不但能夠減輕CPU的負(fù)擔(dān),還有著低功耗,發(fā)熱少等特點(diǎn)。

但是,由于硬解碼起步比較晚,軟件和驅(qū)動(dòng)對(duì)他的支持度很低,基本上硬解碼內(nèi)置什么樣的模塊,就解碼什么樣的視頻,面對(duì)網(wǎng)上各色各樣的視頻編碼樣式,兼容性不好。此外,硬解碼的濾鏡、字幕、畫質(zhì)方面都做的不夠理想。

對(duì)于android設(shè)備,目前用得比較多的芯片就是高通、海思和聯(lián)發(fā)科,這些芯片大都集成了很多的功能,CPU、GUP、DSP、ISP包括視頻解碼、音頻解碼等等。
在Android中使用硬件解碼直接使用MediaCodec就可以了,雖然MediaPlayer也是硬件解碼,但是被封裝得太死了,支持的協(xié)議很少。而MediaCodec就很好拓展,我們可以根據(jù)流媒體的協(xié)議和設(shè)備硬件本身來(lái)自定義硬件解碼,代表播放器就是Google的ExoPlayer。

軟解

字面上理解就是用軟件解碼。但是實(shí)際上還是要硬件支撐。這個(gè)硬件就是CPU。
在軟解碼過(guò)程中,需要對(duì)大量的視頻信息進(jìn)行運(yùn)算,所以對(duì)CPU性能的要求非常高。尤其是對(duì)高清大碼率的視頻來(lái)說(shuō),巨大的運(yùn)算量就會(huì)造成轉(zhuǎn)換效率低,發(fā)熱量高等問(wèn)題。
我們最常見(jiàn)的視頻軟解碼開源庫(kù)就是FFmpeg。目前基于FFmpeg的開源播放器有B站的ijkplayer
不過(guò),軟解碼不需要過(guò)多的硬件支持,兼容性非常高,即使出現(xiàn)新的視頻編碼格式,只要安裝好相應(yīng)的解碼器文件,就可以順利播放。而且軟解碼擁有豐富的濾鏡,字幕,畫面處理優(yōu)化等效果,只有你CPU夠強(qiáng)悍,就能夠?qū)崿F(xiàn)更加出色的畫面效果。

5. 硬解和軟解總結(jié)

在Android設(shè)備硬件支持的情況下優(yōu)先使用Android設(shè)備的硬件解碼,減少CPU的占用,更加省電。
在Android設(shè)備硬解不支持的情況下選擇使用軟解碼,不管怎么樣,視頻至少能夠播放,具有更好的適應(yīng)性,但是增加了CPU的占用,更加費(fèi)電,軟硬結(jié)合才是最好。

七. Android平臺(tái)音視解碼播放器選擇

在Android中播放視頻很簡(jiǎn)單,可以使用MediaPlayer+SurfaceView或者VideoView設(shè)置一個(gè)視頻文件路徑就可以實(shí)現(xiàn)播放了。但是如果想對(duì)音視頻再進(jìn)行處理,比如視頻播放過(guò)程中增加水印,或者對(duì)視頻進(jìn)行轉(zhuǎn)碼,就需要對(duì)視頻進(jìn)行編解碼處理了。

1. MediaPlayer

在Android系統(tǒng)中對(duì)于視頻播放器有原生的實(shí)現(xiàn)MediaPlayer, 以及將MediaPlayer,SurfaceView封裝在一起的VideoView, 兩者都只是使用硬解播放,基本上只支持本地和HTTP協(xié)議的視頻播放,擴(kuò)展性都很差,只適合最簡(jiǎn)單的視頻播放需求。

Android原生播放器,支持格式較少:支持mp4,3gp,資源文下支持mkv,使用比較簡(jiǎn)單,但是拓展性比較差。不需要集成第三方庫(kù),不占用apk體積。

2. ijkplayer

嗶哩嗶哩開源的基于ffmpeg開發(fā)的一款播放器,功能就比較強(qiáng)大了,如果只是使用它進(jìn)行播放,集成也較為簡(jiǎn)單,使用也和MediaPlayer差不多,但是要定制化需求,就有一定的門檻高度。支持軟硬編解碼,支持倍速播放,可以定制化集成需要的功能,集成占用體積也很小。

3. ExoPlayer(基本來(lái)自于官方文檔翻譯)

谷歌出品,推薦使用的播放器。同RecyclerView一樣定制化程度非常高。并加入了對(duì)DASH和HLS等直播協(xié)議的支持,但也只支持硬碼,如果項(xiàng)目中只需要支持對(duì)H264格式的視頻播放,以及流媒體協(xié)議比較常規(guī)(比如HTTP,HLS),基于ExoPlayer定制也是不錯(cuò)的選擇。

優(yōu)點(diǎn):

  • 支持動(dòng)態(tài)的自適應(yīng)流HTTP(DASH) 和 平滑流,任何目前MediaPlayer支持的視頻格式(同時(shí)它還支持HTTP直播了(HLS),MP4,MP3,WebM,M4A,MPEG-TS 和 AAC).
  • 支持高級(jí)的HLS特性,例如正確處理 EXT-X-DISCONTINUITY 標(biāo)簽。
  • 無(wú)縫合并、連接和循環(huán)媒體的能力。
  • 支持自定義使用場(chǎng)景。ExoPlayer專門為此設(shè)計(jì),它允許將許多組件替換為自定義實(shí)現(xiàn),它提供了低等級(jí)的媒體API,例如:MediaCodec,AudioTrack,MediaDrm,可以用于建立自定義媒體播放的解決方案。。以第三方依賴的方式集成,可以隨應(yīng)用升級(jí)版本。更少的適配性問(wèn)題,更少的設(shè)備特定的問(wèn)題和更少的行為變化, 在不同的設(shè)備和android的版本,可以接入ffmpeg。

缺點(diǎn):

  • 相對(duì)于MediaPlayer更耗電:但是Android Q以開發(fā)audio affload,可以減低功耗。
  • 最低API要求為16,早期版本不支持自動(dòng)檢查需要播放的媒體格式,后續(xù)的版本已經(jīng)支持。

4. 特性

功能支持情況

功能 MediaPlayer IjkPlayer ExoPlayer
調(diào)整顯示比例 支持 支持 支持
滑動(dòng)調(diào)節(jié)播放進(jìn)度、聲音、亮度 支持 支持 支持
雙擊播放、暫停 支持 支持 支持
重力感應(yīng)自動(dòng)進(jìn)入/退出全屏以及手動(dòng)進(jìn)入/退出全屏 支持 支持 支持
倍速播放 不支持 支持 支持
視頻截圖(使用 SurfaceView 時(shí)都不支持,默認(rèn)用的是 TextureView) 支持 支持 支持
列表小窗全局懸浮播放 支持 支持 支持
連續(xù)播放一個(gè)列表的視頻 支持 支持 支持
廣告播放 支持 支持 支持
邊播邊緩存,使用了AndroidVideoCache 實(shí)現(xiàn) 支持 支持 支持
彈幕,使用DanmakuFlameMaster 實(shí)現(xiàn) 支持 支持 支持
多路播放器同時(shí)播放 支持 支持 支持
沒(méi)有任何控制 UI 的純播放 支持 支持 支持
Android 8.0 畫中畫 支持 支持 支持
無(wú)縫銜接播放 支持 支持 支持
抖音 支持 支持 支持

協(xié)議/格式支持情況(只列舉常用格式/協(xié)議)

協(xié)議/格式 MediaPlayer IjkPlayer ExoPlayer
https 支持 支持 支持
rtsp 不支持 支持 不支持
rtmp 不支持 支持 支持
ffconcat 不支持 支持 不支持
file(本地視頻) 支持 支持 支持
android.resource(raw) 支持 支持 支持
assets 中的視頻 支持 支持 支持
mp4 支持 支持 支持
m3u8 支持 支持 支持
flv 支持 支持 可播放,無(wú)法 seek 進(jìn)度

5. 建議

  • 1.如果已知的播放場(chǎng)景比較簡(jiǎn)單,例如小視頻場(chǎng)景,都是mp4視頻(h264/aac格式),建議使用ExoPlayer,沒(méi)有比這更適合的;
  • 2.涉及到多種視頻交互形式,直播、長(zhǎng)視頻等,還是建議引入ijkplayer等軟件的形式;
  • 3.如果Android平臺(tái)不介意包大小,推薦使用VLC,VLC更新頻繁,官方維護(hù)相當(dāng)給力;如果比較關(guān)注包大小,建議選擇ijkplayer,ijkplayer目前的缺點(diǎn)是維護(hù)的不那么勤了;
  • 4.長(zhǎng)遠(yuǎn)來(lái)看,國(guó)內(nèi)很多播放器都從接入ijkplayer開始,逐漸演化,去掉不適合自己產(chǎn)品的代碼,引入自己需要的module,漸漸變成自己的播放器;

6. 開源音視頻播放器UI方案

GSYVideoPlayer
DKVideoPlayer

參考文章:
Android 音頻采集(原始音頻)
音視頻篇 - Android 音視頻涉及到的技術(shù)
Android音視頻編碼基礎(chǔ)一
微信 Android 視頻編碼爬過(guò)的那些坑
Android視頻技術(shù)探索之旅:美團(tuán)外賣商家端的實(shí)踐
Android音視頻開發(fā)之MediaCodec編解碼
Android視頻處理之MediaCodec-1-簡(jiǎn)介
Android視頻處理之MediaCodec-2-使用
Android視頻處理之MediaCodec-3-播放視頻
Android視頻處理之MediaCodec-4-視頻幀轉(zhuǎn)圖片
Android視頻處理之MediaCodec-5-生成mp4視頻
Android視頻處理之MediaCodec-6-給視頻加水印
Android 音視頻編輯經(jīng)驗(yàn)總結(jié)及開源工程分享
Android 音視頻開發(fā)學(xué)習(xí)思路
從開發(fā)小白到音視頻專家
android音視頻開發(fā)基礎(chǔ)4--FFmpeg 入門
視音頻編解碼技術(shù)零基礎(chǔ)學(xué)習(xí)方法
Ijkplayer、ExoPlayer、VLC播放器綜合比較
ijkplayer點(diǎn)播和直播視頻 問(wèn)題 解決及優(yōu)化,視頻播放中可能有的bug
Android視頻編輯器(一)通過(guò)OpenGL預(yù)覽、錄制視頻以及斷點(diǎn)續(xù)錄等
DevYK
cain_huang
Android openGl開發(fā)詳解(二)——通過(guò)SurfaceView,TextureView,GlSurfaceView顯示相機(jī)預(yù)覽(附Demo)
開發(fā)的貓
Android | 音視頻方向進(jìn)階路線及資源合集

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容