AudioPlayer的处理流程

http://blog.csdn.net/ameyume/article/details/7320470

首先需要注意的是,AudioPlayer处理的是已经解码后的数据。
1.创建AudioPlayer对象
(1)在 AwesomePlayer::play_l()函数中创建了AudioPlayer对象,并且在AwesomePlayer.cpp文件中,只在此函数中创建过AudioPlayer对象

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. if (mAudioSource != NULL) {  
  2.     if (mAudioPlayer == NULL) {  
  3.         if (mAudioSink != NULL) { // 只有mAudioSink参数不为空时,才会创建AudioPlayer对象,并作为第一个参数  
  4.             mAudioPlayer = new AudioPlayer(mAudioSink, this);  
  5.             mAudioPlayer->setSource(mAudioSource);  
  6.   
  7.             mTimeSource = mAudioPlayer;  
  8.   
  9.             // If there was a seek request before we ever started,  
  10.             // honor the request now.  
  11.             // Make sure to do this before starting the audio player  
  12.             // to avoid a race condition.  
  13.             seekAudioIfNecessary_l();  
  14.         }  
  15.     }  
(2)在 AwesomePlayer::play_l()函数中创建了mAudioPlayer后,调用startAudioPlayer_l执行输出数据
[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. status_t err = startAudioPlayer_l(  
  2.         false /* sendErrorNotification */);  
2. AwesomePlayer::startAudioPlayer_l
调用mAudioPlayer的start函数,开始输出数据
[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. // We've already started the MediaSource in order to enable  
  2. // the prefetcher to read its data.  
  3. status_t err = mAudioPlayer->start(  
  4.         true /* sourceAlreadyStarted */); // sourceAlreadyStarted参数为true  
3.AudioPlayer::start
(1)由于sourceAlreadyStarted参数为true,所以不会再调用mSource->start()函数

(2)读取第一段解码后的数据
    mFirstBufferResult = mSource->read(&mFirstBuffer, &options);

(3)由于mAudioSink不为空,所以会执行下面的 mAudioSink->open函数,并注册了AudioSinkCallback函数,而不会执行新建AudioTrack,即不会注册AudioCallback函数
[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. if (mAudioSink.get() != NULL) {  
  2.     status_t err = mAudioSink->open(  
  3.             mSampleRate, numChannels, AUDIO_FORMAT_PCM_16_BIT,  
  4.             DEFAULT_AUDIOSINK_BUFFERCOUNT,  
  5.             &AudioPlayer::AudioSinkCallback, this); // 注册的是AudioSinkCallback函数  
  6.     if (err != OK) {  
  7.         if (mFirstBuffer != NULL) {  
  8.             mFirstBuffer->release();  
  9.             mFirstBuffer = NULL;  
  10.         }  
  11.   
  12.         if (!sourceAlreadyStarted) {  
  13.             mSource->stop();  
  14.         }  
  15.   
  16.         return err;  
  17.     }  
  18.   
  19.     mLatencyUs = (int64_t)mAudioSink->latency() * 1000;  
  20.     mFrameSize = mAudioSink->frameSize();  
  21.   
  22.     mAudioSink->start(); // 实际调用AudioSink的实现类AudioOutput::start(), AudioOutput::start()又调用AudioTrack::start()开始输出数据  
  23. else {  
  24.     mAudioTrack = new AudioTrack(  
  25.             AUDIO_STREAM_MUSIC, mSampleRate, AUDIO_FORMAT_PCM_16_BIT,  
  26.             (numChannels == 2)  
  27.                 ? AUDIO_CHANNEL_OUT_STEREO  
  28.                 : AUDIO_CHANNEL_OUT_MONO,  
  29.             0, 0, &AudioCallback, this, 0); // 没有执行到新建AudioTrack函数,不会注册AudioCallback函数  
4.AudioPlayer::AudioSinkCallback
在有数据到来时,循环调用此callback函数
调用fillBuffer函数进行填充数据

5.AudioPlayer::fillBuffer
(1)此函数的返回值size_done,代表已经处理的数据总大小,与传递进来的数据size(第二个参数)不一定相同

(2)获取解码后的数据
[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. if (mInputBuffer == NULL) {  
  2.     status_t err;  
  3.   
  4.     if (mIsFirstBuffer) { // 第一段数据,把mFirstBuffer赋给mInputBuffer  
  5.         mInputBuffer = mFirstBuffer;  
  6.         mFirstBuffer = NULL;  
  7.         err = mFirstBufferResult;  
  8.   
  9.         mIsFirstBuffer = false;  
  10.     } else { // 以后直接从MediaSource的实现类中读数据  
  11.         err = mSource->read(&mInputBuffer, &options);  
  12.     }  
(3)取得一帧数据在媒体文件中存储的时间戳mPositionTimeMediaUs
[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. CHECK(mInputBuffer->meta_data()->findInt64(  
  2.             kKeyTime, &mPositionTimeMediaUs));  
(4)计算一帧数据实际播放位置的时间戳
[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. mPositionTimeRealUs =  
  2.     ((mNumFramesPlayed + size_done / mFrameSize) * 1000000)  
  3.         / mSampleRate;  
  4.   
  5. LOGV("buffer->size() = %d, "  
  6.      "mPositionTimeMediaUs=%.2f mPositionTimeRealUs=%.2f",  
  7.      mInputBuffer->range_length(),  
  8.      mPositionTimeMediaUs / 1E6, mPositionTimeRealUs / 1E6);  
  9.   
  10. // 这两个时间戳,在AwesomePlayer::onVideoEvent()中,用于计算音视频同步的依据  
  11.     int64_t realTimeUs, mediaTimeUs;  
  12.     if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL  
  13.         && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {  
  14.         mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;  
  15.     }  
(5)输出解码数据并释放已经使用的mInputBuffer
[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. if (mInputBuffer->range_length() == 0) {  
  2.     mInputBuffer->release();  
  3.     mInputBuffer = NULL; // 释放mInputBuffer  
  4.   
  5.     continue;  
  6. }  
  7.   
  8. size_t copy = size_remaining;  
  9. if (copy > mInputBuffer->range_length()) {  
  10.     copy = mInputBuffer->range_length();  
  11. }  
  12.   
  13. /// 把解码后的数据copy给输出buffer  
  14. memcpy((char *)data + size_done,  
  15.        (const char *)mInputBuffer->data() + mInputBuffer->range_offset(),  
  16.        copy);  
  17.   
  18. /// 每copy完一块数据后,重新设置剩余未copy数据的范围  
  19. mInputBuffer->set_range(mInputBuffer->range_offset() + copy,  
  20.                         mInputBuffer->range_length() - copy);  
  21.   
  22. size_done += copy;  
  23. size_remaining -= copy;  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值