Android Media Server - MediaPlayer - start (audio)

 

 

 

 

 

 

1.      MediaPlayerService::Client::start()

Frameworks/av/media/libmediaplayerservice/MediaPlayerService.h

Frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp

 

status_t MediaPlayerService::Client::start()

{

    ALOGV("[%d] start", mConnId);

 

// p 是一个 StageFrightPlayer对象

 

    sp p = getPlayer();

    if (p == 0) return UNKNOWN_ERROR;

    p->setLooping(mLoop);

 

// 调用StageFrightPlayer对象的start()

 

    return p->start();

}

 

2.      StagefrightPlayer::start ()

Frameworks/av/media/libmediaplayerservice/StageFrightPlayer.cpp

status_tStagefrightPlayer::start() {

    ALOGV("start");

 

//  调用AwesomePlayerplay()

 

    returnmPlayer->play();

}

 

3.      AwesomePlayer::play ()

Frameworks/av/media/libstagefright/AwesomePlayer.cpp

status_tAwesomePlayer::play() {

    ATRACE_CALL();

 

    Mutex::Autolock autoLock(mLock);

 

    modifyFlags(CACHE_UNDERRUN, CLEAR);

 

    return play_l();

}

 

status_tAwesomePlayer::play_l() {

    modifyFlags(SEEK_PREVIEW, CLEAR);

 

    if (mFlags & PLAYING) {

        return OK;

    }

 

    if (!(mFlags & PREPARED)) {

        status_t err = prepare_l();

 

        if (err != OK) {

            return err;

        }

    }

 

    modifyFlags(PLAYING, SET);

    modifyFlags(FIRST_FRAME, SET);

 

    if (mDecryptHandle != NULL) {

        int64_t position;

        getPosition(&position);

       mDrmManagerClient->setPlaybackStatus(mDecryptHandle,

                Playback::START, position /1000);

    }

 

    if (mAudioSource != NULL) {

        if (mAudioPlayer == NULL) {

            if (mAudioSink != NULL) {

                bool allowDeepBuffering;

                int64_t cachedDurationUs;

                bool eos;

                if (mVideoSource == NULL

                        && (mDurationUs >AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US ||

                       (getCachedDuration_l(&cachedDurationUs, &eos) &&

                        cachedDurationUs >AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US))) {

                    allowDeepBuffering = true;

                } else {

                    allowDeepBuffering = false;

                }

 

                mAudioPlayer = newAudioPlayer(mAudioSink, allowDeepBuffering, this);

               mAudioPlayer->setSource(mAudioSource);

 

                mTimeSource = mAudioPlayer;

 

                // If there was a seek requestbefore we ever started,

                // honor the request now.

                // Make sure to do this beforestarting the audio player

                // to avoid a race condition.

                seekAudioIfNecessary_l();

            }

        }

 

        CHECK(!(mFlags & AUDIO_RUNNING));

 

        if (mVideoSource == NULL) {

            // We don't want to post an errornotification at this point,

            // the error returned fromMediaPlayer::start() will suffice.

 

            status_terr = startAudioPlayer_l(

                   false /* sendErrorNotification */);

 

            if (err != OK) {

                delete mAudioPlayer;

               mAudioPlayer = NULL;

 

                modifyFlags((PLAYING |FIRST_FRAME), CLEAR);

 

                if (mDecryptHandle != NULL) {

                   mDrmManagerClient->setPlaybackStatus(

                            mDecryptHandle,Playback::STOP, 0);

                }

 

                return err;

            }

        }

    }

 

    if (mTimeSource == NULL &&mAudioPlayer == NULL) {

        mTimeSource = &mSystemTimeSource;

    }

 

    if (mVideoSource != NULL) {

        // Kick off video playback

       postVideoEvent_l();

 

        if (mAudioSource != NULL &&mVideoSource != NULL) {

            postVideoLagEvent_l();

        }

    }

 

    if (mFlags & AT_EOS) {

        // Legacy behaviour, if a streamfinishes playing and then

        // is started again, we play from thestart...

        seekTo_l(0);

    }

 

    uint32_t params =IMediaPlayerService::kBatteryDataCodecStarted

        |IMediaPlayerService::kBatteryDataTrackDecoder;

    if ((mAudioSource != NULL) && (mAudioSource!= mAudioTrack)) {

        params |=IMediaPlayerService::kBatteryDataTrackAudio;

    }

    if (mVideoSource != NULL) {

        params |=IMediaPlayerService::kBatteryDataTrackVideo;

    }

    addBatteryData(params);

 

    return OK;

}

 

