音频seekTo的实现
1.音频的seekTo最终是在AudioPlayer类中实现的,AudioPlayer::seekTo函数
status_t AudioPlayer::seekTo(int64_t time_us) { Mutex::Autolock autoLock(mLock);
mSeeking = true;
// 设置seek标志为true mReachedEOS = false;
// 可以seek,说明还未到文件末尾,则结束标识设置为false mSeekTimeUs = time_us;
// seek到的时间点 if (mAudioSink != NULL) { // mAudioSink优先,mAudioSink内部会create AudioTrack并注册callback mAudioSink->flush();
} else { mAudioTrack->flush();
} return OK;
}
2. buffer的填充是在AudioPlayer::AudioSinkCallback函数中调用AudioPlayer::fillBuffer来填充的,而fillBuffer又是通过调用mSource->read(&mInputBuffer, &options);
来实现的,read会调用音频类型对应MediaSource的实现类来实现读取seekto位置的数据,例如MP3音频,如果是软解的话,就会调用MP3Source::read方法,读取seekto位置的数据填充buffer。
seek到的位置被设置到MediaSource::ReadOptions对象options中,通过以下方法设置。
【音频seekTo的实现】options.setSeekTo(mSeekTimeUs);
而options又作为mSource->read的参数,被传递到MP3Source::read函数中,赋值给MP3Source的成员变量mCurrentTimeUs。当读完一帧数据后,mCurrentTimeUs的值就增加了一帧的时长。计算方法如下:
mCurrentTimeUs += frame_size * 8000ll / bitrate;
3.AudioSinkCallback函数是在AudioPlayer::start函数中注册的。
if (mAudioSink.get() != NULL) { status_t err = mAudioSink->open( mSampleRate, numChannels, AudioSystem::PCM_16_BIT, DEFAULT_AUDIOSINK_BUFFERCOUNT, &AudioPlayer::AudioSinkCallback, this);
4.在fillBuffer函数中,当INFO_FORMAT_CHANGED时,又重新注册了AudioSinkCallback函数。
status_t err = mAudioSink->open( mSampleRate, numChannels, AudioSystem::PCM_16_BIT, DEFAULT_AUDIOSINK_BUFFERCOUNT, &AudioPlayer::AudioSinkCallback, this);
以上是对音频seekTo的分析。
推荐阅读
- 热闹中的孤独
- JAVA(抽象类与接口的区别&重载与重写&内存泄漏)
- 放屁有这三个特征的,请注意啦!这说明你的身体毒素太多
- 一个人的旅行,三亚
- 布丽吉特,人生绝对的赢家
- 慢慢的美丽
- 尽力
- 一个小故事,我的思考。
- 家乡的那条小河
- 《真与假的困惑》???|《真与假的困惑》??? ——致良知是一种伟大的力量