Android中直播視頻技術探究之---基礎知識大綱介紹

來源:互聯網
上載者:User

標籤:

一、前言

最近各種ApsaraVideo for Liveapp到處都是,各種霸屏,當然我們也是需要體驗的,關於ApsaraVideo for Live的軟體這裡就不介紹了,在不是技術的人來看,直播是一種潮流,是一種娛樂方式,但是作為一個高技術的,我們除了看看,更重要的是學習技術,其實Android中的視頻技術沒什麼說的,因為網上的資料很多,但是之前的視頻技術大部分都出現在了視頻播放,就是主流的視頻播放器,那個最重要的一個技術就是視頻的編解碼,這個也會在後續文章中詳細介紹視頻的處理技術。但是現在直播的技術是在之前的視頻技術上又有了一個要求就是視頻錄製,現在錄製很多是藉助於牛逼的硬體網路攝影機。但是除了這個技術,還有其他的我們使用行動裝置也可以去解決這個問題。這個後續也會說道如何使用裝置去錄製視頻。


二、知識概要

從這篇文章開始我們就來介紹一下關於Android中的視頻處理,這裡主要包括:Android中的網路攝影機技術,錄製視頻,視頻播放器等知識點,本篇文章是介紹大體的知識點,為後續的章節知識點做鋪墊,其實以前在學習Android中最怕就是圖片和視頻處理方面的技術,因為這些技術有一個基本的要求就是位元組操作,考慮很多位元組流處理,這個在Android中有一個類ByteBuffer,這個類將會貫穿我們後續所有章節的知識點,這個類也是我們下一篇文章的中點,在視頻流處理中這個類將不可或缺的。


下面我們先來看一張Android中視頻的處理大綱圖解:


這張圖片太大了,如果看的不夠清楚可以下載,然後放大查看。下面就來一一介紹這張圖中涉及到的知識點:


三、知識結構

第一、視頻編碼

Android中視頻編碼有兩種方式,主要是兩個核心的類,一個是MediaCodec和MediaRecorder,這兩個類有什麼區別呢?其實很好理解,他們都可以對視頻進行編碼,但是唯一不同的是MediaCodec更偏向原生,而MediaRecorder偏向的上層封裝。

1、MediaCodec類

MediaCodec可以處理具體的視頻流,主要有這幾個方法:

getInputBuffers:擷取需要編碼資料的輸入資料流隊列,返回的是一個ByteBuffer數組

queueInputBuffer:輸入資料流入隊列

dequeueInputBuffer:從輸入資料流隊列中取資料進行編碼操作

getOutputBuffers:擷取編解碼之後的資料輸出資料流隊列,返回的是一個ByteBuffer數組

dequeueOutputBuffer:從輸出隊列中取出編碼操作之後的資料

releaseOutputBuffer:處理完成,釋放ByteBuffer資料


看如:


這裡看到:

視頻流有一個輸入隊列,和輸出隊列,分別對應getInputBuffers和getOutputBuffers這兩個方法擷取這個隊列,然後對於輸入資料流這端有兩個方法一個是queueInputBuffers是將視頻流入隊列,dequeueInputBuffer是從輸入資料流隊列中取出資料進行編解碼操作,在輸出端這邊有一個dequeueOutputBuffer方法從輸出隊列中擷取視頻資料,releaseOutputBuffers方法將處理完的輸出視頻流資料ByteBuffer放回視頻流輸出隊列中,再次迴圈使用。這樣視頻流輸入端和輸出端分別對應一個ByteBuffer隊列,這些ByteBuffer可以重複使用,在處理完資料之後再放回去即可。

所以這裡看到MediaCodec類處理視頻的時候可以接觸到視頻流資料的,這裡比如我們如果有一些特殊需求,比如視頻的疊加技術,添加字幕等就可以在這裡處理了。同時MediaCodec有一個方法:createInputSurface可以設定視頻源輸入Surface類型,同時也是可以通過configure方法設定視頻輸出Surface類型。


2、MediaRecorder類                    

MediaRecorder這個類相對於MediaCodec簡單,因為他封裝的很好,直接就是幾個介面來完成視頻錄製,比如視頻的編碼格式,視頻的儲存路勁,視頻來源等,用法簡單,但是有一個問題就是不能接觸到視頻流資料了,處理不了原生的視頻資料了。這個也是他和MediaCodec最大的區別,他完成不了視頻的疊加技術的。


注意:

關於MediaRecorder這個類,其實他和Android中的一個命令是相對應的,就是:adb screenrecord。這個類還有一個地方需要注意的就是他有一個方法:setVideoSource,可以設定視頻來源,代碼後續文章會介紹,主要就兩個來源:一個是來自於裝置的網路攝影機Camera,一個是來自於Surface,關於Surface這個類後面會介紹。