4.      AwesomePlayer:: startAudioPlayer_l()

Frameworks/av/media/libstagefright/AwesomePlayer.cpp

status_tAwesomePlayer::startAudioPlayer_l(bool sendErrorNotification) {

    CHECK(!(mFlags & AUDIO_RUNNING));

 

    if (mAudioSource == NULL || mAudioPlayer ==NULL) {

        return OK;

    }

 

    if (!(mFlags & AUDIOPLAYER_STARTED)) {

        bool wasSeeking =mAudioPlayer->isSeeking();

 

        // We've already started theMediaSource in order to enable

        // the prefetcher to read its data.

        status_t err =mAudioPlayer->start(

                true /*sourceAlreadyStarted */);

 

        if (err != OK) {

            if (sendErrorNotification) {

                notifyListener_l(MEDIA_ERROR,MEDIA_ERROR_UNKNOWN, err);

            }

 

            return err;

        }

 

        modifyFlags(AUDIOPLAYER_STARTED, SET);

 

        if (wasSeeking) {

           CHECK(!mAudioPlayer->isSeeking());

 

            // We will have finished the seekwhile starting the audio player.

            postAudioSeekComplete();

        }

    } else {

        mAudioPlayer->resume();

    }

 

    modifyFlags(AUDIO_RUNNING, SET);

 

    mWatchForAudioEOS = true;

 

    return OK;

}

 

5.      AwesomePlayer:: startAudioPlayer_l()

Frameworks/av/media/libstagefright/AudioPlayer.cpp

