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
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");
// 调用AwesomePlayer的play()
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
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;
}