注意:

現在視頻編碼的格式都是H264的,關於H264格式說明如下:

H.264,MPEG-4,MPEG-2等這些都是壓縮演算法,畢竟頻寬是有限的,為了獲得更好的映像的傳輸和顯示效果,就不斷的想辦法去掉一些資訊,轉換一些資訊等等,這就是這些壓縮演算法的做的事情。H.264最大的優勢是具有很高的資料壓縮比率,在同等映像品質的條件下,H.264的壓縮比是MPEG-2的2倍以上,是MPEG-4的1.5~2倍。舉個例子,原始檔案的大小如果為88GB,採用MPEG-2壓縮標準壓縮後變成3.5GB,壓縮比為25∶1,而採用H.264壓縮標準壓縮後變為879MB,從88GB到879MB,H.264的壓縮比達到驚人的102∶1!H.264為什麼有那麼高的壓縮比?低碼率(Low Bit Rate)起了重要的作用,和MPEG-2和MPEG-4 ASP等壓縮技術相比,H.264壓縮技術將大大節省使用者的下載時間和資料流量收費。尤其值得一提的是,H.264在具有高壓縮比的同時還擁有高品質流暢的映像。寫了這麼多,舉個例來說下,比如移動電視,我們接收的到的映像訊號一般是H.264格式的,行動裝置接收到後,需要先解碼成原始的YUV碼流,然後又轉換成RGB碼流,將一幀一幀的RGB資料放到顯存上才能顯示出映像。雖然傳輸快了,得是增加了裝置的解碼成本,不過總體來講肯定是值得的。現在PC上的顯卡慢慢都要整合H.264的硬體解碼,據說蘋果的最新產品IPAD也是有了這個硬解碼。而YUV到RGB的轉換,很多ARM晶片上都有了。


第二、視頻資料來源

這裡說到的視頻資料來源就是視頻編碼器需要編碼的視頻來源,在行動裝置中,我們擷取知道兩個地方可以擷取視頻,一個是來自於網路攝影機Camera,一個是來自於裝置螢幕(案頭)。

這裡就需要介紹兩個類了:一個是網路攝影機Camera,一個是Android5.0新增的螢幕錄製類MediaProjection和VirtualDisplay。

1、Camear類

Camera這個類在現在的直播以及美顏相機等app很重要的,他是行動裝置採取視頻和圖片資訊的一個重要渠道,他的用法很簡單,分為自拍和後置網路攝影機,可以設定方向,大小等參數,最重要的是,他還需要一個預覽介面,他一般預覽有兩個方法:setPreviewDisplay和setPreviewTexture,第一個方法是設定SurfaceHolder類型的,第二個方法是設定SurfaceTexture類型的關於這兩個類型,後面會說到的。但是這裡會有一個疑惑了就是來自於網路攝影機的資料會被預覽,但是我們想處理網路攝影機的資料該怎麼辦呢?這裡就需要藉助Camera的一個回調介面:PreviewCallback,這個介面有一個回調方法:onPreviewFrame(byte[] data...),看到這個方法我們都知道了這個是網路攝影機採集的視頻資料的每一幀資料,我們可以在這裡擷取每一幀資料然後進行處理,像現在的美顏相機,就是在這裡擷取到一幀資料,然後在做濾鏡效果,然後產生一張圖片即可。當然這裡可以錄製美白視頻也是可以的哦。那麼在這裡我們就可以擷取到視頻的資料來源了。

那麼上面的MediaCodec類可以使用getInputBuffer類擷取視頻流輸入隊列,我們可以在這個回調方法中擷取到資料,然後傳入到這個隊列中,進行編碼操作,但是需要注意的是資料格式需要做一次轉化,後面會介紹到。同時MediaRecorder類可以通過setVideoSource方法直接設定視頻源。


2、MediaProjection類和VirtualDisplay類

這兩個類主要是Android5.0新增的一個api,就是專門用來錄製裝置視頻的,不過在使用的過程中需要許可權授權的,如果不授權還是很危險的,假如有惡意的軟體在後台偷偷的錄製裝置螢幕視頻,就知道你幹了啥,那是很危險的。需要通過MediaProjection這個類來擷取VirtualDiaplay類,同時需要傳入一個重要的參數,就是錄製螢幕視頻預覽的Surface類。