status_t AudioPlayer::start(boolsourceAlreadyStarted) {

    CHECK(!mStarted);

    CHECK(mSource != NULL);

 

    status_t err;

    if (!sourceAlreadyStarted) {

        err = mSource->start();

 

        if (err != OK) {

            return err;

        }

    }

 

    // We allow an optional INFO_FORMAT_CHANGEDat the very beginning

    // of playback, if there is one, getFormatbelow will retrieve the

    // updated format, if there isn't, we'llstash away the valid buffer

    // of data to be used on the first audiocallback.

 

    CHECK(mFirstBuffer == NULL);

 

    MediaSource::ReadOptions options;

    if (mSeeking) {

        options.setSeekTo(mSeekTimeUs);

        mSeeking = false;

    }

 

    mFirstBufferResult= mSource->read(&mFirstBuffer, &options);

    if (mFirstBufferResult ==INFO_FORMAT_CHANGED) {

       ALOGV("INFO_FORMAT_CHANGED!!!");

 

        CHECK(mFirstBuffer == NULL);

        mFirstBufferResult = OK;

        mIsFirstBuffer = false;

    } else {

        mIsFirstBuffer = true;

    }

 

    sp format =mSource->getFormat();

    const char *mime;

    bool success =format->findCString(kKeyMIMEType, &mime);

    CHECK(success);

    CHECK(!strcasecmp(mime,MEDIA_MIMETYPE_AUDIO_RAW));

 

    success = format->findInt32(kKeySampleRate,&mSampleRate);

    CHECK(success);

 

    int32_t numChannels, channelMask;

    success =format->findInt32(kKeyChannelCount, &numChannels);

    CHECK(success);

 

    if(!format->findInt32(kKeyChannelMask,&channelMask)) {

        // log only when there's a risk ofambiguity of channel mask selection

        ALOGI_IF(numChannels > 2,

                "source format didn'tspecify channel mask, using (%d) channel order", numChannels);

        channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER;

    }

 

    if (mAudioSink.get() != NULL) {

 

        status_t err =mAudioSink->open(

               mSampleRate, numChannels, channelMask, AUDIO_FORMAT_PCM_16_BIT,

               DEFAULT_AUDIOSINK_BUFFERCOUNT,

               &AudioPlayer::AudioSinkCallback,

                this,

               (mAllowDeepBuffering ?

                           AUDIO_OUTPUT_FLAG_DEEP_BUFFER :

                           AUDIO_OUTPUT_FLAG_NONE));

        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();

    } else {

        // playing to an AudioTrack, set upmask if necessary

        audio_channel_mask_t audioMask =channelMask == CHANNEL_MASK_USE_CHANNEL_ORDER ?

               audio_channel_out_mask_from_count(numChannels) : channelMask;

        if (0 == audioMask) {

            return BAD_VALUE;

        }

 

        mAudioTrack =new AudioTrack(

               AUDIO_STREAM_MUSIC, mSampleRate, AUDIO_FORMAT_PCM_16_BIT, audioMask,

                0,AUDIO_OUTPUT_FLAG_NONE, &AudioCallback, this, 0);

 

        if ((err = mAudioTrack->initCheck())!= OK) {

            delete mAudioTrack;

            mAudioTrack = NULL;

 

            if (mFirstBuffer != NULL) {

                mFirstBuffer->release();

                mFirstBuffer = NULL;

            }

 

            if (!sourceAlreadyStarted) {

                mSource->stop();

            }

 

            return err;

        }

 

        mLatencyUs = (int64_t)mAudioTrack->latency()* 1000;

        mFrameSize =mAudioTrack->frameSize();

 

       mAudioTrack->start();

    }

 

    mStarted = true;

    mPinnedTimeUs = -1ll;

 

    return OK;

}

 

6.      AudioPlayer:: AudioSinkCallback()

 

// static

size_tAudioPlayer::AudioSinkCallback(

        MediaPlayerBase::AudioSink *audioSink,

        void *buffer, size_t size, void*cookie) {

    AudioPlayer *me = (AudioPlayer *)cookie;

 

    return me->fillBuffer(buffer, size);

}

 

voidAudioPlayer::AudioCallback(int event, void *info) {

    if (event != AudioTrack::EVENT_MORE_DATA) {

        return;

    }

 

    AudioTrack::Buffer *buffer =(AudioTrack::Buffer *)info;

    size_t numBytesWritten =fillBuffer(buffer->raw, buffer->size);

 

    buffer->size = numBytesWritten;

}

 

