stagefright中的时间
在stagefright框架下播放音视频会涉及到三种情况:
1、只有音频(audio):stagefright中音频播放最后由AudioTrack进行播放速度的控制。无论有无Video、XXXSource返回的 kKeyTime不影响音频的播放;
2、只有视频(video):在stagefright中以video的kKeyTime控制视频速度;
3、既有音频(audio)还有视频(video):在stagefright中以Audio的kKeyTime时间为准同时要进行A/V同步;
在一般情况下,在stagefright播放视频时候,音频和视频都会有。在这种情况下,以音频的kKeyTime为准同时进行A/V同步,保证视频播放时候画面和声音同步。
1、取audio的时间,计算latenessUs
mediaTimeUs为audio的kKeyTime;
realTimeUs为AudioTrack返回的实际播放时间;
mAudioPlayer->getMediaTimeMapping(&realTimeUs,&mediaTimeUs);
mTimeSourceDeltaUs=realTimeUs-mediaTimeUs;
nowUs=ts->getRealTimeUs()-mTimeSourceDeltaUs;
timeUs为video的kKeyTime;
latenessUs=nowUs-timeUs;
2、如果解码出来的帧过早,视频解码休息
if(latenessUs<-10000){//早了10ms
postVideoEvent_l(10000);
}
实际上只有video时,控制解码速度也是通过这里控制的,即控制mVideoEvent触发频率
3、如果解码出来的帧慢了,往前seek、或丢帧
if(latenessUs>50000011){
mSeekTimeUs=mediaTimeUs;//直接seek
}
if(latenessUs>40000){
mVideoBuffer=NULL;//丢帧,立即触发一下mVideoEvent
postVideoEvent_l();
}
4、AudioTrack对音频播放速度的控制
(1)、AudioTrack与Output的数据交换通过共享内存实现,即AudioTrack中的mCblk;
(2)、AudioTrack建立的时候,初始化了一个AudioTrackThread,线程循环进入AudioTrack::processAudioB uffer,,不停的去获取解码后的数据,Buffer写入mCblk;
(3)、 AudioTrack::processAudioBuffer{
obtainBuffer(&audioBuffer, -1);// 这里回调 AudioPlayer::fillBuffer() 返回解码后的数据
// 解码流程与video一致,可参考前文《Stagefright,omx与Component的交互》的分析
mCbf(EVENT_MORE_DATA, mUserData, &audioBuffer);
releaseBuffer(&audioBuffer);
}
(4)、 AudioTrack::obtainBuffer(){
while (framesAvail == 0) {
// 这里根据cblk控制了Buffer的获得,也就控制了最后回调获取解码后数据的频率
// 也间接控制了audio解包速度
// 但最后audio播放速度的控制应该是由output层控制,有待output层分析考证!
result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
}
}