summaryrefslogtreecommitdiffstats
path: root/media/libmediaplayerservice/nuplayer
diff options
context:
space:
mode:
authorAndreas Huber <andih@google.com>2011-01-04 14:01:29 -0800
committerAndreas Huber <andih@google.com>2011-01-04 14:07:58 -0800
commitcbeaca7a819cc11724f6f34457dabf5bd55a84a1 (patch)
treed4601ae2e269aa16dfbd5c138c4d6bae285701dd /media/libmediaplayerservice/nuplayer
parent08a4186b1f0ca71aac94a24c1dbbdc0a84b8c705 (diff)
downloadframeworks_base-cbeaca7a819cc11724f6f34457dabf5bd55a84a1.zip
frameworks_base-cbeaca7a819cc11724f6f34457dabf5bd55a84a1.tar.gz
frameworks_base-cbeaca7a819cc11724f6f34457dabf5bd55a84a1.tar.bz2
Properly shutdown the decoders on a reset() in NuPlayer's implementation.
related-to-bug: 3321470 Change-Id: Ida6d2171c5a3a407188d4633602b764f8fe7086a
Diffstat (limited to 'media/libmediaplayerservice/nuplayer')
-rw-r--r--media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp2
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayer.cpp201
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayer.h18
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp25
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerDriver.h6
5 files changed, 191 insertions, 61 deletions
diff --git a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
index c656e69..29e4971 100644
--- a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
@@ -87,7 +87,7 @@ bool NuPlayer::HTTPLiveSource::feedMoreTSData() {
break;
} else if (n < 0) {
LOGI("input data EOS reached.");
- mTSParser->signalEOS(ERROR_END_OF_STREAM);
+ mTSParser->signalEOS(n);
mEOS = true;
break;
} else {
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 24efa35..9a8cff3 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -45,8 +45,11 @@ NuPlayer::NuPlayer()
: mAudioEOS(false),
mVideoEOS(false),
mScanSourcesPending(false),
+ mScanSourcesGeneration(0),
mFlushingAudio(NONE),
- mFlushingVideo(NONE) {
+ mFlushingVideo(NONE),
+ mResetInProgress(false),
+ mResetPostponed(false) {
}
NuPlayer::~NuPlayer() {
@@ -87,18 +90,22 @@ void NuPlayer::start() {
(new AMessage(kWhatStart, id()))->post();
}
+void NuPlayer::resetAsync() {
+ (new AMessage(kWhatReset, id()))->post();
+}
+
// static
-bool NuPlayer::IsFlushingState(FlushStatus state, bool *formatChange) {
+bool NuPlayer::IsFlushingState(FlushStatus state, bool *needShutdown) {
switch (state) {
case FLUSHING_DECODER:
- if (formatChange != NULL) {
- *formatChange = false;
+ if (needShutdown != NULL) {
+ *needShutdown = false;
}
return true;
- case FLUSHING_DECODER_FORMATCHANGE:
- if (formatChange != NULL) {
- *formatChange = true;
+ case FLUSHING_DECODER_SHUTDOWN:
+ if (needShutdown != NULL) {
+ *needShutdown = true;
}
return true;
@@ -111,7 +118,7 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
switch (msg->what()) {
case kWhatSetDataSource:
{
- LOGI("kWhatSetDataSource");
+ LOGV("kWhatSetDataSource");
CHECK(mSource == NULL);
@@ -124,7 +131,7 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
case kWhatSetVideoSurface:
{
- LOGI("kWhatSetVideoSurface");
+ LOGV("kWhatSetVideoSurface");
sp<RefBase> obj;
CHECK(msg->findObject("surface", &obj));
@@ -135,7 +142,7 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
case kWhatSetAudioSink:
{
- LOGI("kWhatSetAudioSink");
+ LOGV("kWhatSetAudioSink");
sp<RefBase> obj;
CHECK(msg->findObject("sink", &obj));
@@ -146,6 +153,9 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
case kWhatStart:
{
+ mAudioEOS = false;
+ mVideoEOS = false;
+
mSource->start();
mRenderer = new Renderer(
@@ -154,13 +164,19 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
looper()->registerHandler(mRenderer);
- (new AMessage(kWhatScanSources, id()))->post();
- mScanSourcesPending = true;
+ postScanSources();
break;
}
case kWhatScanSources:
{
+ int32_t generation;
+ CHECK(msg->findInt32("generation", &generation));
+ if (generation != mScanSourcesGeneration) {
+ // Drop obsolete msg.
+ break;
+ }
+
mScanSourcesPending = false;
instantiateDecoder(false, &mVideoDecoder);
@@ -170,6 +186,11 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
}
if (!mSource->feedMoreTSData()) {
+ if (mAudioDecoder == NULL && mVideoDecoder == NULL) {
+ // We're not currently decoding anything (no audio or
+ // video tracks found) and we just ran out of input data.
+ notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0);
+ }
break;
}
@@ -203,20 +224,20 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
} else if (what == ACodec::kWhatEOS) {
mRenderer->queueEOS(audio, ERROR_END_OF_STREAM);
} else if (what == ACodec::kWhatFlushCompleted) {
- bool formatChange;
+ bool needShutdown;
if (audio) {
- CHECK(IsFlushingState(mFlushingAudio, &formatChange));
+ CHECK(IsFlushingState(mFlushingAudio, &needShutdown));
mFlushingAudio = FLUSHED;
} else {
- CHECK(IsFlushingState(mFlushingVideo, &formatChange));
+ CHECK(IsFlushingState(mFlushingVideo, &needShutdown));
mFlushingVideo = FLUSHED;
}
- LOGI("decoder %s flush completed", audio ? "audio" : "video");
+ LOGV("decoder %s flush completed", audio ? "audio" : "video");
- if (formatChange) {
- LOGI("initiating %s decoder shutdown",
+ if (needShutdown) {
+ LOGV("initiating %s decoder shutdown",
audio ? "audio" : "video");
(audio ? mAudioDecoder : mVideoDecoder)->initiateShutdown();
@@ -238,7 +259,7 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
int32_t sampleRate;
CHECK(codecRequest->findInt32("sample-rate", &sampleRate));
- LOGI("Audio output format changed to %d Hz, %d channels",
+ LOGV("Audio output format changed to %d Hz, %d channels",
sampleRate, numChannels);
mAudioSink->close();
@@ -247,7 +268,7 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
mRenderer->signalAudioSinkChanged();
} else if (what == ACodec::kWhatShutdownCompleted) {
- LOGI("%s shutdown completed", audio ? "audio" : "video");
+ LOGV("%s shutdown completed", audio ? "audio" : "video");
if (audio) {
mAudioDecoder.clear();
@@ -285,7 +306,7 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
mVideoEOS = true;
}
- LOGI("reached %s EOS", audio ? "audio" : "video");
+ LOGV("reached %s EOS", audio ? "audio" : "video");
if ((mAudioEOS || mAudioDecoder == NULL)
&& (mVideoEOS || mVideoDecoder == NULL)) {
@@ -297,7 +318,7 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
int32_t audio;
CHECK(msg->findInt32("audio", &audio));
- LOGI("renderer %s flush completed.", audio ? "audio" : "video");
+ LOGV("renderer %s flush completed.", audio ? "audio" : "video");
}
break;
}
@@ -307,6 +328,37 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
break;
}
+ case kWhatReset:
+ {
+ LOGV("kWhatReset");
+
+ if (mFlushingAudio != NONE || mFlushingVideo != NONE) {
+ // We're currently flushing, postpone the reset until that's
+ // completed.
+
+ LOGV("postponing reset");
+
+ mResetPostponed = true;
+ break;
+ }
+
+ if (mAudioDecoder == NULL && mVideoDecoder == NULL) {
+ finishReset();
+ break;
+ }
+
+ if (mAudioDecoder != NULL) {
+ flushDecoder(true /* audio */, true /* needShutdown */);
+ }
+
+ if (mVideoDecoder != NULL) {
+ flushDecoder(false /* audio */, true /* needShutdown */);
+ }
+
+ mResetInProgress = true;
+ break;
+ }
+
default:
TRESPASS();
break;
@@ -322,7 +374,7 @@ void NuPlayer::finishFlushIfPossible() {
return;
}
- LOGI("both audio and video are flushed now.");
+ LOGV("both audio and video are flushed now.");
mRenderer->signalTimeDiscontinuity();
@@ -343,10 +395,39 @@ void NuPlayer::finishFlushIfPossible() {
mFlushingAudio = NONE;
mFlushingVideo = NONE;
- if (scanSourcesAgain && !mScanSourcesPending) {
- mScanSourcesPending = true;
- (new AMessage(kWhatScanSources, id()))->post();
+ if (mResetInProgress) {
+ LOGV("reset completed");
+
+ mResetInProgress = false;
+ finishReset();
+ } else if (mResetPostponed) {
+ (new AMessage(kWhatReset, id()))->post();
+ mResetPostponed = false;
+ } else if (scanSourcesAgain) {
+ postScanSources();
+ }
+}
+
+void NuPlayer::finishReset() {
+ CHECK(mAudioDecoder == NULL);
+ CHECK(mVideoDecoder == NULL);
+
+ mRenderer.clear();
+ mSource.clear();
+
+ notifyListener(MEDIA_RESET_COMPLETE, 0, 0);
+}
+
+void NuPlayer::postScanSources() {
+ if (mScanSourcesPending) {
+ return;
}
+
+ sp<AMessage> msg = new AMessage(kWhatScanSources, id());
+ msg->setInt32("generation", mScanSourcesGeneration);
+ msg->post();
+
+ mScanSourcesPending = true;
}
status_t NuPlayer::instantiateDecoder(bool audio, sp<Decoder> *decoder) {
@@ -396,37 +477,10 @@ status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) {
bool formatChange =
type == ATSParser::DISCONTINUITY_FORMATCHANGE;
- LOGI("%s discontinuity (formatChange=%d)",
+ LOGV("%s discontinuity (formatChange=%d)",
audio ? "audio" : "video", formatChange);
- (audio ? mAudioDecoder : mVideoDecoder)->signalFlush();
- mRenderer->flush(audio);
-
- if (audio) {
- CHECK(mFlushingAudio == NONE
- || mFlushingAudio == AWAITING_DISCONTINUITY);
-
- mFlushingAudio = formatChange
- ? FLUSHING_DECODER_FORMATCHANGE : FLUSHING_DECODER;
-
- if (mFlushingVideo == NONE) {
- mFlushingVideo = (mVideoDecoder != NULL)
- ? AWAITING_DISCONTINUITY
- : FLUSHED;
- }
- } else {
- CHECK(mFlushingVideo == NONE
- || mFlushingVideo == AWAITING_DISCONTINUITY);
-
- mFlushingVideo = formatChange
- ? FLUSHING_DECODER_FORMATCHANGE : FLUSHING_DECODER;
-
- if (mFlushingAudio == NONE) {
- mFlushingAudio = (mAudioDecoder != NULL)
- ? AWAITING_DISCONTINUITY
- : FLUSHED;
- }
- }
+ flushDecoder(audio, formatChange);
}
reply->setInt32("err", err);
@@ -439,7 +493,7 @@ status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) {
#if 0
int64_t mediaTimeUs;
CHECK(accessUnit->meta()->findInt64("timeUs", &mediaTimeUs));
- LOGI("feeding %s input buffer at media time %.2f secs",
+ LOGV("feeding %s input buffer at media time %.2f secs",
audio ? "audio" : "video",
mediaTimeUs / 1E6);
#endif
@@ -478,4 +532,39 @@ void NuPlayer::notifyListener(int msg, int ext1, int ext2) {
listener->sendEvent(msg, ext1, ext2);
}
+void NuPlayer::flushDecoder(bool audio, bool needShutdown) {
+ // Make sure we don't continue to scan sources until we finish flushing.
+ ++mScanSourcesGeneration;
+
+ (audio ? mAudioDecoder : mVideoDecoder)->signalFlush();
+ mRenderer->flush(audio);
+
+ FlushStatus newStatus =
+ needShutdown ? FLUSHING_DECODER_SHUTDOWN : FLUSHING_DECODER;
+
+ if (audio) {
+ CHECK(mFlushingAudio == NONE
+ || mFlushingAudio == AWAITING_DISCONTINUITY);
+
+ mFlushingAudio = newStatus;
+
+ if (mFlushingVideo == NONE) {
+ mFlushingVideo = (mVideoDecoder != NULL)
+ ? AWAITING_DISCONTINUITY
+ : FLUSHED;
+ }
+ } else {
+ CHECK(mFlushingVideo == NONE
+ || mFlushingVideo == AWAITING_DISCONTINUITY);
+
+ mFlushingVideo = newStatus;
+
+ if (mFlushingAudio == NONE) {
+ mFlushingAudio = (mAudioDecoder != NULL)
+ ? AWAITING_DISCONTINUITY
+ : FLUSHED;
+ }
+ }
+}
+
} // namespace android
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index 172a962..1cf2f60 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -40,6 +40,10 @@ struct NuPlayer : public AHandler {
void setAudioSink(const sp<MediaPlayerBase::AudioSink> &sink);
void start();
+ // Will notify the listener that reset() has completed
+ // with code MEDIA_RESET_COMPLETE.
+ void resetAsync();
+
protected:
virtual ~NuPlayer();
@@ -63,6 +67,7 @@ private:
kWhatVideoNotify,
kWhatAudioNotify,
kWhatRendererNotify,
+ kWhatReset,
};
wp<MediaPlayerBase> mListener;
@@ -73,17 +78,17 @@ private:
sp<Decoder> mAudioDecoder;
sp<Renderer> mRenderer;
- bool mEOS;
bool mAudioEOS;
bool mVideoEOS;
bool mScanSourcesPending;
+ int32_t mScanSourcesGeneration;
enum FlushStatus {
NONE,
AWAITING_DISCONTINUITY,
FLUSHING_DECODER,
- FLUSHING_DECODER_FORMATCHANGE,
+ FLUSHING_DECODER_SHUTDOWN,
SHUTTING_DOWN_DECODER,
FLUSHED,
SHUT_DOWN,
@@ -91,6 +96,8 @@ private:
FlushStatus mFlushingAudio;
FlushStatus mFlushingVideo;
+ bool mResetInProgress;
+ bool mResetPostponed;
status_t instantiateDecoder(bool audio, sp<Decoder> *decoder);
@@ -101,7 +108,12 @@ private:
void finishFlushIfPossible();
- static bool IsFlushingState(FlushStatus state, bool *formatChange = NULL);
+ void flushDecoder(bool audio, bool needShutdown);
+
+ static bool IsFlushingState(FlushStatus state, bool *needShutdown = NULL);
+
+ void finishReset();
+ void postScanSources();
DISALLOW_EVIL_CONSTRUCTORS(NuPlayer);
};
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index d21d4ff..4988d24 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -22,12 +22,14 @@
#include "NuPlayer.h"
+#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/ALooper.h>
namespace android {
NuPlayerDriver::NuPlayerDriver()
- : mLooper(new ALooper),
+ : mResetInProgress(false),
+ mLooper(new ALooper),
mPlayer(false) {
mLooper->setName("NuPlayerDriver Looper");
@@ -121,6 +123,15 @@ status_t NuPlayerDriver::getDuration(int *msec) {
}
status_t NuPlayerDriver::reset() {
+ Mutex::Autolock autoLock(mLock);
+ mResetInProgress = true;
+
+ mPlayer->resetAsync();
+
+ while (mResetInProgress) {
+ mCondition.wait(mLock);
+ }
+
return OK;
}
@@ -145,4 +156,16 @@ status_t NuPlayerDriver::getMetadata(
return INVALID_OPERATION;
}
+void NuPlayerDriver::sendEvent(int msg, int ext1, int ext2) {
+ if (msg != MEDIA_RESET_COMPLETE) {
+ MediaPlayerInterface::sendEvent(msg, ext1, ext2);
+ return;
+ }
+
+ Mutex::Autolock autoLock(mLock);
+ CHECK(mResetInProgress);
+ mResetInProgress = false;
+ mCondition.broadcast();
+}
+
} // namespace android
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
index 44ae3bf..f153af4 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
@@ -54,10 +54,16 @@ struct NuPlayerDriver : public MediaPlayerInterface {
virtual status_t getMetadata(
const media::Metadata::Filter& ids, Parcel *records);
+ virtual void sendEvent(int msg, int ext1 = 0, int ext2 = 0);
+
protected:
virtual ~NuPlayerDriver();
private:
+ Mutex mLock;
+ Condition mCondition;
+ bool mResetInProgress;
+
sp<ALooper> mLooper;
sp<NuPlayer> mPlayer;
bool mPlaying;