size_t AudioPlayer::fillBuffer(void*data, size_t size) {

    if (mNumFramesPlayed == 0) {

        ALOGV("AudioCallback");

    }

 

    if (mReachedEOS) {

        return 0;

    }

 

    bool postSeekComplete = false;

    bool postEOS = false;

    int64_t postEOSDelayUs = 0;

 

    size_t size_done = 0;

    size_t size_remaining = size;

    while (size_remaining > 0) {

        MediaSource::ReadOptions options;

 

        {

            Mutex::Autolock autoLock(mLock);

 

            if (mSeeking) {

                if (mIsFirstBuffer) {

                    if (mFirstBuffer != NULL) {

                       mFirstBuffer->release();

                        mFirstBuffer = NULL;

                    }

                    mIsFirstBuffer = false;

                }

 

                options.setSeekTo(mSeekTimeUs);

 

                if (mInputBuffer != NULL) {

                    mInputBuffer->release();

                    mInputBuffer = NULL;

                }

 

                mSeeking = false;

                if (mObserver) {

                    postSeekComplete = true;

                }

            }

        }

 

        if (mInputBuffer == NULL) {

            status_t err;

 

            if (mIsFirstBuffer) {

                mInputBuffer = mFirstBuffer;

                mFirstBuffer = NULL;

                err = mFirstBufferResult;

 

                mIsFirstBuffer = false;

            } else {

                err =mSource->read(&mInputBuffer, &options);

            }

 

            CHECK((err == OK &&mInputBuffer != NULL)

                   || (err != OK &&mInputBuffer == NULL));

 

            Mutex::Autolock autoLock(mLock);

 

            if (err != OK) {

                if (mObserver &&!mReachedEOS) {

                    // We don't want to postEOS right away but only

                    // after all frames haveactually been played out.

 

                    // These are the number offrames submitted to the

                    // AudioTrack that youhaven't heard yet.

                    uint32_tnumFramesPendingPlayout =

                       getNumFramesPendingPlayout();

 

                    // These are the number offrames we're going to

                    // submit to the AudioTrackby returning from this

                    // callback.

                    uint32_tnumAdditionalFrames = size_done / mFrameSize;

 

                    numFramesPendingPlayout +=numAdditionalFrames;

 

                    int64_t timeToCompletionUs=

                        (1000000ll *numFramesPendingPlayout) / mSampleRate;

 

                    ALOGV("total number of framesplayed: %lld (%lld us)",

                            (mNumFramesPlayed +numAdditionalFrames),

                            1000000ll *(mNumFramesPlayed + numAdditionalFrames)

                                / mSampleRate);

 

                    ALOGV("%d frames leftto play, %lld us (%.2f secs)",

                        numFramesPendingPlayout,

                         timeToCompletionUs,timeToCompletionUs / 1E6);

 

                    postEOS = true;

                    if(mAudioSink->needsTrailingPadding()) {

                        postEOSDelayUs =timeToCompletionUs + mLatencyUs;

                    } else {

                        postEOSDelayUs = 0;

                    }

                }

 

                mReachedEOS = true;

                mFinalStatus = err;

                break;

            }

 

            if (mAudioSink != NULL) {

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

            } else {

                mLatencyUs = (int64_t)mAudioTrack->latency()* 1000;

            }

 

           CHECK(mInputBuffer->meta_data()->findInt64(

                        kKeyTime,&mPositionTimeMediaUs));

 

            mPositionTimeRealUs =

                ((mNumFramesPlayed + size_done/ mFrameSize) * 1000000)

                    / mSampleRate;

 

            ALOGV("buffer->size() = %d,"

                "mPositionTimeMediaUs=%.2f mPositionTimeRealUs=%.2f",

                mInputBuffer->range_length(),

                 mPositionTimeMediaUs / 1E6,mPositionTimeRealUs / 1E6);

        }

 

        if (mInputBuffer->range_length() ==0) {

            mInputBuffer->release();

            mInputBuffer = NULL;

 

            continue;

        }

 

        size_t copy = size_remaining;

        if (copy >mInputBuffer->range_length()) {

            copy =mInputBuffer->range_length();

        }

 

        memcpy((char*)data + size_done,

               (constchar *)mInputBuffer->data() + mInputBuffer->range_offset(),

               copy);

 

        mInputBuffer->set_range(mInputBuffer->range_offset()+ copy,

                               mInputBuffer->range_length() - copy);

 

        size_done += copy;

        size_remaining -= copy;

    }

 

    {

        Mutex::Autolock autoLock(mLock);

        mNumFramesPlayed += size_done /mFrameSize;

        mNumFramesPlayedSysTimeUs =ALooper::GetNowUs();

 

        if (mReachedEOS) {

            mPinnedTimeUs =mNumFramesPlayedSysTimeUs;

        } else {

            mPinnedTimeUs = -1ll;

        }

    }

 

    if (postEOS) {

       mObserver->postAudioEOS(postEOSDelayUs);

    }

 

    if (postSeekComplete) {

        mObserver->postAudioSeekComplete();

    }

 

    return size_done;

}

 

 

你可能感兴趣的:(OS/Android)