stagefright框架(七)-Audio和Video的同步 講完了 audio 和 video 的處理流程,接下來要看的是 audio 和 video 同步化 (synchronization) 的問題。 OpenCORE 的做法是設置一個主 clock ,而 audio 和 video 就分 別 以此作為輸出的依據。而在 Stagefright 中, audio 的輸出是透過 callback 函式來驅動, video 則根據 audio 的timestamp 來做同步。以下是詳細的 說 明: (1) 當 callback 函式驅動 AudioPlayer 讀取解碼後的資料時, AudioPlayer 會取得兩個時間戳 -- mPositionTimeMediaUs 和 mPositionTimeRealUs size_t AudioPlayer: : fillBuffer( data, size) { . . . mSource- > read ( & mInputBuffer, . . . ) ; mInputBuffer- > meta_data( ) - > findInt64( kKeyTime, &mPositionTimeMediaUs) ; mPositionTimeRealUs = ( ( mNumFramesPlayed + size_done / mFrameSize) *1000000) / mSampleRate; . . . } mPositionTimeMediaUs 是資料裡面所載明的時間戳 (timestamp) ; mPositionTimeRealUs 則是播放此資料的實際時間 ( 依據 frame number 及 sample rate 得出 ) 。 (2) Stagefright 中的 video 便依據從 AudioPlayer 得出來之兩個時間戳的差值,作為播放的依據 void AwesomePlayer: : onVideoEvent( ) { . . . mVideoSource- > read ( & mVideoBuffer, . . . ) ; mVideoBuffer- > meta_data( ) - > findInt64( kKeyTime, & timeUs) ; mAudioPlayer- > getMediaTimeMapping( & realTimeUs, & mediaTimeUs) ; mTimeSourceDeltaUs = realTimeUs - mediaTimeUs; nowUs = ts- > getRealTimeUs( ) - mTimeSourceDeltaUs; latenessUs = nowUs - timeUs; . . . } AwesomePlayer 從 AudioPlayer 取得 realTimeUs( 即 mPositionTimeRealUs) 和 mediaTimeUs(即 mPositionTimeMediaUs) ,並算出其差值 mTimeSourceDeltaUs 。 (3) 最後我們將該 video 資料做排程 void AwesomePlayer: : onVideoEvent( ) { . . . if ( latenessUs > 40000) { mVideoBuffer- > release( ) ; mVideoBuffer = NULL ; postVideoEvent_l( ) ; return ; } if ( latenessUs < - 10000) { postVideoEvent_l( 10000) ; return ; } mVideoRenderer- > render( mVideoBuffer) ; . . . }