目錄:
(1)概念解釋 : 硬解、軟解
(2)Intel關於Android MediaCodec的相關說明
正文:
一、硬解、軟解
(1)概念:
a、硬件解碼:硬件解碼是圖形芯片廠商提出的用GPU資源解碼視頻流的方案
b、軟件解碼:相對於硬件解碼,傳統的軟件解碼是用CPU承擔解碼工作
(2)優點:
a、硬解:效率高、功耗低、熱功耗低
b、軟解:具備普遍適應性
(3)缺點:
a、硬解:(a)缺乏有力的支持(包括濾鏡、字幕)、局限性較大(例如打開硬件解碼后PC的節能方面的功能
失效cnq等)、設置較為復雜;
(b)需要硬件有硬件解碼模塊、相關的驅動配合、合適的播放軟件以及對播放軟件的正確設置,缺
一不可。否則無法開啟硬件解碼功能。
b、軟解:主要靠算法解碼,很耗費性能、耗電。
(4)示例(基於Android平台):
a、硬解:Android自帶播放器——VideoView
詳述:
VideoView基於MediaPlayer(也是硬件解碼)實現,但 MediaPlayer 封裝的比較死,對於視頻
編解碼協議支持的較少。代表播放器:VideoView。
而 MediaCodec 則具備很高的拓展性,支持的協議較多,我們可以根據流
媒體的協議和設備硬件本身來自定義硬件解碼。代表播放器:Google的
ExoPlayer。
b、軟解:FFmpeg
詳述:
FFmpeg官網:
https://ffmpeg.org/
FFmpeg教程:
雷霄驊(leixiaohua1020)的專欄
基於FFmpeg的代表播放器:Bilibili 的
ijkplayer
二、Android* Hardware Codec — MediaCodec(譯文)
Android有一個很棒的媒體庫,為應用開發提供了無數的可能性。然而,直到最近,Android OS 還沒有底層API用以直接編碼和解碼音頻/視頻,該底層API將幾乎能使開發者創造任何東西。
幸運的是,最新的 Jelly Bean 發布了 Android.media.MediaCodec API。該API使用與 OpenMAX*(媒體行業中的著名標准)相同的原理和架構設計,有效地從純粹的高級媒體播放器轉換到低級編碼器/解碼器。
從 MediaPlayer 到 MediaCodec
Android自API level 1以來已包含 MediaPlayer。MediaPlayer提供了一種簡單的方式來播放音頻和視頻。但是,它受限於它只提供三種媒體格式:MP4、3GPP 和 MKV(從Android 4.0開始)。為了播放不支持的格式,許多開發人員使用了FFmpeg軟件解碼器。
有一個x86二進制版本的FFmpeg可提供出色的性能。但是,包括 x86二進制文件 和 FFmpeg ARM* 二進制文件 都會產生一個很大的二進制鏡像。
截至Android 4.1發布,MediaCodec為此問題提供了合理的解決方案。由於MediaCodec是使用 Java API 編寫的,因此它允許接口訪問底層系統編解碼器,無論是硬件編解碼器,還是結合音頻編解碼器,都是高度優化的軟件編解碼器。使用MediaCodec能獲得合理性能優化並節省電量。
MediaCodec的函數調用流程
函數調用流程非常簡單,請參照下圖。配置完成后,開發人員使用 dequeueInputBuffer 獲取硬件緩沖區ID。將解碼原始緩沖區復制到輸入隊列后,使用 queueInputBuffer 使硬件編解碼器執行解碼功能。開發人員使用 dequeueOutputBuffer 獲取解碼緩沖區,然后使用 releaseOutputBuffer 釋放硬件緩沖區,該緩沖區提供一個選擇:輸出或者不輸出到屏幕。

