diff options
Diffstat (limited to 'media')
-rw-r--r-- | media/libmedia/AudioTrack.cpp | 3 | ||||
-rw-r--r-- | media/libmediaplayerservice/StagefrightRecorder.cpp | 1 | ||||
-rw-r--r-- | media/libmediaplayerservice/nuplayer/NuPlayer.cpp | 101 | ||||
-rw-r--r-- | media/libmediaplayerservice/nuplayer/NuPlayer.h | 13 | ||||
-rw-r--r-- | media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp | 2 | ||||
-rw-r--r-- | media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp | 19 | ||||
-rw-r--r-- | media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h | 1 | ||||
-rw-r--r-- | media/libstagefright/ACodec.cpp | 57 | ||||
-rw-r--r-- | media/libstagefright/MediaCodec.cpp | 24 | ||||
-rw-r--r-- | media/libstagefright/codecs/aacdec/SoftAAC2.cpp | 19 | ||||
-rw-r--r-- | media/libstagefright/codecs/g711/dec/SoftG711.cpp | 9 |
11 files changed, 180 insertions, 69 deletions
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index e3beba5..8e0704f 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -2244,6 +2244,9 @@ bool AudioTrack::AudioTrackThread::threadLoop() return true; } } + if (exitPending()) { + return false; + } nsecs_t ns = mReceiver.processAudioBuffer(); switch (ns) { case 0: diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp index 17190fb..cadd691 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.cpp +++ b/media/libmediaplayerservice/StagefrightRecorder.cpp @@ -1172,6 +1172,7 @@ status_t StagefrightRecorder::checkVideoEncoderCapabilities( client.interface(), (mVideoEncoder == VIDEO_ENCODER_H263 ? MEDIA_MIMETYPE_VIDEO_H263 : mVideoEncoder == VIDEO_ENCODER_MPEG_4_SP ? MEDIA_MIMETYPE_VIDEO_MPEG4 : + mVideoEncoder == VIDEO_ENCODER_VP8 ? MEDIA_MIMETYPE_VIDEO_VP8 : mVideoEncoder == VIDEO_ENCODER_H264 ? MEDIA_MIMETYPE_VIDEO_AVC : ""), false /* decoder */, true /* hwCodec */, &codecs); *supportsCameraSourceMetaDataMode = codecs.size() > 0; diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index 53eec91..1c73995 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -174,6 +174,7 @@ NuPlayer::NuPlayer() mNumFramesDropped(0ll), mVideoScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW), mStarted(false) { + clearFlushComplete(); } NuPlayer::~NuPlayer() { @@ -333,25 +334,6 @@ void NuPlayer::seekToAsync(int64_t seekTimeUs, bool needNotify) { msg->post(); } -// static -bool NuPlayer::IsFlushingState(FlushStatus state, bool *needShutdown) { - switch (state) { - case FLUSHING_DECODER: - if (needShutdown != NULL) { - *needShutdown = false; - } - return true; - - case FLUSHING_DECODER_SHUTDOWN: - if (needShutdown != NULL) { - *needShutdown = true; - } - return true; - - default: - return false; - } -} void NuPlayer::writeTrackInfo( Parcel* reply, const sp<AMessage> format) const { @@ -773,38 +755,9 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { mRenderer->queueEOS(audio, err); } else if (what == Decoder::kWhatFlushCompleted) { - bool needShutdown; - - if (audio) { - CHECK(IsFlushingState(mFlushingAudio, &needShutdown)); - mFlushingAudio = FLUSHED; - } else { - CHECK(IsFlushingState(mFlushingVideo, &needShutdown)); - mFlushingVideo = FLUSHED; - - mVideoLateByUs = 0; - } - ALOGV("decoder %s flush completed", audio ? "audio" : "video"); - if (needShutdown) { - ALOGV("initiating %s decoder shutdown", - audio ? "audio" : "video"); - - // Widevine source reads must stop before releasing the video decoder. - if (!audio && mSource != NULL && mSourceFlags & Source::FLAG_SECURE) { - mSource->stop(); - } - - getDecoder(audio)->initiateShutdown(); - - if (audio) { - mFlushingAudio = SHUTTING_DOWN_DECODER; - } else { - mFlushingVideo = SHUTTING_DOWN_DECODER; - } - } - + handleFlushComplete(audio, true /* isDecoder */); finishFlushIfPossible(); } else if (what == Decoder::kWhatOutputFormatChanged) { sp<AMessage> format; @@ -957,6 +910,8 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { CHECK(msg->findInt32("audio", &audio)); ALOGV("renderer %s flush completed.", audio ? "audio" : "video"); + handleFlushComplete(audio, false /* isDecoder */); + finishFlushIfPossible(); } else if (what == Renderer::kWhatVideoRenderingStart) { notifyListener(MEDIA_INFO, MEDIA_INFO_RENDERING_START, 0); } else if (what == Renderer::kWhatMediaRenderingStart) { @@ -1084,6 +1039,50 @@ bool NuPlayer::audioDecoderStillNeeded() { return ((mFlushingAudio != SHUT_DOWN) && (mFlushingAudio != SHUTTING_DOWN_DECODER)); } +void NuPlayer::handleFlushComplete(bool audio, bool isDecoder) { + // We wait for both the decoder flush and the renderer flush to complete + // before entering either the FLUSHED or the SHUTTING_DOWN_DECODER state. + + mFlushComplete[audio][isDecoder] = true; + if (!mFlushComplete[audio][!isDecoder]) { + return; + } + + FlushStatus *state = audio ? &mFlushingAudio : &mFlushingVideo; + switch (*state) { + case FLUSHING_DECODER: + { + *state = FLUSHED; + + if (!audio) { + mVideoLateByUs = 0; + } + break; + } + + case FLUSHING_DECODER_SHUTDOWN: + { + *state = SHUTTING_DOWN_DECODER; + + ALOGV("initiating %s decoder shutdown", audio ? "audio" : "video"); + if (!audio) { + mVideoLateByUs = 0; + // Widevine source reads must stop before releasing the video decoder. + if (mSource != NULL && mSourceFlags & Source::FLAG_SECURE) { + mSource->stop(); + } + } + getDecoder(audio)->initiateShutdown(); + break; + } + + default: + // decoder flush completes only occur in a flushing state. + LOG_ALWAYS_FATAL_IF(isDecoder, "decoder flush in invalid state %d", *state); + break; + } +} + void NuPlayer::finishFlushIfPossible() { if (mFlushingAudio != NONE && mFlushingAudio != FLUSHED && mFlushingAudio != SHUT_DOWN) { @@ -1116,6 +1115,8 @@ void NuPlayer::finishFlushIfPossible() { mFlushingAudio = NONE; mFlushingVideo = NONE; + clearFlushComplete(); + processDeferredActions(); } @@ -1720,6 +1721,8 @@ void NuPlayer::flushDecoder( FlushStatus newStatus = needShutdown ? FLUSHING_DECODER_SHUTDOWN : FLUSHING_DECODER; + mFlushComplete[audio][false /* isDecoder */] = false; + mFlushComplete[audio][true /* isDecoder */] = false; if (audio) { ALOGE_IF(mFlushingAudio != NONE, "audio flushDecoder() is called in state %d", mFlushingAudio); diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h index 8157733..1b9a756 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.h +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h @@ -164,6 +164,9 @@ private: // notion of time has changed. bool mTimeDiscontinuityPending; + // Status of flush responses from the decoder and renderer. + bool mFlushComplete[2][2]; + // Used by feedDecoderInputData to aggregate small buffers into // one large buffer. sp<ABuffer> mPendingAudioAccessUnit; @@ -187,6 +190,13 @@ private: return audio ? mAudioDecoder : mVideoDecoder; } + inline void clearFlushComplete() { + mFlushComplete[0][0] = false; + mFlushComplete[0][1] = false; + mFlushComplete[1][0] = false; + mFlushComplete[1][1] = false; + } + void openAudioSink(const sp<AMessage> &format, bool offloadOnly); void closeAudioSink(); @@ -201,6 +211,7 @@ private: void notifyListener(int msg, int ext1, int ext2, const Parcel *in = NULL); + void handleFlushComplete(bool audio, bool isDecoder); void finishFlushIfPossible(); bool audioDecoderStillNeeded(); @@ -209,8 +220,6 @@ private: bool audio, bool needShutdown, const sp<AMessage> &newFormat = NULL); void updateDecoderFormatWithoutFlush(bool audio, const sp<AMessage> &format); - static bool IsFlushingState(FlushStatus state, bool *needShutdown = NULL); - void postScanSources(); void schedulePollDuration(); diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp index 776fd92..63c4fce 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp @@ -582,7 +582,7 @@ status_t NuPlayerDriver::getMetadata( } void NuPlayerDriver::notifyResetComplete() { - ALOGI("notifyResetComplete(%p)", this); + ALOGD("notifyResetComplete(%p)", this); Mutex::Autolock autoLock(mLock); CHECK_EQ(mState, STATE_RESET_IN_PROGRESS); diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp index d6bf1de..e5c64f6 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp @@ -72,6 +72,7 @@ NuPlayer::Renderer::Renderer( mHasVideo(false), mSyncQueues(false), mPaused(false), + mPauseStartedTimeRealUs(-1), mVideoSampleReceived(false), mVideoRenderingStarted(false), mVideoRenderingStartGeneration(0), @@ -574,7 +575,9 @@ void NuPlayer::Renderer::postDrainVideoQueue() { if (!mHasAudio) { mAnchorTimeMediaUs = mediaTimeUs; mAnchorTimeRealUs = nowUs; - notifyPosition(); + if (!mPaused || mVideoSampleReceived) { + notifyPosition(); + } } realTimeUs = nowUs; } else { @@ -645,6 +648,10 @@ void NuPlayer::Renderer::onDrainVideoQueue() { } } else { mVideoLateByUs = 0ll; + if (!mHasAudio && !mVideoSampleReceived) { + mAnchorTimeMediaUs = -1; + mAnchorTimeRealUs = -1; + } } entry->mNotifyConsumed->setInt64("timestampNs", realTimeUs * 1000ll); @@ -830,6 +837,9 @@ void NuPlayer::Renderer::onFlush(const sp<AMessage> &msg) { { Mutex::Autolock autoLock(mLock); syncQueuesDone_l(); + if (!mHasAudio) { + mPauseStartedTimeRealUs = -1; + } } ALOGV("flushing %s", audio ? "audio" : "video"); @@ -980,6 +990,9 @@ void NuPlayer::Renderer::onPause() { ++mVideoQueueGeneration; prepareForMediaRenderingStart(); mPaused = true; + if (!mHasAudio) { + mPauseStartedTimeRealUs = ALooper::GetNowUs(); + } } mDrainAudioQueuePending = false; @@ -1008,6 +1021,10 @@ void NuPlayer::Renderer::onResume() { Mutex::Autolock autoLock(mLock); mPaused = false; + if (!mHasAudio && mPauseStartedTimeRealUs != -1) { + mAnchorTimeRealUs += ALooper::GetNowUs() - mPauseStartedTimeRealUs; + mPauseStartedTimeRealUs = -1; + } if (!mAudioQueue.empty()) { postDrainAudioQueue_l(); diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h index 4237902..d27c238 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h +++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h @@ -130,6 +130,7 @@ private: bool mSyncQueues; bool mPaused; + int64_t mPauseStartedTimeRealUs; bool mVideoSampleReceived; bool mVideoRenderingStarted; int32_t mVideoRenderingStartGeneration; diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp index b6ac2a0..9b11ded 100644 --- a/media/libstagefright/ACodec.cpp +++ b/media/libstagefright/ACodec.cpp @@ -421,7 +421,8 @@ ACodec::ACodec() mMaxPtsGapUs(-1ll), mTimePerFrameUs(-1ll), mTimePerCaptureUs(-1ll), - mCreateInputBuffersSuspended(false) { + mCreateInputBuffersSuspended(false), + mTunneled(false) { mUninitializedState = new UninitializedState(this); mLoadedState = new LoadedState(this); mLoadedToIdleState = new LoadedToIdleState(this); @@ -697,6 +698,21 @@ status_t ACodec::configureOutputBuffersFromNativeWindow( return err; } + // Exits here for tunneled video playback codecs -- i.e. skips native window + // buffer allocation step as this is managed by the tunneled OMX omponent + // itself and explicitly sets def.nBufferCountActual to 0. + if (mTunneled) { + ALOGV("Tunneled Playback: skipping native window buffer allocation."); + def.nBufferCountActual = 0; + err = mOMX->setParameter( + mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); + + *minUndequeuedBuffers = 0; + *bufferCount = 0; + *bufferSize = 0; + return err; + } + *minUndequeuedBuffers = 0; err = mNativeWindow->query( mNativeWindow.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, @@ -904,6 +920,13 @@ ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() { ANativeWindowBuffer *buf; int fenceFd = -1; CHECK(mNativeWindow.get() != NULL); + + if (mTunneled) { + ALOGW("dequeueBufferFromNativeWindow() should not be called in tunnel" + " video playback mode mode!"); + return NULL; + } + if (native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &buf) != 0) { ALOGE("dequeueBuffer failed."); return NULL; @@ -1245,6 +1268,7 @@ status_t ACodec::configureCodec( if (msg->findInt32("feature-tunneled-playback", &tunneled) && tunneled != 0) { ALOGI("Configuring TUNNELED video playback."); + mTunneled = true; int32_t audioHwSync = 0; if (!msg->findInt32("audio-hw-sync", &audioHwSync)) { @@ -1259,6 +1283,9 @@ status_t ACodec::configureCodec( inputFormat->setInt32("adaptive-playback", true); } else { + ALOGV("Configuring CPU controlled video playback."); + mTunneled = false; + // Always try to enable dynamic output buffers on native surface err = mOMX->storeMetaDataInBuffers( mNode, kPortIndexOutput, OMX_TRUE); @@ -3431,6 +3458,32 @@ status_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> ¬ify) { break; } + case OMX_AUDIO_CodingG711: + { + OMX_AUDIO_PARAM_PCMMODETYPE params; + InitOMXParams(¶ms); + params.nPortIndex = portIndex; + + CHECK_EQ((status_t)OK, mOMX->getParameter( + mNode, + (OMX_INDEXTYPE)OMX_IndexParamAudioPcm, + ¶ms, + sizeof(params))); + + const char *mime = NULL; + if (params.ePCMMode == OMX_AUDIO_PCMModeMULaw) { + mime = MEDIA_MIMETYPE_AUDIO_G711_MLAW; + } else if (params.ePCMMode == OMX_AUDIO_PCMModeALaw) { + mime = MEDIA_MIMETYPE_AUDIO_G711_ALAW; + } else { // params.ePCMMode == OMX_AUDIO_PCMModeLinear + mime = MEDIA_MIMETYPE_AUDIO_RAW; + } + notify->setString("mime", mime); + notify->setInt32("channel-count", params.nChannels); + notify->setInt32("sample-rate", params.nSamplingRate); + break; + } + default: ALOGE("UNKNOWN AUDIO CODING: %d\n", audioDef->eEncoding); TRESPASS(); @@ -4551,6 +4604,8 @@ void ACodec::LoadedState::stateEntered() { onShutdown(keepComponentAllocated); } mCodec->mExplicitShutdown = false; + + mCodec->processDeferredMessages(); } void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) { diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp index b568063..5f55484 100644 --- a/media/libstagefright/MediaCodec.cpp +++ b/media/libstagefright/MediaCodec.cpp @@ -780,7 +780,9 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) { // STOPPING->UNINITIALIZED, instead of the // usual STOPPING->INITIALIZED state. setState(UNINITIALIZED); - + if (mState == RELEASING) { + mComponentName.clear(); + } (new AMessage)->postReply(mReplyID); } break; @@ -1046,7 +1048,9 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) { } if (mFlags & kFlagIsAsync) { - onInputBufferAvailable(); + if (!mHaveInputSurface) { + onInputBufferAvailable(); + } } else if (mFlags & kFlagDequeueInputPending) { CHECK(handleDequeueInputBuffer(mDequeueInputReplyID)); @@ -1130,6 +1134,7 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) { } else { CHECK_EQ(mState, RELEASING); setState(UNINITIALIZED); + mComponentName.clear(); } (new AMessage)->postReply(mReplyID); @@ -1339,12 +1344,12 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) { // after stop() returned, it would be safe to call release() // and it should be in this case, no harm to allow a release() // if we're already uninitialized. - // Similarly stopping a stopped MediaCodec should be benign. sp<AMessage> response = new AMessage; - response->setInt32( - "err", - mState == targetState ? OK : INVALID_OPERATION); - + status_t err = mState == targetState ? OK : INVALID_OPERATION; + response->setInt32("err", err); + if (err == OK && targetState == UNINITIALIZED) { + mComponentName.clear(); + } response->postReply(replyID); break; } @@ -1353,6 +1358,9 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) { // It's dead, Jim. Don't expect initiateShutdown to yield // any useful results now... setState(UNINITIALIZED); + if (targetState == UNINITIALIZED) { + mComponentName.clear(); + } (new AMessage)->postReply(replyID); break; } @@ -1745,8 +1753,6 @@ void MediaCodec::setState(State newState) { // return any straggling buffers, e.g. if we got here on an error returnBuffersToCodec(); - mComponentName.clear(); - // The component is gone, mediaserver's probably back up already // but should definitely be back up should we try to instantiate // another component.. and the cycle continues. diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp index 1b6eac4..40925fd 100644 --- a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp +++ b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp @@ -654,6 +654,7 @@ void SoftAAC2::onQueueFilled(OMX_U32 /* portIndex */) { inHeader->nOffset += inBufferUsedLength; AAC_DECODER_ERROR decoderErr; + int numLoops = 0; do { if (outputDelayRingBufferSpaceLeft() < (mStreamInfo->frameSize * mStreamInfo->numChannels)) { @@ -661,20 +662,19 @@ void SoftAAC2::onQueueFilled(OMX_U32 /* portIndex */) { break; } - int numconsumed = mStreamInfo->numTotalBytes + mStreamInfo->numBadBytes; + int numConsumed = mStreamInfo->numTotalBytes; decoderErr = aacDecoder_DecodeFrame(mAACDecoder, tmpOutBuffer, 2048 * MAX_CHANNEL_COUNT, 0 /* flags */); - numconsumed = (mStreamInfo->numTotalBytes + mStreamInfo->numBadBytes) - numconsumed; - if (numconsumed != 0) { - mDecodedSizes.add(numconsumed); - } + numConsumed = mStreamInfo->numTotalBytes - numConsumed; + numLoops++; if (decoderErr == AAC_DEC_NOT_ENOUGH_BITS) { break; } + mDecodedSizes.add(numConsumed); if (decoderErr != AAC_DEC_OK) { ALOGW("aacDecoder_DecodeFrame decoderErr = 0x%4.4x", decoderErr); @@ -716,6 +716,15 @@ void SoftAAC2::onQueueFilled(OMX_U32 /* portIndex */) { aacDecoder_SetParam(mAACDecoder, AAC_TPDEC_CLEAR_BUFFER, 1); + // After an error, replace the last entry in mBufferSizes with the sum of the + // last <numLoops> entries from mDecodedSizes to resynchronize the in/out lists. + mBufferSizes.pop(); + int n = 0; + for (int i = 0; i < numLoops; i++) { + n += mDecodedSizes.itemAt(mDecodedSizes.size() - numLoops + i); + } + mBufferSizes.add(n); + // fall through } diff --git a/media/libstagefright/codecs/g711/dec/SoftG711.cpp b/media/libstagefright/codecs/g711/dec/SoftG711.cpp index 240c0c1..3a69095 100644 --- a/media/libstagefright/codecs/g711/dec/SoftG711.cpp +++ b/media/libstagefright/codecs/g711/dec/SoftG711.cpp @@ -117,7 +117,14 @@ OMX_ERRORTYPE SoftG711::internalGetParameter( pcmParams->eEndian = OMX_EndianBig; pcmParams->bInterleaved = OMX_TRUE; pcmParams->nBitPerSample = 16; - pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear; + if (pcmParams->nPortIndex == 0) { + // input port + pcmParams->ePCMMode = mIsMLaw ? OMX_AUDIO_PCMModeMULaw + : OMX_AUDIO_PCMModeALaw; + } else { + // output port + pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear; + } pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF; pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF; |