Files
Obsidian-Main/03. 專注Study/Android/MediaCodec.md

6.4 KiB
Raw Blame History

一般流程

  1. 使用者從MediaCodec請求一個空的輸入bufferByteBuffer填充滿數據後將它傳遞給MediaCodec處理。
  2. MediaCodec處理完這些數據並將處理結果輸出至一個空的輸出bufferByteBuffer中。
  3. 使用者從MediaCodec獲取輸出buffer的數據消耗掉裡面的數據使用完輸出buffer的數據之後將其釋放回編解碼器。

流程如下圖所示: !android_mediacodec_flow.png

生命週期

MediaCodec的生命週期有三種狀態Stopped、Executing、Released。

  • Stopped包含三種子狀態Uninitialized、Configured、Error。
  • Executing包含三種子狀態Flushed、Running、End-of-Stream。 !android_mediacodec_life_cycle.png

Stopped 的三種子狀態:

  1. Uninitialized當創建了一個MediaCodec對象此時處於Uninitialized狀態。可以在任何狀態調用reset()方法使MediaCodec返回到Uninitialized狀態。
  2. Configured使用configure(…)方法對MediaCodec進行配置轉為Configured狀態。
  3. ErrorMediaCodec遇到錯誤時進入Error狀態。錯誤可能是在隊列操作時返回的錯誤或者異常導致的。

Executing 的三種子狀態:

  1. Flushed在調用start()方法後MediaCodec立即進入Flushed子狀態此時MediaCodec會擁有所有的緩存。可以在Executing狀態的任何時候通過調用flush()方法返回到Flushed子狀態。
  2. Running一旦第一個輸入緩存input buffer被移出隊列MediaCodec就轉入Running子狀態這種狀態佔據了MediaCodec的大部分生命週期。通過調用stop()方法轉移到Uninitialized狀態。
  3. End-of-Stream將一個帶有end-of-stream標記的輸入buffer入隊列時MediaCodec將轉入End-of-Stream子狀態。在這種狀態下MediaCodec不再接收之後的輸入buffer但它仍然產生輸出buffer直到end-of-stream標記輸出。

Released

  1. 當使用完MediaCodec後必須調用release()方法釋放其資源。調用release()方法進入最終的Released狀態。

API

createEncoderByType

createDecoderByType

configure

start

dequeueInputBuffer

queueInputBuffer

getInputBuffer

dequeueOutputBuffer

getOutputBuffer

releaseOutputBuffer

stop

release

使用

  1. 根據需求使用createEncoderByType或是createDecoderByType建立codec。以下以encode為例。
  2. 呼叫configure傳入相應的MediaFormat。
  3. 呼叫start開始encode。
  4. 建立一個迴圈不斷的傳入要encode的buffer也不斷的拿出已經encode的buffer。
  5. 在迴圈內要傳入的buffer處理方法
    1. 呼叫dequeueInputBuffer試探是否有能用的buffer如果有回傳值將大於等於0>= 0。這裡假設回傳值的變數叫做index。
    2. 如果index合法inputBuffer = queueInputBuffer(index)來取得可用的buffer。這裡假設buffer的變數叫做inputBuffer。
    3. 將要encode的資料copy到inputBuffer。
  6. 在迴圈內要取得已經encode buffer的方法
    1. 呼叫dequeueOutputBuffer試探是否有encoded buffer如果有回傳值將大於等於0>= 0。這裡假設回傳值的變數叫做index。
    2. 如果index合法outputBuffer = getOutputBuffer(index)來取得可用的buffer。這裡假設buffer的變數叫做outputBuffer。
    3. outputBuffer 就是已經 encode 好的,就看你怎麼處理。
    4. 重要!呼叫 releaseOutputBuffer 來回收剛剛那一塊 buffer。

Psuedo code 如下:

while (true)
    // send buffer to encode
    index = dequeueInputBuffer()
    if (index >= 0)
        inputBuffer = queueInputBuffer(index)
        copy(inputBuffer, srcBuffer)
    // Get encoded buffer
    index = dequeueOutputBuffer()
    if (index >= 0)
        outputBuffer = getOutputBuffer(index)
        releaseOutputBuffer(index)

參考資料