diff options
Diffstat (limited to 'media')
-rw-r--r-- | media/libmedia/AudioSystem.cpp | 6 | ||||
-rw-r--r-- | media/libmediaplayerservice/nuplayer/NuPlayer.cpp | 95 | ||||
-rw-r--r-- | media/libmediaplayerservice/nuplayer/NuPlayer.h | 3 | ||||
-rw-r--r-- | media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp | 4 |
4 files changed, 101 insertions, 7 deletions
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index 3486d21..1742fbe 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -582,9 +582,13 @@ const sp<IAudioPolicyService>& AudioSystem::get_audio_policy_service() } binder->linkToDeath(gAudioPolicyServiceClient); gAudioPolicyService = interface_cast<IAudioPolicyService>(binder); - gAudioPolicyService->registerClient(gAudioPolicyServiceClient); gLock.unlock(); + // Registering the client takes the AudioPolicyService lock. + // Don't hold the AudioSystem lock at the same time. + gAudioPolicyService->registerClient(gAudioPolicyServiceClient); } else { + // There exists a benign race condition where gAudioPolicyService + // is set, but gAudioPolicyServiceClient is not yet registered. gLock.unlock(); } return gAudioPolicyService; diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index 35cc1ee..a44de98 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -994,6 +994,8 @@ void NuPlayer::finishFlushIfPossible() { ALOGV("both audio and video are flushed now."); + mPendingAudioAccessUnit.clear(); + if (mTimeDiscontinuityPending) { mRenderer->signalTimeDiscontinuity(); mTimeDiscontinuityPending = false; @@ -1251,14 +1253,48 @@ status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) { sp<ABuffer> accessUnit; + // Aggregate smaller buffers into a larger buffer. + // The goal is to reduce power consumption. + // Unfortunately this does not work with the software AAC decoder. + // TODO optimize buffer size for power consumption + // The offload read buffer size is 32 KB but 24 KB uses less power. + const int kAudioBigBufferSizeBytes = 24 * 1024; + bool doBufferAggregation = (audio && mOffloadAudio); + sp<ABuffer> biggerBuffer; + bool needMoreData = false; + int numSmallBuffers = 0; + bool gotTime = false; + bool dropAccessUnit; do { - status_t err = mSource->dequeueAccessUnit(audio, &accessUnit); + status_t err; + // Did we save an accessUnit earlier because of a discontinuity? + if (audio && (mPendingAudioAccessUnit != NULL)) { + accessUnit = mPendingAudioAccessUnit; + mPendingAudioAccessUnit.clear(); + err = mPendingAudioErr; + ALOGV("feedDecoderInputData() use mPendingAudioAccessUnit"); + } else { + err = mSource->dequeueAccessUnit(audio, &accessUnit); + } if (err == -EWOULDBLOCK) { - return err; + ALOGD("feedDecoderInputData() got EWOULDBLOCK"); + if (biggerBuffer == NULL) { + return err; + } else { + break; // Reply with data that we already have. + } } else if (err != OK) { if (err == INFO_DISCONTINUITY) { + if (biggerBuffer != NULL) { + // We already have some data so save this for later. + mPendingAudioErr = err; + mPendingAudioAccessUnit = accessUnit; + accessUnit.clear(); + ALOGD("feedDecoderInputData() save discontinuity for later"); + break; + } int32_t type; CHECK(accessUnit->meta()->findInt32("discontinuity", &type)); @@ -1363,7 +1399,52 @@ status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) { dropAccessUnit = true; ++mNumFramesDropped; } - } while (dropAccessUnit); + + size_t smallSize = accessUnit->size(); + needMoreData = false; + if (doBufferAggregation && (biggerBuffer == NULL) + // Don't bother if only room for a few small buffers. + && (smallSize < (kAudioBigBufferSizeBytes / 3))) { + // Create a larger buffer for combining smaller buffers from the extractor. + biggerBuffer = new ABuffer(kAudioBigBufferSizeBytes); + biggerBuffer->setRange(0, 0); // start empty + } + + if (biggerBuffer != NULL) { + int64_t timeUs; + bool smallTimestampValid = accessUnit->meta()->findInt64("timeUs", &timeUs); + // Will the smaller buffer fit? + size_t bigSize = biggerBuffer->size(); + size_t roomLeft = biggerBuffer->capacity() - bigSize; + // Should we save this small buffer for the next big buffer? + // If the first small buffer did not have a timestamp then save + // any buffer that does have a timestamp until the next big buffer. + if ((smallSize > roomLeft) + || (!gotTime && (numSmallBuffers > 0) && smallTimestampValid)) { + mPendingAudioErr = err; + mPendingAudioAccessUnit = accessUnit; + accessUnit.clear(); + } else { + // Append small buffer to the bigger buffer. + memcpy(biggerBuffer->base() + bigSize, accessUnit->data(), smallSize); + bigSize += smallSize; + biggerBuffer->setRange(0, bigSize); + + // Keep looping until we run out of room in the biggerBuffer. + needMoreData = true; + + // Grab time from first small buffer if available. + if ((numSmallBuffers == 0) && smallTimestampValid) { + biggerBuffer->meta()->setInt64("timeUs", timeUs); + gotTime = true; + } + + ALOGV("feedDecoderInputData() #%d, smallSize = %zu, bigSize = %zu, capacity = %zu", + numSmallBuffers, smallSize, bigSize, biggerBuffer->capacity()); + numSmallBuffers++; + } + } + } while (dropAccessUnit || needMoreData); // ALOGV("returned a valid buffer of %s data", audio ? "audio" : "video"); @@ -1379,7 +1460,13 @@ status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) { mCCDecoder->decode(accessUnit); } - reply->setBuffer("buffer", accessUnit); + if (biggerBuffer != NULL) { + ALOGV("feedDecoderInputData() reply with aggregated buffer, %d", numSmallBuffers); + reply->setBuffer("buffer", biggerBuffer); + } else { + reply->setBuffer("buffer", accessUnit); + } + reply->post(); return OK; diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h index 0c7f531..89ae11c 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.h +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h @@ -158,6 +158,9 @@ private: // notion of time has changed. bool mTimeDiscontinuityPending; + sp<ABuffer> mPendingAudioAccessUnit; + status_t mPendingAudioErr; + FlushStatus mFlushingAudio; FlushStatus mFlushingVideo; diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp index 09324ae..35cd514 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp @@ -627,11 +627,11 @@ void NuPlayerDriver::notifyListener_l( case MEDIA_PLAYBACK_COMPLETE: { if (mLooping && mState != STATE_RESET_IN_PROGRESS) { - mLock.unlock(); mPlayer->seekToAsync(0); - mLock.lock(); break; } + mPlayer->pause(); + mState = STATE_PAUSED; // fall through } |