在《 Stagefright (1) – Video Playback 的流程 》中,我們並沒有詳述 Stagefright 是如何根據影片檔的類型來選擇適合的 video decoder ,現在,就讓我們來看一看。
(1) Video decoder 是在 onPrepareAsyncEvent 中的 initVideoDecoder 被決定的 OMXCodec::Create() 會回傳 video decoder 給 mVideoSource 。
status_t AwesomePlayer: : initVideoDecoder( ) { mVideoSource = OMXCodec: : Create( mClient. interface( ) , mVideoTrack- > getFormat( ) , false , mVideoTrack) ; } sp< MediaSource> OMXCodec: : Create( & omx, & meta, createEncoder, & source, matchComponentName) { meta- > findCString( kKeyMIMEType, & mime) ; findMatchingCodecs( mime, . . . , & matchingCodecs) ; . . . . . . . . ( 2) for ( size_t i = 0; i < matchingCodecs. size( ) ; + + i) { componentName = matchingCodecs[ i] . string ( ) ; softwareCodec = InstantiateSoftwareCodec( componentName, . . . ) ; . . . . . ( 3) if ( softwareCodec ! = NULL ) return softwareCodec; err = omx- > allocateNode( componentName, . . . , & node) ; . . . ( 4) if ( err = = OK) { codec = new OMXCodec( . . . , componentName, . . . ) ; . . . . . . ( 5) return codec; } } }
(2) 根據 mVideoTrack 的 MIME 從 kDecoderInfo 挑出合適的 components
void OMXCodec: : findMatchingCodecs( mime, . . . , matchingCodecs) { for ( int index = 0; ; + + index) { componentName = GetCodec( kDecoderInfo, sizeof ( kDecoderInfo) / sizeof ( kDecoderInfo[ 0] ) , mime, index) ; matchingCodecs- > push( String8( componentName) ) ; } } static const CodecInfo kDecoderInfo[ ] = { . . . { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.video.decoder.mpeg4" } , { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.TI.Video.Decoder" } , { MEDIA_MIMETYPE_VIDEO_MPEG4, "M4vH263Decoder" } , . . . }
GetCodec 會依據 mime 從 kDecoderInfo 挑出所有的 component name ,然後存到 matchingCodecs 中。 (3) 根據 matchingCodecs 中 component 的順序,我們會先去檢查其是否為 software decoder
static sp< MediaSource> InstantiateSoftwareCodec( name, . . . ) { FactoryInfo kFactoryInfo[ ] = { . . . FACTORY_REF( M4vH263Decoder) . . . } ; for ( i = 0; i < sizeof ( kFactoryInfo) / sizeof ( kFactoryInfo[ 0] ) ; + + i) { if ( ! strcmp ( name, kFactoryInfo[ i] . name) ) return ( * kFactoryInfo[ i] . CreateFunc) ( source) ; } }
所有的software decoder 都會被列在 kFactoryInfo 中,我們藉由傳進來的 name 來對應到適合的 decoder 。 (4) 如果該 component 不是 software decoder ,則試著去配置對應的 OMX component
status_t OMX: : allocateNode( name, . . . , node) { mMaster- > makeComponentInstance( name, & OMXNodeInstance: : kCallbacks, instance, handle) ; } OMX_ERRORTYPE OMXMaster: : makeComponentInstance( name, . . . ) { plugin- > makeComponentInstance( name, . . . ) ; } OMX_ERRORTYPE OMXPVCodecsPlugin: : makeComponentInstance( name, . . . ) { return OMX_MasterGetHandle( . . . , name, . . . ) ; } OMX_ERRORTYPE OMX_MasterGetHandle( . . . ) { return OMX_GetHandle( . . . ) ; }
(5) 若該 component 為 OMX deocder ,則回傳;否則繼續檢查下一個 component