AudioPlayer的处理流程

首先需要注意的是,AudioPlayer处理的是已经解码后的数据。
1.创建AudioPlayer对象
(1)在 AwesomePlayer::play_l()函数中创建了AudioPlayer对象,并且在AwesomePlayer.cpp文件中,只在此函数中创建过AudioPlayer对象
    if (mAudioSource != NULL) {
        if (mAudioPlayer == NULL) {
            if (mAudioSink != NULL) { // 只有mAudioSink参数不为空时,才会创建AudioPlayer对象,并作为第一个参数
                mAudioPlayer = new AudioPlayer(mAudioSink, this);
                mAudioPlayer->setSource(mAudioSource);

                mTimeSource = mAudioPlayer;

                // If there was a seek request before we ever started,
                // honor the request now.
                // Make sure to do this before starting the audio player
                // to avoid a race condition.
                seekAudioIfNecessary_l();
            }
        }
(2)在 AwesomePlayer::play_l()函数中创建了mAudioPlayer后,调用startAudioPlayer_l执行输出数据
    status_t err = startAudioPlayer_l(
            false /* sendErrorNotification */);
2. AwesomePlayer::startAudioPlayer_l
调用mAudioPlayer的start函数,开始输出数据
    // We've already started the MediaSource in order to enable
    // the prefetcher to read its data.
    status_t err = mAudioPlayer->start(
            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函数
    if (mAudioSink.get() != NULL) {
        status_t err = mAudioSink->open(
                mSampleRate, numChannels, AUDIO_FORMAT_PCM_16_BIT,
                DEFAULT_AUDIOSINK_BUFFERCOUNT,
                &AudioPlayer::AudioSinkCallback, this); // 注册的是AudioSinkCallback函数
        if (err != OK) {
            if (mFirstBuffer != NULL) {
                mFirstBuffer->release();
                mFirstBuffer = NULL;
            }

            if (!sourceAlreadyStarted) {
                mSource->stop();
            }

            return err;
        }

        mLatencyUs = (int64_t)mAudioSink->latency() * 1000;
        mFrameSize = mAudioSink->frameSize();

        mAudioSink->start(); // 实际调用AudioSink的实现类AudioOutput::start(), AudioOutput::start()又调用AudioTrack::start()开始输出数据
    } else {
        mAudioTrack = new AudioTrack(
                AUDIO_STREAM_MUSIC, mSampleRate, AUDIO_FORMAT_PCM_16_BIT,
                (numChannels == 2)
                    ? AUDIO_CHANNEL_OUT_STEREO
                    : AUDIO_CHANNEL_OUT_MONO,
                0, 0, &AudioCallback, this, 0); // 没有执行到新建AudioTrack函数,不会注册AudioCallback函数
4.AudioPlayer::AudioSinkCallback
在有数据到来时,循环调用此callback函数
调用fillBuffer函数进行填充数据

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

(2)获取解码后的数据
    if (mInputBuffer == NULL) {
        status_t err;

        if (mIsFirstBuffer) { // 第一段数据,把mFirstBuffer赋给mInputBuffer
            mInputBuffer = mFirstBuffer;
            mFirstBuffer = NULL;
            err = mFirstBufferResult;

            mIsFirstBuffer = false;
        } else { // 以后直接从MediaSource的实现类中读数据
            err = mSource->read(&mInputBuffer, &options);
        }
(3)取得一帧数据在媒体文件中存储的时间戳mPositionTimeMediaUs
    CHECK(mInputBuffer->meta_data()->findInt64(
                kKeyTime, &mPositionTimeMediaUs));
(4)计算一帧数据实际播放位置的时间戳
    mPositionTimeRealUs =
        ((mNumFramesPlayed + size_done / mFrameSize) * 1000000)
            / mSampleRate;

    LOGV("buffer->size() = %d, "
         "mPositionTimeMediaUs=%.2f mPositionTimeRealUs=%.2f",
         mInputBuffer->range_length(),
         mPositionTimeMediaUs / 1E6, mPositionTimeRealUs / 1E6);

    // 这两个时间戳,在AwesomePlayer::onVideoEvent()中,用于计算音视频同步的依据
        int64_t realTimeUs, mediaTimeUs;
        if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL
            && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
            mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
        }
(5)输出解码数据并释放已经使用的mInputBuffer
    if (mInputBuffer->range_length() == 0) {
        mInputBuffer->release();
        mInputBuffer = NULL; // 释放mInputBuffer

        continue;
    }

    size_t copy = size_remaining;
    if (copy > mInputBuffer->range_length()) {
        copy = mInputBuffer->range_length();
    }

    /// 把解码后的数据copy给输出buffer
    memcpy((char *)data + size_done,
           (const char *)mInputBuffer->data() + mInputBuffer->range_offset(),
           copy);

    /// 每copy完一块数据后,重新设置剩余未copy数据的范围
    mInputBuffer->set_range(mInputBuffer->range_offset() + copy,
                            mInputBuffer->range_length() - copy);

    size_done += copy;
    size_remaining -= copy;
发布了270 篇原创文章 · 获赞 274 · 访问量 377万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览