diff options
-rw-r--r-- | include/media/stagefright/ACodec.h | 3 | ||||
-rw-r--r-- | media/libmediaplayerservice/nuplayer/NuPlayer.cpp | 18 | ||||
-rw-r--r-- | media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp | 33 | ||||
-rw-r--r-- | media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h | 2 | ||||
-rw-r--r-- | media/libstagefright/ACodec.cpp | 74 | ||||
-rw-r--r-- | media/libstagefright/Android.mk | 6 | ||||
-rw-r--r-- | media/libstagefright/AwesomePlayer.cpp | 2 | ||||
-rw-r--r-- | media/libstagefright/MPEG4Extractor.cpp | 5 | ||||
-rwxr-xr-x | media/libstagefright/OMXCodec.cpp | 9 | ||||
-rw-r--r-- | media/libstagefright/SampleTable.cpp | 7 | ||||
-rw-r--r-- | media/libstagefright/include/SampleTable.h | 2 |
11 files changed, 90 insertions, 71 deletions
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h index f13e9bb..e965f14 100644 --- a/include/media/stagefright/ACodec.h +++ b/include/media/stagefright/ACodec.h @@ -36,6 +36,7 @@ struct ACodec : public AHierarchicalStateMachine { kWhatShutdownCompleted = 'scom', kWhatFlushCompleted = 'fcom', kWhatOutputFormatChanged = 'outC', + kWhatError = 'erro', }; ACodec(); @@ -58,7 +59,6 @@ private: struct OutputPortSettingsChangedState; struct ExecutingToIdleState; struct IdleToLoadedState; - struct ErrorState; struct FlushingState; enum { @@ -102,7 +102,6 @@ private: sp<OutputPortSettingsChangedState> mOutputPortSettingsChangedState; sp<ExecutingToIdleState> mExecutingToIdleState; sp<IdleToLoadedState> mIdleToLoadedState; - sp<ErrorState> mErrorState; sp<FlushingState> mFlushingState; AString mComponentName; diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index b06f20d..7fb141a 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -340,6 +340,11 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { } finishFlushIfPossible(); + } else if (what == ACodec::kWhatError) { + LOGE("Received error from %s decoder, aborting playback.", + audio ? "audio" : "video"); + + mRenderer->queueEOS(audio, UNKNOWN_ERROR); } else { CHECK_EQ((int)what, (int)ACodec::kWhatDrainThisBuffer); @@ -358,13 +363,24 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { int32_t audio; CHECK(msg->findInt32("audio", &audio)); + int32_t finalResult; + CHECK(msg->findInt32("finalResult", &finalResult)); + if (audio) { mAudioEOS = true; } else { mVideoEOS = true; } - LOGV("reached %s EOS", audio ? "audio" : "video"); + if (finalResult == ERROR_END_OF_STREAM) { + LOGV("reached %s EOS", audio ? "audio" : "video"); + } else { + LOGE("%s track encountered an error (0x%08x)", + audio ? "audio" : "video", finalResult); + + notifyListener( + MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, finalResult); + } if ((mAudioEOS || mAudioDecoder == NULL) && (mVideoEOS || mVideoDecoder == NULL)) { diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp index 828e008..35ed43f 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp @@ -200,19 +200,6 @@ void NuPlayer::Renderer::signalAudioSinkChanged() { void NuPlayer::Renderer::onDrainAudioQueue() { for (;;) { - uint32_t numFramesPlayed; - CHECK_EQ(mAudioSink->getPosition(&numFramesPlayed), (status_t)OK); - - ssize_t numFramesAvailableToWrite = - mAudioSink->frameCount() - (mNumFramesWritten - numFramesPlayed); - - size_t numBytesAvailableToWrite = - numFramesAvailableToWrite * mAudioSink->frameSize(); - - if (numBytesAvailableToWrite == 0) { - break; - } - if (mAudioQueue.empty()) { break; } @@ -222,13 +209,26 @@ void NuPlayer::Renderer::onDrainAudioQueue() { if (entry->mBuffer == NULL) { // EOS - notifyEOS(true /* audio */); + notifyEOS(true /* audio */, entry->mFinalResult); mAudioQueue.erase(mAudioQueue.begin()); entry = NULL; return; } + uint32_t numFramesPlayed; + CHECK_EQ(mAudioSink->getPosition(&numFramesPlayed), (status_t)OK); + + ssize_t numFramesAvailableToWrite = + mAudioSink->frameCount() - (mNumFramesWritten - numFramesPlayed); + + size_t numBytesAvailableToWrite = + numFramesAvailableToWrite * mAudioSink->frameSize(); + + if (numBytesAvailableToWrite == 0) { + break; + } + if (entry->mOffset == 0) { int64_t mediaTimeUs; CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs)); @@ -330,7 +330,7 @@ void NuPlayer::Renderer::onDrainVideoQueue() { if (entry->mBuffer == NULL) { // EOS - notifyEOS(false /* audio */); + notifyEOS(false /* audio */, entry->mFinalResult); mVideoQueue.erase(mVideoQueue.begin()); entry = NULL; @@ -352,10 +352,11 @@ void NuPlayer::Renderer::onDrainVideoQueue() { notifyPosition(); } -void NuPlayer::Renderer::notifyEOS(bool audio) { +void NuPlayer::Renderer::notifyEOS(bool audio, status_t finalResult) { sp<AMessage> notify = mNotify->dup(); notify->setInt32("what", kWhatEOS); notify->setInt32("audio", static_cast<int32_t>(audio)); + notify->setInt32("finalResult", finalResult); notify->post(); } diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h index 703e971..2713031 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h +++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h @@ -111,7 +111,7 @@ private: void onPause(); void onResume(); - void notifyEOS(bool audio); + void notifyEOS(bool audio, status_t finalResult); void notifyFlushComplete(bool audio); void notifyPosition(); diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp index 174ec92..5d91f6a 100644 --- a/media/libstagefright/ACodec.cpp +++ b/media/libstagefright/ACodec.cpp @@ -285,21 +285,6 @@ private: //////////////////////////////////////////////////////////////////////////////// -struct ACodec::ErrorState : public ACodec::BaseState { - ErrorState(ACodec *codec); - -protected: - virtual bool onMessageReceived(const sp<AMessage> &msg); - virtual void stateEntered(); - - virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); - -private: - DISALLOW_EVIL_CONSTRUCTORS(ErrorState); -}; - -//////////////////////////////////////////////////////////////////////////////// - struct ACodec::FlushingState : public ACodec::BaseState { FlushingState(ACodec *codec); @@ -335,7 +320,6 @@ ACodec::ACodec() mExecutingToIdleState = new ExecutingToIdleState(this); mIdleToLoadedState = new IdleToLoadedState(this); - mErrorState = new ErrorState(this); mFlushingState = new FlushingState(this); mPortEOS[kPortIndexInput] = mPortEOS[kPortIndexOutput] = false; @@ -594,7 +578,10 @@ status_t ACodec::cancelBufferToNativeWindow(BufferInfo *info) { ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() { ANativeWindowBuffer *buf; - CHECK_EQ(mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf), 0); + if (mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf) != 0) { + LOGE("dequeueBuffer failed."); + return NULL; + } for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) { BufferInfo *info = @@ -1263,10 +1250,12 @@ bool ACodec::BaseState::onOMXEvent( return false; } - LOGE("[%s] ERROR(0x%08lx, 0x%08lx)", - mCodec->mComponentName.c_str(), data1, data2); + LOGE("[%s] ERROR(0x%08lx)", mCodec->mComponentName.c_str(), data1); - mCodec->changeState(mCodec->mErrorState); + sp<AMessage> notify = mCodec->mNotify->dup(); + notify->setInt32("what", ACodec::kWhatError); + notify->setInt32("omx-error", data1); + notify->post(); return true; } @@ -1595,13 +1584,15 @@ void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) { info = mCodec->dequeueBufferFromNativeWindow(); } - LOGV("[%s] calling fillBuffer %p", - mCodec->mComponentName.c_str(), info->mBufferID); + if (info != NULL) { + LOGV("[%s] calling fillBuffer %p", + mCodec->mComponentName.c_str(), info->mBufferID); - CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID), - (status_t)OK); + CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID), + (status_t)OK); - info->mStatus = BufferInfo::OWNED_BY_COMPONENT; + info->mStatus = BufferInfo::OWNED_BY_COMPONENT; + } } break; } @@ -1642,6 +1633,7 @@ bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) { notify->post(); handled = true; + break; } case ACodec::kWhatFlush: @@ -1651,6 +1643,7 @@ bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) { notify->post(); handled = true; + break; } default: @@ -1696,7 +1689,16 @@ void ACodec::UninitializedState::onSetup( node = NULL; } - CHECK(node != NULL); + if (node == NULL) { + LOGE("Unable to instantiate a decoder for type '%s'.", mime.c_str()); + + sp<AMessage> notify = mCodec->mNotify->dup(); + notify->setInt32("what", ACodec::kWhatError); + notify->setInt32("omx-error", OMX_ErrorComponentNotFound); + notify->post(); + + return; + } sp<AMessage> notify = new AMessage(kWhatOMXMessage, mCodec->id()); observer->setNotificationMessage(notify); @@ -2236,26 +2238,6 @@ bool ACodec::IdleToLoadedState::onOMXEvent( //////////////////////////////////////////////////////////////////////////////// -ACodec::ErrorState::ErrorState(ACodec *codec) - : BaseState(codec) { -} - -bool ACodec::ErrorState::onMessageReceived(const sp<AMessage> &msg) { - return BaseState::onMessageReceived(msg); -} - -void ACodec::ErrorState::stateEntered() { - LOGV("[%s] Now in ErrorState", mCodec->mComponentName.c_str()); -} - -bool ACodec::ErrorState::onOMXEvent( - OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { - LOGV("EVENT(%d, 0x%08lx, 0x%08lx)", event, data1, data2); - return true; -} - -//////////////////////////////////////////////////////////////////////////////// - ACodec::FlushingState::FlushingState(ACodec *codec) : BaseState(codec) { } diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk index b9e4f9f..0b1a2af 100644 --- a/media/libstagefright/Android.mk +++ b/media/libstagefright/Android.mk @@ -131,11 +131,9 @@ LOCAL_SHARED_LIBRARIES += \ libdl \ LOCAL_STATIC_LIBRARIES += \ - libstagefright_chromium_http \ - libwebcore \ - libchromium_net \ + libstagefright_chromium_http -LOCAL_SHARED_LIBRARIES += libstlport +LOCAL_SHARED_LIBRARIES += libstlport libchromium_net include external/stlport/libstlport.mk LOCAL_CPPFLAGS += -DCHROMIUM_AVAILABLE=1 diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp index 0ea880b..99242ab 100644 --- a/media/libstagefright/AwesomePlayer.cpp +++ b/media/libstagefright/AwesomePlayer.cpp @@ -574,6 +574,8 @@ void AwesomePlayer::reset_l() { mStats.mTracks.clear(); } + mWatchForAudioSeekComplete = false; + mWatchForAudioEOS = false; } void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) { diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp index 73a05a5..3b79f06 100644 --- a/media/libstagefright/MPEG4Extractor.cpp +++ b/media/libstagefright/MPEG4Extractor.cpp @@ -1687,6 +1687,11 @@ status_t MPEG4Extractor::verifyTrack(Track *track) { } } + if (!track->sampleTable->isValid()) { + // Make sure we have all the metadata we need. + return ERROR_MALFORMED; + } + return OK; } diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp index 644c413..27dfeab 100755 --- a/media/libstagefright/OMXCodec.cpp +++ b/media/libstagefright/OMXCodec.cpp @@ -3199,9 +3199,16 @@ void OMXCodec::setState(State newState) { } status_t OMXCodec::waitForBufferFilled_l() { + + if (mIsEncoder) { + // For timelapse video recording, the timelapse video recording may + // not send an input frame for a _long_ time. Do not use timeout + // for video encoding. + return mBufferFilled.wait(mLock); + } status_t err = mBufferFilled.waitRelative(mLock, kBufferFilledEventTimeOutUs); if (err != OK) { - LOGE("Timed out waiting for buffers from video encoder: %d/%d", + CODEC_LOGE("Timed out waiting for output buffers: %d/%d", countBuffersWeOwn(mPortBuffers[kPortIndexInput]), countBuffersWeOwn(mPortBuffers[kPortIndexOutput])); } diff --git a/media/libstagefright/SampleTable.cpp b/media/libstagefright/SampleTable.cpp index a8a094e..2b9d99b 100644 --- a/media/libstagefright/SampleTable.cpp +++ b/media/libstagefright/SampleTable.cpp @@ -84,6 +84,13 @@ SampleTable::~SampleTable() { mSampleIterator = NULL; } +bool SampleTable::isValid() const { + return mChunkOffsetOffset >= 0 + && mSampleToChunkOffset >= 0 + && mSampleSizeOffset >= 0 + && mTimeToSample != NULL; +} + status_t SampleTable::setChunkOffsetParams( uint32_t type, off64_t data_offset, size_t data_size) { if (mChunkOffsetOffset >= 0) { diff --git a/media/libstagefright/include/SampleTable.h b/media/libstagefright/include/SampleTable.h index f44e0a2..a6a6524 100644 --- a/media/libstagefright/include/SampleTable.h +++ b/media/libstagefright/include/SampleTable.h @@ -34,6 +34,8 @@ class SampleTable : public RefBase { public: SampleTable(const sp<DataSource> &source); + bool isValid() const; + // type can be 'stco' or 'co64'. status_t setChunkOffsetParams( uint32_t type, off64_t data_offset, size_t data_size); |