那麼這裡就可以和上面的視頻編碼器聯絡到一起了,MediaCodec有一個createInputSurface方法可以設定視頻源類型的Surface,而且MediaRecoder這個類也是可以通過setVideoSource方法設定Surface類型的視頻輸入源的,在這裡如果想實現裝置螢幕錄製視頻可以通過上面的兩個視頻編碼類別進行操作然後儲存即可。


第三、視頻資料格式

我們上面看到了兩種視頻源,一個來自於網路攝影機,一個來自於螢幕,但是這兩個資料來源都有自己的格式,所以這裡還需要介紹一下資料格式,以及他們之間的轉化。我們平常接觸的一般都是ARGB色彩空間,A代表透明度,RGB是三原色,但是在處理視頻的時候特別是在錄製行動裝置的時候視頻有一個色彩空間:YUV

它也是一種色彩空間,為什麼要出現YUV,主要有兩個原因,一個是為了讓彩色訊號相容黑白電視機,另外一個原因是為了減少傳輸的頻寬。YUV中,Y表示亮度,U和V表示色度,總之它是將RGB訊號進行了一種處理,根據人對亮度更敏感些,增加亮度的訊號,減少顏色的訊號,以這樣“欺騙”人的眼睛的手段來節省空間的。YUV的格式也很多,不過常見的就是422和420格式。在一般的技術開發中,常用的還是yCbCr,這是一種420格式,也稱作I420,注意這個YV12的資料排列剛好是相反的。

Y,U,V它們之間是有一個比例,這個比例不是唯一的,比如Y,U,V三個分量的數量比是4:1:1.也就是說每四個像素共用一對UV。如果是一個30*40的幀,那麼有1200個Y分量,分別有300個U和300個V分量。總共有1200*1.5這麼多個值。

1、N21/YV12

這個格式一般是裝置的網路攝影機Camera採集的資料,就是我們上面說到的onPreviewFrame(byte[] data...)每一幀資料,其實是N21或者是YV12格式的,具體哪種格式,可以設定的。所以這裡比如我們想擷取一幀資料進行處理,一定要記得格式的轉化,比如這裡想儲存一張圖片,那麼這裡就需要將NV21轉化成RGB格式的,或者直接使用系統類別YUVImage,產生一張圖片。


2、YUV420P(I420)/YUV420SP(N12)

YUV420有打包格式(Packed),同時還有平面格式(Planar),即Y、U、V是分開儲存的,每個分量佔一塊地方,其中Y為width*height,而U、V合占Y的一半,該種格式每個像素佔12位元。根據U、V的順序,分出2種格式,U前V後即YUV420P,也叫I420,V前U後,叫YV12(YV表示Y後面跟著V,12表示12bit)。另外,還有一種半平面格式(Semi-planar),即Y單獨佔一塊地方,但其後U、V又緊挨著排在一起,根據U、V的順序,又有2種,U前V後叫NV12,在國內好像很多人叫它為YUV420SP格式;V前U後叫NV21。這種格式似乎比NV16稍受歡迎。

這種格式一般是錄製螢幕視頻源的格式,就是上面的MediaProjection類,所以我們上面提到的一個將錄製裝置螢幕視頻然後進行編碼儲存的話,就需要把網路攝影機的N21/YV12格式轉化成編碼器識別的YUV420P/YUV420SP格式的。


第四、視頻預覽畫面

1、SurfaceView類

這個類,我們在開發應用的時候可能會用到的很少,在開發遊戲中會用到一些,我們在開發應用製作特殊動畫的時候只需要繼承View類,然後在onDraw中開始繪製就好了,這個類也可以做到繪製功能,上面看到視頻源需要一個預覽功能,需要一個Surface,其實SurfaceView就是View+Surface結合體,Surface是映像繪製資料層,而View只是一個展現層,中間還有一個SurfaceHolder作為連結著,他們的關係如下:


可以通過SurfaceHolder的getSurface方法擷取一個Surface類即可。


所以這裡的我們在使用SurfaceView作為一個視頻預覽介面的時候,其實是擷取到Surface或者是SurfaceHolder即可,比如網路攝影機預覽介面可以通過Camera的setPreviewDisplay方法設定SurfaceHolder類型即可,螢幕錄製介面可以通過VirtualDisplay類參數傳遞一個輸入Surface類型。


2、TextureView類

