這篇文章將介紹 Stagefright 中是如何和 OMX video decoder 傳遞 buffer 。
(1) OMXCodec 會在一開始的時候透過 read 函式來傳送未解碼的 data 給 decoder ,並且要求 decoder 將解碼後的 data 傳回來
status_t OMXCodec: : read ( . . . ) { if ( mInitialBufferSubmit) { mInitialBufferSubmit = false ; drainInputBuffers( ) ; <----- OMX_EmptyThisBuffer fillOutputBuffers( ) ; <----- OMX_FillThisBuffer } . . . } void OMXCodec: : drainInputBuffers( ) { Vector < BufferInfo> * buffers = & mPortBuffers[ kPortIndexInput] ; for ( i = 0; i < buffers- > size( ) ; + + i) { drainInputBuffer( & buffers- > editItemAt( i) ) ; } } void OMXCodec: : drainInputBuffer( BufferInfo * info) { mOMX- > emptyBuffer( . . . ) ; } void OMXCodec: : fillOutputBuffers( ) { Vector < BufferInfo> * buffers = & mPortBuffers[ kPortIndexOutput] ; for ( i = 0; i < buffers- > size( ) ; + + i) { fillOutputBuffer( & buffers- > editItemAt( i) ) ; } } void OMXCodec: : fillOutputBuffer( BufferInfo * info) { mOMX- > fillBuffer( . . . ) ; }
(2) Decoder 從 input port 讀取資料後,開始進行解碼,並且回傳 EmptyBufferDone 通知 OMXCodec
void OMXCodec: : on_message( const omx_message & msg) { switch ( msg. type) { case omx_message: : EMPTY_BUFFER_DONE: { IOMX: : buffer_id buffer = msg. u. extended_buffer_data. buffer; drainInputBuffer( & buffers- > editItemAt( i) ) ; } } }
OMXCodec 收到 EMPTY_BUFFER_DONE 之後,繼續傳送下一個未解碼的資料給 decoder 。 (3) Decoder 將解碼完的資料送到 output port ,並回傳 FillBufferDone 通知 OMXCodec
void OMXCodec: : on_message( const omx_message & msg) { switch ( msg. type) { case omx_message: : FILL_BUFFER_DONE: { IOMX: : buffer_id buffer = msg. u. extended_buffer_data. buffer; fillOutputBuffer( info) ; mFilledBuffers. push_back( i) ; mBufferFilled. signal ( ) ; } } }
OMXCodec 收到 FILL_BUFFER_DONE 之後,將解碼後的資料放入 mFilledBuffers ,發出 mBufferFilled 信號,並且要求 decoder 繼續送出資料。 (4) read 函式在後段等待 mBufferFilled 信號。當 mFilledBuffers 被填入資料後, read 函式將其指定給 buffer 指標,並回傳給 AwesomePlayer
status_t OMXCodec: : read ( MediaBuffer * * buffer, . . . ) { . . . while ( mFilledBuffers. empty( ) ) { mBufferFilled. wait( mLock) ; } BufferInfo * info = & mPortBuffers[ kPortIndexOutput] . editItemAt( index) ; info- > mMediaBuffer- > add_ref( ) ; * buffer = info- > mMediaBuffer; }