有關詳細代碼,請參閱 Android 源碼中的 DecoderTest.java:
此示例代碼使用 MediaExtractor 作為媒體格式解析器。由於 Android 支持的媒體格式有限,大多數開發人員使用 AVFormat(FFmpeg的一個組件)作為媒體格式解析器。MediaCodec的配置與此功能不同。開發人員需要使用MediaFormat.createVideoFormat來創建視頻格式(如果使用MediaExtractor,則使用 getTrackFormat 來獲取格式)。一些解碼器(例如:H.264)需要額外的配置信息。可以使用 MediaFormat 或者 刷新幀 添加此信息。例如: H.264刷新幀是IDR幀,在該幀的報頭中包括附加配置信息。
創建 H.264視頻格式示例代碼:
videoformat = MediaFormat.createVideoFormat(“video/avc”, width,height);
videoformat.setByteBuffer("csd-0", extra configure data);
將 OpenGL* 與 MediaCodec 一起使用
OpenGL被用來渲染 MediaCodec輸出到屏幕。它在播放視頻時添加一些視頻特效也很有用。關鍵是 SurfaceTexture類。
SurfaceTexture包含在 API Level 15(Android 4.0.3)中。開發人員可以使用它將圖像流式傳輸到給定的OpenGL紋理。因此,如果使用 SurfaceTexture配置 MediaCodec,輸出緩沖區將被渲染到一個OpenGL紋理,而不是設備屏幕。因此,需要視頻后處理。
開發人員需要添加 幀監聽器(函數是setOnFrameAvailableListener)以獲取圖像更新消息,然后使用 updateTexImage 獲取最新圖像。OpenGL僅支持 RGB 顏色格式,但視頻解碼器的輸出是 YUV 顏色格式,因此必須使用 GL_TEXTURE_EXTERNAL_OES 來支持 YUV 顏色格式。例如:要更改紋理類型,請使用函數 GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureId)。
請參閱 https://github.com/MasDennis/Rajawali/wiki/Tutorial-25-Video-Material 以獲取有關如何將 SurfaceTexture 用於 MediaPlayer 的詳細信息。MediaCodec使用相同的過程,因此,如果使用 SurfaceTexture 配置 MediaCodec,將實現相同的結果。
Support Pipeline on Android 4.3
新的 InputSurface 和 OutputSurface 包含在Android 4.3 中,在 InputSurface 和 OutputSurface 的幫助下,可以使用零拷貝完成代碼轉換管道,也就是說,所有解碼視頻內存都不會從GPU復制到CPU。編碼器可以直接從管道獲取內存處理程序。InputSurface 和 OutputSurface 將與當前的 OpenGL 環境綁定,而 OutputSurface 可以作為 SurfaceTexture 的一種“打包”。
工作流程如下:

有關詳細代碼,請參閱 Android 4.3源碼中的 EncodeDecodeTest.java。資料來源: http://androidxref.com/4.3_r2.1/xref/cts/tests/tests/media/src/android/media/cts/EncodeDecodeTest.java
在英特爾®架構(IA)平台上使用MediaCodec時獲得低延遲
在某些情況下,例如屏幕投影或雲游戲,我們需要低延遲和高性能解碼。使用硬件解碼器,我們可以獲得良好的性能,而用軟件解碼器的副作用即高延遲。
如果編碼器為 H.264 ,則 MediaCodec 可能具有幾幀的延遲(對於IA平台,它是7幀,而其他主或高配置上是3-5幀)。如果幀速率為30 FPS,則 7 幀將具有 200 毫秒的延遲。什么原因造成硬件解碼器延遲?原因可能是主要或高配置文件具有B幀,並且如果解碼器在B幀引用后續緩沖器時沒有緩沖器,則播放將被阻止一小段時間。英特爾已經考慮了硬件解碼器的這種情況,並為主要或高配置文件提供了7個緩沖區,但由於基線沒有B幀,因此將其減少到零緩沖區用於基線。其他供應商可以為所有配置文件使用4個緩沖。
因此,在基於IA的Android平台上,解決方案是將編碼器更改為基線配置文件。如果無法更改編碼器配置文件,則可行的解決方法是更改解碼器端的配置數據。通常,配置文件位於第五個字節,因此將基線配置文件更改為66將在IA平台上產生最低延遲。
結論
為IA平台編寫Android媒體應用程序的開發人員應考慮使用本文所述的硬件解決方案,因為它在IA平台上表現最佳。 他們的客戶將從強大的硬件中獲得更多好處,反過來,這將為基於IA的Android設備構建一個h3多媒體軟件生態系統。
三、參考鏈接