TextureView在4.0(API level 14)中引入。它可以將內容流直接投影到View中,可以用於實現Live preview等功能。和SurfaceView不同,它不會在WMS中單獨建立視窗,而是作為View hierachy中的一個普通View,因此可以和其它普通View一樣進行移動,旋轉,縮放,動畫等變化。值得注意的是TextureView必須在硬體加速的視窗中。它顯示的內容流資料可以來自App進程或是遠端進程。從類圖中可以看到,TextureView繼承自View,它與其它的View一樣在View hierachy中管理與繪製。TextureView重載了draw()方法,其中主要把SurfaceTexture中收到的映像資料作為紋理更新到對應的HardwareLayer中。SurfaceTexture.OnFrameAvailableListener用於通知TextureView內容流有新映像到來。SurfaceTextureListener介面用於讓TextureView的使用者知道SurfaceTexture已準備好,這樣就可以把SurfaceTexture交給相應的內容來源。Surface為BufferQueue的Producer介面實作類別,使生產者可以通過它的軟體或硬體渲染介面為SurfaceTexture內部的BufferQueue提供graphic buffer。


這個類其實和SurfaceView差不多,只是他內部不是依賴於Surface和SurfacHolder了,而是SurfaceTexture,關於SurfaceTexture它的好處就很多了:

SurfaceTexture是從Android3.0(API 11)加入的一個新類。這個類跟SurfaceView很像,可以從camera preview或者video decode裡面擷取映像流(image stream)。但是,和SurfaceView不同的是,SurfaceTexture在接收映像流之後,不需要顯示出來。有做過Android camera開發的人都知道,比較頭疼的一個問題就是,從camera讀取到的預覽(preview)映像流一定要輸出到一個可見的(Visible)SurfaceView上,然後通過Camera.PreviewCallback的onPreviewFrame(byte[] data, Camera camera)函數來獲得映像幀資料的拷貝。這就存在一個問題,比如希望隱藏網路攝影機的預覽映像或者對每一幀進行一些處理再顯示到手機顯示屏上,那麼在Android3.0之前是沒有辦法做到的,或者說你需要用一些小技巧,比如用其他控制項把SurfaceView給擋住,注意這個顯示原始camera映像流的SurfaceView其實是依然存在的,也就是說被擋住的SurfaceView依然在接收從camera傳過來的映像,而且一直按照一定幀率去重新整理,這是消耗cpu的,而且如果一些參數設定的不恰當,後面隱藏的SurfaceView有可能會露出來,因此這些小技巧並不是好辦法。但是,有了SurfaceTexture之後,就好辦多了,因為SurfaceTexture不需要顯示到螢幕上,因此我們可以用SurfaceTexture接收來自camera的映像流,然後從SurfaceTexture中取得映像幀的拷貝進行處理,處理完畢後再送給另一個SurfaceView用於顯示即可。

而且SurfaceTexture可以輕鬆的擷取視頻的時間戳記資料,不需要我們人工的去計算,同時他還有一個強大的功能就是和Render結合了,而Render是後面要說到GLSurfaceView的核心,就是OpenGL技術了,對於後續圖片和視頻的濾鏡處理,這個發揮著巨大的作用,因為它對映像流的處理並不直接顯示,而是轉為GL外部紋理,因此可用於映像流資料的二次處理(如Camera濾鏡,案頭特效等)。比如Camera的預覽資料,變成紋理後可以交給GLSurfaceView直接顯示,也可以通過SurfaceTexture交給TextureView作為View heirachy中的一個硬體加速層來顯示。首先,SurfaceTexture從映像流(來自Camera預覽,視頻解碼,GL繪製情境等)中獲得幀資料,當調用updateTexImage()時,根據內容流中最近的映像更新SurfaceTexture對應的GL紋理對象,對於Camera資料來源的話可以通過setPreviewTexture方法來設定SurfaceTexture類型,錄製螢幕資料來源的話沒有入口可以設定。



3、GLSurfaceView類

GLSurfaceView從Android 1.5(API level 3)開始加入,作為SurfaceView的補充。它可以看作是SurfaceView的一種典型使用模式。在SurfaceView的基礎上,它加入了EGL的管理,並內建了渲染線程。另外它定義了使用者需要實現的Render介面,提供了用Strategy pattern更改具體Render行為的靈活性。作為GLSurfaceView的Client,只需要將實現了渲染函數的Renderer的實作類別設定給GLSurfaceView即可。



這裡看到GLSurfaceView有一個特點就是不是系統幫我們繪製預覽畫面了,而是需要我們自己拿到資料之後自己渲染,同時這裡會有一個單獨的GL線程來進行重新整理資料。


四、流程總結

上面就介紹完了所有類的大致功能以及幾種視頻源採集的資料格式,下面來總結一下:

第一、兩種編碼器MediaCodec和MediaRecorder

MediaCodec可以通過createInputSurface方法設定輸入Surface類型以及configure方法設定輸出Surface類型

MediaRecorder可以通過setVideoSource方法設定視頻源,兩種:一種是網路攝影機,一種是錄製螢幕

這兩種編碼器的區別在於:MediaCodec可以處理詳細的視頻流資訊,但是MediaRecorder封裝太好了,沒辦法處理。


第二、兩種視頻源Camera和MediaProjection

網路攝影機資料來源提供了一個回調介面中的一個回調方法:onPreviewFrame(byte[] data...)可以擷取到視頻的每一幀資料

螢幕資料來源類VirtualDiaplay提供了一個輸入Surface類型的設定入口類型


第三、視頻源格式和視頻編碼資料格式

網路攝影機採集的視頻資料格式是N21和YV12,但是編碼器MediaCodec處理的資料格式是Y420P和Y420SP的,所以這裡需要做一次資料格式的轉化,同樣如果想採集網路攝影機的每一幀圖片做處理的話,還需要把N21格式轉化成RGB格式。


第四、視頻預覽View

1》這裡主要有SurfaceView類型,他主要和SurfaceHolder,Surface相關聯,網路攝影機提供了setPreviewDisplay方法設定SurfaceHolder類型。網路攝影機可以通過SurfaceView進行資料的預覽,錄製螢幕VirtualDisplay可以提供一個設定Surface入口,所以錄製螢幕也可以通過SurfaceView進行資料的預覽。

2》還有就是TextureView類型,他主要和SurfaceTexture類相對應的,而網路攝影機提供了一個setPreviewTexture方法來設定SurfaceTexture類型,但是錄製螢幕的VirtualDisplay沒有,所以網路攝影機可以通過TextureView進行資料預覽,但是錄製螢幕不可以。

3》最後就是GLSurfaceView類型了,他是繼承SurfaceView的,在這基礎上添加了OpenGL技術,用來處理視頻資料和圖片資料的。但是GLSurfaceView和前面兩個預覽View不同的是,他需要拿到資料自己進行渲染預覽,大致流程如下:

GLSurfaceView->setRender->onSurfaceCreated回調方法中構造一個SurfaceTexture對象,然後設定到Camera預覽中->SurfaceTexture中的回調方法onFrameAvailable來得知一幀的資料準備好了->requestRender通知Render來繪製資料->在Render的回調方法onDrawFrame中調用SurfaceTexture的updateTexImage方法擷取一幀資料,然後開始使用GL來進行繪製預覽。


五、使用情境

第一種情境:從網路攝影機採集視頻資料儲存到本地
第一種辦法:
Camera->setPreviewCallback->onPreviewFrame->擷取沒幀資料(N21)->轉化資料格式為Y420SP->給MediaCodec->編碼產生H264格式的視頻流儲存到本地
第二種辦法:
設定MediaRecorder的視頻源為Camera即可,但是這個過程中擷取不到網路攝影機的沒幀資料,做不了處理了。

第二種情境:錄製螢幕視頻資料儲存到本地
MediaProjection->VirtualDisplay->設定輸入Surface(MediaRecorder通過getSurface方法擷取,這裡需要設定MediaRecorder視頻源為Surface格式的)

第三種情境:從網路攝影機中採集資料做每一幀資料處理擷取圖片
第一種方法:使用YUVImage類,將N21/YV12格式變成一個Bitmap資料
第二種方法:擷取每幀資料,將N21/YV12資料格式轉化成ARGB8888格式資料,然後產生圖片
第三種方法:調用Camera的回調介面PictureCallback中的回調方法 onPictureTaken(byte[] data, final Camera camera)直接擷取的data資料就是圖片格式資料

第四種情境:錄製螢幕時擷取一張圖片(螢幕功能)
使用ImageReader->getSurface->設定到VirtualDisplay類中作為輸入的Surface->ImageReader擷取Image圖片即可


第五個情境:對採集的視頻和圖片做濾鏡效果

我們通過Camera的回調方法onPreviewFrame(byte[] data...)來擷取視頻流中每一幀資料,然後藉助強大的OpenGL技術來進行資料處理,做到類似於美顏相機功能


第六個情境:掃描二維碼技術解析

可以藉助Camera,擷取每一幀資料,然後進行二維碼的識別。


六、總結

到這裡我們就介紹完了ApsaraVideo for Live中大致知識結構,兩個資料來源,兩種編碼器,資料格式,三種預覽View,但是我們在預覽View中看到涉及到了OpenGL技術了,沒錯,這個也是我們後續需要介紹的內容,如何使用OpenGL做視頻的濾鏡效果,讓每個直播都那麼白,後續會詳細的結合案例來介紹每個知識點。


更多內容:點擊這裡

關注公眾號,最新Android技術即時推送




Android中直播視頻技術探究之---基礎知識大綱介紹

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.