From a1f8ab0ad670c30e57f3f072df13df66fe4f4910 Mon Sep 17 00:00:00 2001 From: Andreas Huber Date: Fri, 30 Nov 2012 10:53:22 -0800 Subject: Fix nuplayer seek jankiness by properly flushing decoders before initiating the seek. Also refactor the nuplayer state machine to make this a little more maintainable and extensible in the future. Change-Id: I36a673bdecff732bca7094c8f72bac24f37c01e9 related-to-bug: 7120373 --- media/libmediaplayerservice/nuplayer/NuPlayer.cpp | 279 +++++++++++++++------- 1 file changed, 194 insertions(+), 85 deletions(-) (limited to 'media/libmediaplayerservice/nuplayer/NuPlayer.cpp') diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index d3ec122..f363568 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -50,6 +50,49 @@ namespace android { +struct NuPlayer::Action : public RefBase { + Action() {} + + virtual void execute(NuPlayer *player) = 0; + +private: + DISALLOW_EVIL_CONSTRUCTORS(Action); +}; + +struct NuPlayer::SeekAction : public Action { + SeekAction(int64_t seekTimeUs) + : mSeekTimeUs(seekTimeUs) { + } + + virtual void execute(NuPlayer *player) { + player->performSeek(mSeekTimeUs); + } + +private: + int64_t mSeekTimeUs; + + DISALLOW_EVIL_CONSTRUCTORS(SeekAction); +}; + +// Use this if there's no state necessary to save in order to execute +// the action. +struct NuPlayer::SimpleAction : public Action { + typedef void (NuPlayer::*ActionFunc)(); + + SimpleAction(ActionFunc func) + : mFunc(func) { + } + + virtual void execute(NuPlayer *player) { + (player->*mFunc)(); + } + +private: + ActionFunc mFunc; + + DISALLOW_EVIL_CONSTRUCTORS(SimpleAction); +}; + //////////////////////////////////////////////////////////////////////////////// NuPlayer::NuPlayer() @@ -63,8 +106,6 @@ NuPlayer::NuPlayer() mTimeDiscontinuityPending(false), mFlushingAudio(NONE), mFlushingVideo(NONE), - mResetInProgress(false), - mResetPostponed(false), mSkipRenderingAudioUntilMediaTimeUs(-1ll), mSkipRenderingVideoUntilMediaTimeUs(-1ll), mVideoLateByUs(0ll), @@ -495,8 +536,15 @@ void NuPlayer::onMessageReceived(const sp &msg) { mRenderer->queueEOS(audio, UNKNOWN_ERROR); } else if (what == ACodec::kWhatDrainThisBuffer) { renderBuffer(audio, codecRequest); - } else { - ALOGV("Unhandled codec notification %d.", what); + } else if (what != ACodec::kWhatComponentAllocated + && what != ACodec::kWhatComponentConfigured + && what != ACodec::kWhatBuffersAllocated) { + ALOGV("Unhandled codec notification %d '%c%c%c%c'.", + what, + what >> 24, + (what >> 16) & 0xff, + (what >> 8) & 0xff, + what & 0xff); } break; @@ -569,47 +617,13 @@ void NuPlayer::onMessageReceived(const sp &msg) { { ALOGV("kWhatReset"); - cancelPollDuration(); - - if (mRenderer != NULL) { - // There's an edge case where the renderer owns all output - // buffers and is paused, therefore the decoder will not read - // more input data and will never encounter the matching - // discontinuity. To avoid this, we resume the renderer. + mDeferredActions.push_back( + new SimpleAction(&NuPlayer::performDecoderShutdown)); - if (mFlushingAudio == AWAITING_DISCONTINUITY - || mFlushingVideo == AWAITING_DISCONTINUITY) { - mRenderer->resume(); - } - } - - if (mFlushingAudio != NONE || mFlushingVideo != NONE) { - // We're currently flushing, postpone the reset until that's - // completed. + mDeferredActions.push_back( + new SimpleAction(&NuPlayer::performReset)); - ALOGV("postponing reset mFlushingAudio=%d, mFlushingVideo=%d", - mFlushingAudio, mFlushingVideo); - - mResetPostponed = true; - break; - } - - if (mAudioDecoder == NULL && mVideoDecoder == NULL) { - finishReset(); - break; - } - - mTimeDiscontinuityPending = true; - - if (mAudioDecoder != NULL) { - flushDecoder(true /* audio */, true /* needShutdown */); - } - - if (mVideoDecoder != NULL) { - flushDecoder(false /* audio */, true /* needShutdown */); - } - - mResetInProgress = true; + processDeferredActions(); break; } @@ -618,18 +632,14 @@ void NuPlayer::onMessageReceived(const sp &msg) { int64_t seekTimeUs; CHECK(msg->findInt64("seekTimeUs", &seekTimeUs)); - ALOGV("kWhatSeek seekTimeUs=%lld us (%.2f secs)", - seekTimeUs, seekTimeUs / 1E6); + ALOGV("kWhatSeek seekTimeUs=%lld us", seekTimeUs); - mSource->seekTo(seekTimeUs); + mDeferredActions.push_back( + new SimpleAction(&NuPlayer::performDecoderFlush)); - if (mDriver != NULL) { - sp driver = mDriver.promote(); - if (driver != NULL) { - driver->notifySeekComplete(); - } - } + mDeferredActions.push_back(new SeekAction(seekTimeUs)); + processDeferredActions(); break; } @@ -680,39 +690,7 @@ void NuPlayer::finishFlushIfPossible() { mFlushingAudio = NONE; mFlushingVideo = NONE; - if (mResetInProgress) { - ALOGV("reset completed"); - - mResetInProgress = false; - finishReset(); - } else if (mResetPostponed) { - (new AMessage(kWhatReset, id()))->post(); - mResetPostponed = false; - } else if (mAudioDecoder == NULL || mVideoDecoder == NULL) { - postScanSources(); - } -} - -void NuPlayer::finishReset() { - CHECK(mAudioDecoder == NULL); - CHECK(mVideoDecoder == NULL); - - ++mScanSourcesGeneration; - mScanSourcesPending = false; - - mRenderer.clear(); - - if (mSource != NULL) { - mSource->stop(); - mSource.clear(); - } - - if (mDriver != NULL) { - sp driver = mDriver.promote(); - if (driver != NULL) { - driver->notifyResetComplete(); - } - } + processDeferredActions(); } void NuPlayer::postScanSources() { @@ -831,6 +809,14 @@ status_t NuPlayer::feedDecoderInputData(bool audio, const sp &msg) { mTimeDiscontinuityPending || timeChange; if (formatChange || timeChange) { + if (mFlushingAudio == NONE && mFlushingVideo == NONE) { + // And we'll resume scanning sources once we're done + // flushing. + mDeferredActions.push_front( + new SimpleAction( + &NuPlayer::performScanSources)); + } + flushDecoder(audio, formatChange); } else { // This stream is unaffected by the discontinuity @@ -1023,4 +1009,127 @@ void NuPlayer::cancelPollDuration() { ++mPollDurationGeneration; } +void NuPlayer::processDeferredActions() { + while (!mDeferredActions.empty()) { + // We won't execute any deferred actions until we're no longer in + // an intermediate state, i.e. one more more decoders are currently + // flushing or shutting down. + + if (mRenderer != NULL) { + // There's an edge case where the renderer owns all output + // buffers and is paused, therefore the decoder will not read + // more input data and will never encounter the matching + // discontinuity. To avoid this, we resume the renderer. + + if (mFlushingAudio == AWAITING_DISCONTINUITY + || mFlushingVideo == AWAITING_DISCONTINUITY) { + mRenderer->resume(); + } + } + + if (mFlushingAudio != NONE || mFlushingVideo != NONE) { + // We're currently flushing, postpone the reset until that's + // completed. + + ALOGV("postponing action mFlushingAudio=%d, mFlushingVideo=%d", + mFlushingAudio, mFlushingVideo); + + break; + } + + sp action = *mDeferredActions.begin(); + mDeferredActions.erase(mDeferredActions.begin()); + + action->execute(this); + } +} + +void NuPlayer::performSeek(int64_t seekTimeUs) { + ALOGV("performSeek seekTimeUs=%lld us (%.2f secs)", + seekTimeUs, + seekTimeUs / 1E6); + + mSource->seekTo(seekTimeUs); + + if (mDriver != NULL) { + sp driver = mDriver.promote(); + if (driver != NULL) { + driver->notifyPosition(seekTimeUs); + driver->notifySeekComplete(); + } + } + + // everything's flushed, continue playback. +} + +void NuPlayer::performDecoderFlush() { + ALOGV("performDecoderFlush"); + + if (mAudioDecoder != NULL && mVideoDecoder == NULL) { + return; + } + + mTimeDiscontinuityPending = true; + + if (mAudioDecoder != NULL) { + flushDecoder(true /* audio */, false /* needShutdown */); + } + + if (mVideoDecoder != NULL) { + flushDecoder(false /* audio */, false /* needShutdown */); + } +} + +void NuPlayer::performDecoderShutdown() { + ALOGV("performDecoderShutdown"); + + if (mAudioDecoder != NULL && mVideoDecoder == NULL) { + return; + } + + mTimeDiscontinuityPending = true; + + if (mAudioDecoder != NULL) { + flushDecoder(true /* audio */, true /* needShutdown */); + } + + if (mVideoDecoder != NULL) { + flushDecoder(false /* audio */, true /* needShutdown */); + } +} + +void NuPlayer::performReset() { + ALOGV("performReset"); + + CHECK(mAudioDecoder == NULL); + CHECK(mVideoDecoder == NULL); + + cancelPollDuration(); + + ++mScanSourcesGeneration; + mScanSourcesPending = false; + + mRenderer.clear(); + + if (mSource != NULL) { + mSource->stop(); + mSource.clear(); + } + + if (mDriver != NULL) { + sp driver = mDriver.promote(); + if (driver != NULL) { + driver->notifyResetComplete(); + } + } +} + +void NuPlayer::performScanSources() { + ALOGV("performScanSources"); + + if (mAudioDecoder == NULL || mVideoDecoder == NULL) { + postScanSources(); + } +} + } // namespace android -- cgit v1.1 From 57a339cdb7524f883de3ceb364c0b5606df0c610 Mon Sep 17 00:00:00 2001 From: Andreas Huber Date: Mon, 3 Dec 2012 11:18:00 -0800 Subject: setVideoSurfaceTexture is now synchronous and applied dynamically while playing. Change-Id: If9f08659a01bdc7dac0999730368e9dfa5e58d36 related-to-bug: 5666482 --- media/libmediaplayerservice/nuplayer/NuPlayer.cpp | 77 ++++++++++++++++++++--- 1 file changed, 67 insertions(+), 10 deletions(-) (limited to 'media/libmediaplayerservice/nuplayer/NuPlayer.cpp') diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index f363568..f9c3283 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -74,6 +74,21 @@ private: DISALLOW_EVIL_CONSTRUCTORS(SeekAction); }; +struct NuPlayer::SetSurfaceAction : public Action { + SetSurfaceAction(const sp &wrapper) + : mWrapper(wrapper) { + } + + virtual void execute(NuPlayer *player) { + player->performSetSurface(mWrapper); + } + +private: + sp mWrapper; + + DISALLOW_EVIL_CONSTRUCTORS(SetSurfaceAction); +}; + // Use this if there's no state necessary to save in order to execute // the action. struct NuPlayer::SimpleAction : public Action { @@ -111,7 +126,8 @@ NuPlayer::NuPlayer() mVideoLateByUs(0ll), mNumFramesTotal(0ll), mNumFramesDropped(0ll), - mVideoScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW) { + mVideoScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW), + mStarted(false) { } NuPlayer::~NuPlayer() { @@ -181,11 +197,19 @@ void NuPlayer::setDataSource(int fd, int64_t offset, int64_t length) { msg->post(); } -void NuPlayer::setVideoSurfaceTexture(const sp &surfaceTexture) { +void NuPlayer::setVideoSurfaceTextureAsync( + const sp &surfaceTexture) { sp msg = new AMessage(kWhatSetVideoNativeWindow, id()); - sp surfaceTextureClient(surfaceTexture != NULL ? - new SurfaceTextureClient(surfaceTexture) : NULL); - msg->setObject("native-window", new NativeWindowWrapper(surfaceTextureClient)); + + if (surfaceTexture == NULL) { + msg->setObject("native-window", NULL); + } else { + msg->setObject( + "native-window", + new NativeWindowWrapper( + new SurfaceTextureClient(surfaceTexture))); + } + msg->post(); } @@ -278,13 +302,24 @@ void NuPlayer::onMessageReceived(const sp &msg) { { ALOGV("kWhatSetVideoNativeWindow"); + mDeferredActions.push_back( + new SimpleAction(&NuPlayer::performDecoderShutdown)); + sp obj; CHECK(msg->findObject("native-window", &obj)); - mNativeWindow = static_cast(obj.get()); + mDeferredActions.push_back( + new SetSurfaceAction( + static_cast(obj.get()))); + + if (obj != NULL) { + // If there is a new surface texture, instantiate decoders + // again if possible. + mDeferredActions.push_back( + new SimpleAction(&NuPlayer::performScanSources)); + } - // XXX - ignore error from setVideoScalingMode for now - setVideoScalingMode(mVideoScalingMode); + processDeferredActions(); break; } @@ -311,6 +346,7 @@ void NuPlayer::onMessageReceived(const sp &msg) { mVideoLateByUs = 0; mNumFramesTotal = 0; mNumFramesDropped = 0; + mStarted = true; mSource->start(); @@ -986,8 +1022,7 @@ sp NuPlayer::Source::getFormat(bool audio) { status_t NuPlayer::setVideoScalingMode(int32_t mode) { mVideoScalingMode = mode; - if (mNativeWindow != NULL - && mNativeWindow->getNativeWindow() != NULL) { + if (mNativeWindow != NULL) { status_t ret = native_window_set_scaling_mode( mNativeWindow->getNativeWindow().get(), mVideoScalingMode); if (ret != OK) { @@ -1122,14 +1157,36 @@ void NuPlayer::performReset() { driver->notifyResetComplete(); } } + + mStarted = false; } void NuPlayer::performScanSources() { ALOGV("performScanSources"); + if (!mStarted) { + return; + } + if (mAudioDecoder == NULL || mVideoDecoder == NULL) { postScanSources(); } } +void NuPlayer::performSetSurface(const sp &wrapper) { + ALOGV("performSetSurface"); + + mNativeWindow = wrapper; + + // XXX - ignore error from setVideoScalingMode for now + setVideoScalingMode(mVideoScalingMode); + + if (mDriver != NULL) { + sp driver = mDriver.promote(); + if (driver != NULL) { + driver->notifySetSurfaceComplete(); + } + } +} + } // namespace android -- cgit v1.1 From 516dacfb02d0b0eafe21114330c98ce0e7d90da9 Mon Sep 17 00:00:00 2001 From: Andreas Huber Date: Mon, 3 Dec 2012 15:20:40 -0800 Subject: Respect sample aspect ratio in NuPlayer. related-to-bug: 7569402 Change-Id: I302de95d83b180bd2dc72ddd0c69a665dbce2527 --- media/libmediaplayerservice/nuplayer/NuPlayer.cpp | 41 +++++++++++++++++------ 1 file changed, 31 insertions(+), 10 deletions(-) (limited to 'media/libmediaplayerservice/nuplayer/NuPlayer.cpp') diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index f363568..746055c 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -448,7 +448,8 @@ void NuPlayer::onMessageReceived(const sp &msg) { } else if (what == ACodec::kWhatOutputFormatChanged) { if (audio) { int32_t numChannels; - CHECK(codecRequest->findInt32("channel-count", &numChannels)); + CHECK(codecRequest->findInt32( + "channel-count", &numChannels)); int32_t sampleRate; CHECK(codecRequest->findInt32("sample-rate", &sampleRate)); @@ -460,13 +461,15 @@ void NuPlayer::onMessageReceived(const sp &msg) { audio_output_flags_t flags; int64_t durationUs; - // FIXME: we should handle the case where the video decoder is created after - // we receive the format change indication. Current code will just make that - // we select deep buffer with video which should not be a problem as it should + // FIXME: we should handle the case where the video decoder + // is created after we receive the format change indication. + // Current code will just make that we select deep buffer + // with video which should not be a problem as it should // not prevent from keeping A/V sync. if (mVideoDecoder == NULL && mSource->getDuration(&durationUs) == OK && - durationUs > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US) { + durationUs + > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US) { flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER; } else { flags = AUDIO_OUTPUT_FLAG_NONE; @@ -502,17 +505,35 @@ void NuPlayer::onMessageReceived(const sp &msg) { "crop", &cropLeft, &cropTop, &cropRight, &cropBottom)); + int32_t displayWidth = cropRight - cropLeft + 1; + int32_t displayHeight = cropBottom - cropTop + 1; + ALOGV("Video output format changed to %d x %d " "(crop: %d x %d @ (%d, %d))", width, height, - (cropRight - cropLeft + 1), - (cropBottom - cropTop + 1), + displayWidth, + displayHeight, cropLeft, cropTop); + sp videoInputFormat = + mSource->getFormat(false /* audio */); + + // Take into account sample aspect ratio if necessary: + int32_t sarWidth, sarHeight; + if (videoInputFormat->findInt32("sar-width", &sarWidth) + && videoInputFormat->findInt32( + "sar-height", &sarHeight)) { + ALOGV("Sample aspect ratio %d : %d", + sarWidth, sarHeight); + + displayWidth = (displayWidth * sarWidth) / sarHeight; + + ALOGV("display dimensions %d x %d", + displayWidth, displayHeight); + } + notifyListener( - MEDIA_SET_VIDEO_SIZE, - cropRight - cropLeft + 1, - cropBottom - cropTop + 1); + MEDIA_SET_VIDEO_SIZE, displayWidth, displayHeight); } } else if (what == ACodec::kWhatShutdownCompleted) { ALOGV("%s shutdown completed", audio ? "audio" : "video"); -- cgit v1.1 From 8ba01021b573889802e67e029225a96f0dfa471a Mon Sep 17 00:00:00 2001 From: Andy McFadden Date: Tue, 18 Dec 2012 09:46:54 -0800 Subject: Rename ISurfaceTexture and SurfaceTexture The C++ class names don't match what the classes do, so rename ISurfaceTexture to IGraphicBufferProducer, and SurfaceTexture to GLConsumer. Bug 7736700 Change-Id: I64520a55f8c09fe6215382ea361c539a9940cba5 --- media/libmediaplayerservice/nuplayer/NuPlayer.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'media/libmediaplayerservice/nuplayer/NuPlayer.cpp') diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index 0f30372..517fb34 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -41,7 +41,7 @@ #include #include #include -#include +#include #include "avc_utils.h" @@ -198,16 +198,16 @@ void NuPlayer::setDataSource(int fd, int64_t offset, int64_t length) { } void NuPlayer::setVideoSurfaceTextureAsync( - const sp &surfaceTexture) { + const sp &bufferProducer) { sp msg = new AMessage(kWhatSetVideoNativeWindow, id()); - if (surfaceTexture == NULL) { + if (bufferProducer == NULL) { msg->setObject("native-window", NULL); } else { msg->setObject( "native-window", new NativeWindowWrapper( - new SurfaceTextureClient(surfaceTexture))); + new SurfaceTextureClient(bufferProducer))); } msg->post(); -- cgit v1.1 From b5f25f005bc1d3ae35f45b58c88345e183dc336d Mon Sep 17 00:00:00 2001 From: Andreas Huber Date: Tue, 5 Feb 2013 10:14:26 -0800 Subject: Groundwork to support bidirectional, asynchronous communication between NuPlayer and its sources. Change-Id: I1989022d806206b926555add3aa5c1fcf37aa78d --- media/libmediaplayerservice/nuplayer/NuPlayer.cpp | 35 +++++++++++++++++++---- 1 file changed, 29 insertions(+), 6 deletions(-) (limited to 'media/libmediaplayerservice/nuplayer/NuPlayer.cpp') diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index 517fb34..9585aba 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -145,12 +145,14 @@ void NuPlayer::setDriver(const wp &driver) { void NuPlayer::setDataSource(const sp &source) { sp msg = new AMessage(kWhatSetDataSource, id()); + sp notify = new AMessage(kWhatSourceNotify, id()); + char prop[PROPERTY_VALUE_MAX]; if (property_get("media.stagefright.use-mp4source", prop, NULL) && (!strcmp(prop, "1") || !strcasecmp(prop, "true"))) { - msg->setObject("source", new MP4Source(source)); + msg->setObject("source", new MP4Source(notify, source)); } else { - msg->setObject("source", new StreamingSource(source)); + msg->setObject("source", new StreamingSource(notify, source)); } msg->post(); @@ -176,13 +178,15 @@ void NuPlayer::setDataSource( const char *url, const KeyedVector *headers) { sp msg = new AMessage(kWhatSetDataSource, id()); + sp notify = new AMessage(kWhatSourceNotify, id()); + sp source; if (IsHTTPLiveURL(url)) { - source = new HTTPLiveSource(url, headers, mUIDValid, mUID); + source = new HTTPLiveSource(notify, url, headers, mUIDValid, mUID); } else if (!strncasecmp(url, "rtsp://", 7)) { - source = new RTSPSource(url, headers, mUIDValid, mUID); + source = new RTSPSource(notify, url, headers, mUIDValid, mUID); } else { - source = new GenericSource(url, headers, mUIDValid, mUID); + source = new GenericSource(notify, url, headers, mUIDValid, mUID); } msg->setObject("source", source); @@ -192,7 +196,9 @@ void NuPlayer::setDataSource( void NuPlayer::setDataSource(int fd, int64_t offset, int64_t length) { sp msg = new AMessage(kWhatSetDataSource, id()); - sp source = new GenericSource(fd, offset, length); + sp notify = new AMessage(kWhatSourceNotify, id()); + + sp source = new GenericSource(notify, fd, offset, length); msg->setObject("source", source); msg->post(); } @@ -273,6 +279,8 @@ void NuPlayer::onMessageReceived(const sp &msg) { CHECK(msg->findObject("source", &obj)); mSource = static_cast(obj.get()); + + looper()->registerHandler(mSource); break; } @@ -714,6 +722,12 @@ void NuPlayer::onMessageReceived(const sp &msg) { break; } + case kWhatSourceNotify: + { + TRESPASS(); // TBD + break; + } + default: TRESPASS(); break; @@ -1169,6 +1183,9 @@ void NuPlayer::performReset() { if (mSource != NULL) { mSource->stop(); + + looper()->unregisterHandler(mSource->id()); + mSource.clear(); } @@ -1210,4 +1227,10 @@ void NuPlayer::performSetSurface(const sp &wrapper) { } } +//////////////////////////////////////////////////////////////////////////////// + +void NuPlayer::Source::onMessageReceived(const sp &msg) { + TRESPASS(); +} + } // namespace android -- cgit v1.1 From 7a33b7740412accf6a1cc912686c8d0acfb2a883 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Rydh=C3=A9?= Date: Mon, 20 Feb 2012 10:15:48 +0100 Subject: Added HTTP support for SDP files. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added support for playing SDP files from http links. Previously, SDP files only worked when started from rtsp links (rtsp://a.b.c/abc.sdp), but they are just as common in http links. patch provided by "Oscar Rydhé " Change-Id: Ic73af3a9a002009dbe8b04c267a4621bf7fe2f46 --- media/libmediaplayerservice/nuplayer/NuPlayer.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'media/libmediaplayerservice/nuplayer/NuPlayer.cpp') diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index 9585aba..0736fbe 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -177,6 +177,7 @@ static bool IsHTTPLiveURL(const char *url) { void NuPlayer::setDataSource( const char *url, const KeyedVector *headers) { sp msg = new AMessage(kWhatSetDataSource, id()); + size_t len = strlen(url); sp notify = new AMessage(kWhatSourceNotify, id()); @@ -185,6 +186,11 @@ void NuPlayer::setDataSource( source = new HTTPLiveSource(notify, url, headers, mUIDValid, mUID); } else if (!strncasecmp(url, "rtsp://", 7)) { source = new RTSPSource(notify, url, headers, mUIDValid, mUID); + } else if ((!strncasecmp(url, "http://", 7) + || !strncasecmp(url, "https://", 8)) + && ((len >= 4 && !strcasecmp(".sdp", &url[len - 4])) + || strstr(url, ".sdp?"))) { + source = new RTSPSource(notify, url, headers, mUIDValid, mUID, true); } else { source = new GenericSource(notify, url, headers, mUIDValid, mUID); } -- cgit v1.1 From 9575c96b6e418914e2ffc6741ecc8d71e3968dbe Mon Sep 17 00:00:00 2001 From: Andreas Huber Date: Tue, 5 Feb 2013 13:59:56 -0800 Subject: Support for a "preparation" state that can take care of lengthy operations in NuPlayer and its sources. Sources also can publish their flags now and the mediaplayer UI will be able to pick up on these. Change-Id: I4f2b7e5d105dcb4b6c9132cd0e8799efa0c6a14b --- media/libmediaplayerservice/nuplayer/NuPlayer.cpp | 97 +++++++++++++++++++++-- 1 file changed, 90 insertions(+), 7 deletions(-) (limited to 'media/libmediaplayerservice/nuplayer/NuPlayer.cpp') diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index 0736fbe..78b94ba 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -112,6 +112,7 @@ private: NuPlayer::NuPlayer() : mUIDValid(false), + mSourceFlags(0), mVideoIsAVC(false), mAudioEOS(false), mVideoEOS(false), @@ -142,7 +143,7 @@ void NuPlayer::setDriver(const wp &driver) { mDriver = driver; } -void NuPlayer::setDataSource(const sp &source) { +void NuPlayer::setDataSourceAsync(const sp &source) { sp msg = new AMessage(kWhatSetDataSource, id()); sp notify = new AMessage(kWhatSourceNotify, id()); @@ -174,7 +175,7 @@ static bool IsHTTPLiveURL(const char *url) { return false; } -void NuPlayer::setDataSource( +void NuPlayer::setDataSourceAsync( const char *url, const KeyedVector *headers) { sp msg = new AMessage(kWhatSetDataSource, id()); size_t len = strlen(url); @@ -199,7 +200,7 @@ void NuPlayer::setDataSource( msg->post(); } -void NuPlayer::setDataSource(int fd, int64_t offset, int64_t length) { +void NuPlayer::setDataSourceAsync(int fd, int64_t offset, int64_t length) { sp msg = new AMessage(kWhatSetDataSource, id()); sp notify = new AMessage(kWhatSourceNotify, id()); @@ -209,6 +210,10 @@ void NuPlayer::setDataSource(int fd, int64_t offset, int64_t length) { msg->post(); } +void NuPlayer::prepareAsync() { + (new AMessage(kWhatPrepare, id()))->post(); +} + void NuPlayer::setVideoSurfaceTextureAsync( const sp &bufferProducer) { sp msg = new AMessage(kWhatSetVideoNativeWindow, id()); @@ -287,6 +292,18 @@ void NuPlayer::onMessageReceived(const sp &msg) { mSource = static_cast(obj.get()); looper()->registerHandler(mSource); + + CHECK(mDriver != NULL); + sp driver = mDriver.promote(); + if (driver != NULL) { + driver->notifySetDataSourceCompleted(OK); + } + break; + } + + case kWhatPrepare: + { + mSource->prepareAsync(); break; } @@ -403,9 +420,7 @@ void NuPlayer::onMessageReceived(const sp &msg) { && (mAudioDecoder != NULL || mVideoDecoder != NULL)) { // This is the first time we've found anything playable. - uint32_t flags = mSource->flags(); - - if (flags & Source::FLAG_DYNAMIC_DURATION) { + if (mSourceFlags & Source::FLAG_DYNAMIC_DURATION) { schedulePollDuration(); } } @@ -730,7 +745,7 @@ void NuPlayer::onMessageReceived(const sp &msg) { case kWhatSourceNotify: { - TRESPASS(); // TBD + onSourceNotify(msg); break; } @@ -1233,8 +1248,76 @@ void NuPlayer::performSetSurface(const sp &wrapper) { } } +void NuPlayer::onSourceNotify(const sp &msg) { + int32_t what; + CHECK(msg->findInt32("what", &what)); + + switch (what) { + case Source::kWhatPrepared: + { + sp driver = mDriver.promote(); + if (driver != NULL) { + driver->notifyPrepareCompleted(OK); + } + break; + } + + case Source::kWhatFlagsChanged: + { + uint32_t flags; + CHECK(msg->findInt32("flags", (int32_t *)&flags)); + + if ((mSourceFlags & Source::FLAG_DYNAMIC_DURATION) + && (!(flags & Source::FLAG_DYNAMIC_DURATION))) { + cancelPollDuration(); + } else if (!(mSourceFlags & Source::FLAG_DYNAMIC_DURATION) + && (flags & Source::FLAG_DYNAMIC_DURATION) + && (mAudioDecoder != NULL || mVideoDecoder != NULL)) { + schedulePollDuration(); + } + + mSourceFlags = flags; + break; + } + + case Source::kWhatVideoSizeChanged: + { + int32_t width, height; + CHECK(msg->findInt32("width", &width)); + CHECK(msg->findInt32("height", &height)); + + notifyListener(MEDIA_SET_VIDEO_SIZE, width, height); + break; + } + + default: + TRESPASS(); + } +} + //////////////////////////////////////////////////////////////////////////////// +void NuPlayer::Source::notifyFlagsChanged(uint32_t flags) { + sp notify = dupNotify(); + notify->setInt32("what", kWhatFlagsChanged); + notify->setInt32("flags", flags); + notify->post(); +} + +void NuPlayer::Source::notifyVideoSizeChanged(int32_t width, int32_t height) { + sp notify = dupNotify(); + notify->setInt32("what", kWhatVideoSizeChanged); + notify->setInt32("width", width); + notify->setInt32("height", height); + notify->post(); +} + +void NuPlayer::Source::notifyPrepared() { + sp notify = dupNotify(); + notify->setInt32("what", kWhatPrepared); + notify->post(); +} + void NuPlayer::Source::onMessageReceived(const sp &msg) { TRESPASS(); } -- cgit v1.1 From ec0c597cabf169ca646bcea5faac1bd81ed4484d Mon Sep 17 00:00:00 2001 From: Andreas Huber Date: Tue, 5 Feb 2013 14:47:13 -0800 Subject: RTSP now properly publishes its "seekable" flags after connection has successfully completed and only then signals that preparation is complete. Change-Id: I1a60f718e673fe1462c69369c40eafbed6a14326 --- media/libmediaplayerservice/nuplayer/NuPlayer.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'media/libmediaplayerservice/nuplayer/NuPlayer.cpp') diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index 78b94ba..bcefe63 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -1255,9 +1255,12 @@ void NuPlayer::onSourceNotify(const sp &msg) { switch (what) { case Source::kWhatPrepared: { + int32_t err; + CHECK(msg->findInt32("err", &err)); + sp driver = mDriver.promote(); if (driver != NULL) { - driver->notifyPrepareCompleted(OK); + driver->notifyPrepareCompleted(err); } break; } @@ -1312,9 +1315,10 @@ void NuPlayer::Source::notifyVideoSizeChanged(int32_t width, int32_t height) { notify->post(); } -void NuPlayer::Source::notifyPrepared() { +void NuPlayer::Source::notifyPrepared(status_t err) { sp notify = dupNotify(); notify->setInt32("what", kWhatPrepared); + notify->setInt32("err", err); notify->post(); } -- cgit v1.1 From b50e83eca302a12f0fced6e7bab1b8617d63deaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roger=20J=C3=B6nsson?= Date: Mon, 21 Jan 2013 16:26:41 +0100 Subject: RTSP buffering improvements Added buffering start and end notifications for RTSP. MEDIA_INFO_BUFFERING_START is sent when buffering is started and MEDIA_INFO_BUFFERING_END is sent when the buffer has filled up. This patch also adds RTSP end of stream handling. EOS is signalled when BYE is received OR when detecting end of stream even if no actual EOS is received. Change-Id: I5cccb6845060ae6afd66d9f735b89da81476cd13 --- media/libmediaplayerservice/nuplayer/NuPlayer.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'media/libmediaplayerservice/nuplayer/NuPlayer.cpp') diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index bcefe63..ee25cc6 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -1293,6 +1293,18 @@ void NuPlayer::onSourceNotify(const sp &msg) { break; } + case Source::kWhatBufferingStart: + { + notifyListener(MEDIA_INFO, MEDIA_INFO_BUFFERING_START, 0); + break; + } + + case Source::kWhatBufferingEnd: + { + notifyListener(MEDIA_INFO, MEDIA_INFO_BUFFERING_END, 0); + break; + } + default: TRESPASS(); } -- cgit v1.1 From fba60daf77cc74a13ae3bf4b0e9925dd2ee4470c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roger=20J=C3=B6nsson?= Date: Mon, 21 Jan 2013 17:15:45 +0100 Subject: Enable pause/resume for RTSP streaming When a stream is paused, RTSP Pause is also sent to the server. Otherwise the buffering might continue until the memory runs out. When the stream is resumed, RTSP Play will be sent in order to resume the buffering. Change-Id: I5dc1761140827c532451638c3fd3f34271e5b9ab --- media/libmediaplayerservice/nuplayer/NuPlayer.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'media/libmediaplayerservice/nuplayer/NuPlayer.cpp') diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index ee25cc6..30eb4b9 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -732,6 +732,7 @@ void NuPlayer::onMessageReceived(const sp &msg) { case kWhatPause: { CHECK(mRenderer != NULL); + mSource->pause(); mRenderer->pause(); break; } @@ -739,6 +740,7 @@ void NuPlayer::onMessageReceived(const sp &msg) { case kWhatResume: { CHECK(mRenderer != NULL); + mSource->resume(); mRenderer->resume(); break; } -- cgit v1.1 From 1a2952aee048ca7b1765e2bc09ebe9aeddaeafa3 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Thu, 14 Feb 2013 17:11:27 -0800 Subject: Refactoring: Rename SurfaceTextureClient to Surface Change-Id: I4e8a8b20914cb64edc37abe68233fbc9f2b5d830 --- media/libmediaplayerservice/nuplayer/NuPlayer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'media/libmediaplayerservice/nuplayer/NuPlayer.cpp') diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index 30eb4b9..2ba6c22 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -224,7 +224,7 @@ void NuPlayer::setVideoSurfaceTextureAsync( msg->setObject( "native-window", new NativeWindowWrapper( - new SurfaceTextureClient(bufferProducer))); + new Surface(bufferProducer))); } msg->post(); -- cgit v1.1 From d5e56231a598b180a1d898bb7dc61b75580e59a4 Mon Sep 17 00:00:00 2001 From: Andreas Huber Date: Tue, 12 Mar 2013 11:01:43 -0700 Subject: Squashed commit of the following: commit f4edf442741886cdbe071e2d15f6e6247269f7c5 Author: Andreas Huber Date: Tue Mar 12 09:09:18 2013 -0700 Pass additional flags to the sink, use TCP by default in wolfiecast mode. Change-Id: I41e11a2375d4199656e45c4f149d8441d0016092 commit 6302602ed280a38287f507159abfb40a1da38c5a Author: Andreas Huber Date: Tue Mar 12 08:51:58 2013 -0700 tweaks Change-Id: Ie29e422d7258be522f4bb1f6c5afcf74c937e547 commit a38a860e4979ba563cadbaafa21b084439449d26 Author: Andreas Huber Date: Mon Mar 11 16:57:43 2013 -0700 Report average lateness all the way from NuPlayerRenderer... Change-Id: I2e7700703ae656515e44b9c25610d26c75778111 commit a7d49b11675ea88be4029dd8451d1649db94571d Author: Andreas Huber Date: Mon Mar 11 14:54:19 2013 -0700 Make TimeSyncer smarter, enable TunnelRenderer Change-Id: I27377a60cd8feb01589da456967fddd34532c20e commit 0f214c8ef68179f7b61512c37040939554013151 Author: Andreas Huber Date: Thu Mar 7 15:57:56 2013 -0800 convert source timestamps to sink timestamps, report lateness. Change-Id: I051a60fbbceca2f7b508ae3dac6e01e402bae39e commit 04a4f8e16bad09157b5615a5fa45310438955832 Author: Andreas Huber Date: Thu Mar 7 09:00:28 2013 -0800 Sync time between sink and source. Change-Id: Ie8b4d75c957aa48310e7c81d1279761b9f821efe commit aebe20e6184e3636a99082f8ece08e708015cb8d Author: Andreas Huber Date: Wed Mar 6 09:03:12 2013 -0800 play with back pressure Change-Id: I51eb69257e6a79e76f5f9c75ff99d8adbd083947 Change-Id: Ifdf57228667fed7fc71c5090a2c3f7cea1037c5c --- media/libmediaplayerservice/nuplayer/NuPlayer.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'media/libmediaplayerservice/nuplayer/NuPlayer.cpp') diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index 2ba6c22..5387e1a 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -381,9 +381,16 @@ void NuPlayer::onMessageReceived(const sp &msg) { mSource->start(); + uint32_t flags = 0; + + if (mSource->isRealTime()) { + flags |= Renderer::FLAG_REAL_TIME; + } + mRenderer = new Renderer( mAudioSink, - new AMessage(kWhatRendererNotify, id())); + new AMessage(kWhatRendererNotify, id()), + flags); looper()->registerHandler(mRenderer); -- cgit v1.1 From 997594088164cfb33c1cb8c376884346fbf1e7ae Mon Sep 17 00:00:00 2001 From: Andreas Huber Date: Mon, 1 Apr 2013 14:28:31 -0700 Subject: Fix seek in response to OnPrepared() for HLS content Change-Id: I0e52352845398a4db074e939487f6f6de94bd523 related-to-bug: 8225122 --- media/libmediaplayerservice/nuplayer/NuPlayer.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'media/libmediaplayerservice/nuplayer/NuPlayer.cpp') diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index 5387e1a..46d0a5a 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -161,7 +161,8 @@ void NuPlayer::setDataSourceAsync(const sp &source) { static bool IsHTTPLiveURL(const char *url) { if (!strncasecmp("http://", url, 7) - || !strncasecmp("https://", url, 8)) { + || !strncasecmp("https://", url, 8) + || !strncasecmp("file://", url, 7)) { size_t len = strlen(url); if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) { return true; @@ -833,14 +834,6 @@ status_t NuPlayer::instantiateDecoder(bool audio, sp *decoder) { (*decoder)->configure(format); - int64_t durationUs; - if (mDriver != NULL && mSource->getDuration(&durationUs) == OK) { - sp driver = mDriver.promote(); - if (driver != NULL) { - driver->notifyDuration(durationUs); - } - } - return OK; } @@ -1271,6 +1264,14 @@ void NuPlayer::onSourceNotify(const sp &msg) { if (driver != NULL) { driver->notifyPrepareCompleted(err); } + + int64_t durationUs; + if (mDriver != NULL && mSource->getDuration(&durationUs) == OK) { + sp driver = mDriver.promote(); + if (driver != NULL) { + driver->notifyDuration(durationUs); + } + } break; } -- cgit v1.1 From da9740e63a835e610519bd235be9137d74b6d409 Mon Sep 17 00:00:00 2001 From: Andreas Huber Date: Tue, 16 Apr 2013 10:54:03 -0700 Subject: Fix a typo that would cause us not to shutdown/flush the decoders in some cases. related-to-bug: 8630032 Change-Id: I8e94b53b34e137e827e9630c65f3252ea91e4ebd --- media/libmediaplayerservice/nuplayer/NuPlayer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'media/libmediaplayerservice/nuplayer/NuPlayer.cpp') diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index 46d0a5a..607ec6a 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -1158,7 +1158,7 @@ void NuPlayer::performSeek(int64_t seekTimeUs) { void NuPlayer::performDecoderFlush() { ALOGV("performDecoderFlush"); - if (mAudioDecoder != NULL && mVideoDecoder == NULL) { + if (mAudioDecoder == NULL && mVideoDecoder == NULL) { return; } @@ -1176,7 +1176,7 @@ void NuPlayer::performDecoderFlush() { void NuPlayer::performDecoderShutdown() { ALOGV("performDecoderShutdown"); - if (mAudioDecoder != NULL && mVideoDecoder == NULL) { + if (mAudioDecoder == NULL && mVideoDecoder == NULL) { return; } -- cgit v1.1 From b5f28d4749b898d92fe5e56236b417e37b6fe84f Mon Sep 17 00:00:00 2001 From: Andreas Huber Date: Thu, 25 Apr 2013 15:11:19 -0700 Subject: Handle the case where an asynchronous prepare was initiated and then the mediaplayer was reset. Change-Id: Ib241747c5dc002b88a3854569c1f8340b2a8ef41 related-to-bug: 8688986 --- media/libmediaplayerservice/nuplayer/NuPlayer.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'media/libmediaplayerservice/nuplayer/NuPlayer.cpp') diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index 607ec6a..b89b1c8 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -1257,6 +1257,13 @@ void NuPlayer::onSourceNotify(const sp &msg) { switch (what) { case Source::kWhatPrepared: { + if (mSource == NULL) { + // This is a stale notification from a source that was + // asynchronously preparing when the client called reset(). + // We handled the reset, the source is gone. + break; + } + int32_t err; CHECK(msg->findInt32("err", &err)); -- cgit v1.1 From 14f7672b5d450ed26a06fd3bb3ce045ea78b11b2 Mon Sep 17 00:00:00 2001 From: Andreas Huber Date: Tue, 15 Jan 2013 09:04:18 -0800 Subject: New HLS implementation supporting independent stream sources, audio-only streams and more. Change-Id: Icfc45a0100243b2f7a14a9e65696be45b67d6495 --- media/libmediaplayerservice/nuplayer/NuPlayer.cpp | 88 +++++++++++++++++++++-- 1 file changed, 81 insertions(+), 7 deletions(-) (limited to 'media/libmediaplayerservice/nuplayer/NuPlayer.cpp') diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index b89b1c8..7e81035 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -89,6 +89,38 @@ private: DISALLOW_EVIL_CONSTRUCTORS(SetSurfaceAction); }; +struct NuPlayer::ShutdownDecoderAction : public Action { + ShutdownDecoderAction(bool audio, bool video) + : mAudio(audio), + mVideo(video) { + } + + virtual void execute(NuPlayer *player) { + player->performDecoderShutdown(mAudio, mVideo); + } + +private: + bool mAudio; + bool mVideo; + + DISALLOW_EVIL_CONSTRUCTORS(ShutdownDecoderAction); +}; + +struct NuPlayer::PostMessageAction : public Action { + PostMessageAction(const sp &msg) + : mMessage(msg) { + } + + virtual void execute(NuPlayer *) { + mMessage->post(); + } + +private: + sp mMessage; + + DISALLOW_EVIL_CONSTRUCTORS(PostMessageAction); +}; + // Use this if there's no state necessary to save in order to execute // the action. struct NuPlayer::SimpleAction : public Action { @@ -335,7 +367,8 @@ void NuPlayer::onMessageReceived(const sp &msg) { ALOGV("kWhatSetVideoNativeWindow"); mDeferredActions.push_back( - new SimpleAction(&NuPlayer::performDecoderShutdown)); + new ShutdownDecoderAction( + false /* audio */, true /* video */)); sp obj; CHECK(msg->findObject("native-window", &obj)); @@ -712,7 +745,8 @@ void NuPlayer::onMessageReceived(const sp &msg) { ALOGV("kWhatReset"); mDeferredActions.push_back( - new SimpleAction(&NuPlayer::performDecoderShutdown)); + new ShutdownDecoderAction( + true /* audio */, true /* video */)); mDeferredActions.push_back( new SimpleAction(&NuPlayer::performReset)); @@ -1023,6 +1057,9 @@ void NuPlayer::notifyListener(int msg, int ext1, int ext2) { } void NuPlayer::flushDecoder(bool audio, bool needShutdown) { + ALOGV("[%s] flushDecoder needShutdown=%d", + audio ? "audio" : "video", needShutdown); + if ((audio && mAudioDecoder == NULL) || (!audio && mVideoDecoder == NULL)) { ALOGI("flushDecoder %s without decoder present", audio ? "audio" : "video"); @@ -1173,20 +1210,29 @@ void NuPlayer::performDecoderFlush() { } } -void NuPlayer::performDecoderShutdown() { - ALOGV("performDecoderShutdown"); +void NuPlayer::performDecoderShutdown(bool audio, bool video) { + ALOGV("performDecoderShutdown audio=%d, video=%d", audio, video); - if (mAudioDecoder == NULL && mVideoDecoder == NULL) { + if ((!audio || mAudioDecoder == NULL) + && (!video || mVideoDecoder == NULL)) { return; } mTimeDiscontinuityPending = true; - if (mAudioDecoder != NULL) { + if (mFlushingAudio == NONE && (!audio || mAudioDecoder == NULL)) { + mFlushingAudio = FLUSHED; + } + + if (mFlushingVideo == NONE && (!video || mVideoDecoder == NULL)) { + mFlushingVideo = FLUSHED; + } + + if (audio && mAudioDecoder != NULL) { flushDecoder(true /* audio */, true /* needShutdown */); } - if (mVideoDecoder != NULL) { + if (video && mVideoDecoder != NULL) { flushDecoder(false /* audio */, true /* needShutdown */); } } @@ -1322,6 +1368,19 @@ void NuPlayer::onSourceNotify(const sp &msg) { break; } + case Source::kWhatQueueDecoderShutdown: + { + int32_t audio, video; + CHECK(msg->findInt32("audio", &audio)); + CHECK(msg->findInt32("video", &video)); + + sp reply; + CHECK(msg->findMessage("reply", &reply)); + + queueDecoderShutdown(audio, video, reply); + break; + } + default: TRESPASS(); } @@ -1355,4 +1414,19 @@ void NuPlayer::Source::onMessageReceived(const sp &msg) { TRESPASS(); } +void NuPlayer::queueDecoderShutdown( + bool audio, bool video, const sp &reply) { + ALOGI("queueDecoderShutdown audio=%d, video=%d", audio, video); + + mDeferredActions.push_back( + new ShutdownDecoderAction(audio, video)); + + mDeferredActions.push_back( + new SimpleAction(&NuPlayer::performScanSources)); + + mDeferredActions.push_back(new PostMessageAction(reply)); + + processDeferredActions(); +} + } // namespace android -- cgit v1.1 From cbaffcffee6418d678806e63097c19fe26d48fe0 Mon Sep 17 00:00:00 2001 From: Lajos Molnar Date: Wed, 14 Aug 2013 18:30:38 -0700 Subject: Add MEDIA_STARTED/PAUSED/STOPPED events to media players This is needed for the MediaTimeProvider java interface, so it does not continually poll for current media time. Note: NuPlayer and AwesomePlayer do not correctly handle stop (pause instead), so for those we will signal PAUSED. Signed-off-by: Lajos Molnar Change-Id: I3c61e1bda475f131323f475c18a42e3ec66c9ae1 Bug: 10326117 --- media/libmediaplayerservice/nuplayer/NuPlayer.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'media/libmediaplayerservice/nuplayer/NuPlayer.cpp') diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index 7e81035..b411f34 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -731,6 +731,9 @@ void NuPlayer::onMessageReceived(const sp &msg) { ALOGV("renderer %s flush completed.", audio ? "audio" : "video"); } else if (what == Renderer::kWhatVideoRenderingStart) { notifyListener(MEDIA_INFO, MEDIA_INFO_RENDERING_START, 0); + } else if (what == Renderer::kWhatMediaRenderingStart) { + ALOGV("media rendering started"); + notifyListener(MEDIA_STARTED, 0, 0); } break; } -- cgit v1.1 From dcb89b3b505522efde173c105a851c412f947178 Mon Sep 17 00:00:00 2001 From: Chong Zhang Date: Tue, 6 Aug 2013 09:44:47 -0700 Subject: MediaPlayer: add listener for raw track data Bug: 10326117 Change-Id: I2c0bdf8adc67b11f8dc633423bee66897548f181 --- media/libmediaplayerservice/nuplayer/NuPlayer.cpp | 87 ++++++++++++++++++++++- 1 file changed, 85 insertions(+), 2 deletions(-) (limited to 'media/libmediaplayerservice/nuplayer/NuPlayer.cpp') diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index b411f34..e1735fa 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -340,6 +340,46 @@ void NuPlayer::onMessageReceived(const sp &msg) { break; } + case kWhatGetTrackInfo: + { + uint32_t replyID; + CHECK(msg->senderAwaitsResponse(&replyID)); + + status_t err = INVALID_OPERATION; + if (mSource != NULL) { + Parcel* reply; + CHECK(msg->findPointer("reply", (void**)&reply)); + err = mSource->getTrackInfo(reply); + } + + sp response = new AMessage; + response->setInt32("err", err); + + response->postReply(replyID); + break; + } + + case kWhatSelectTrack: + { + uint32_t replyID; + CHECK(msg->senderAwaitsResponse(&replyID)); + + status_t err = INVALID_OPERATION; + if (mSource != NULL) { + size_t trackIndex; + int32_t select; + CHECK(msg->findSize("trackIndex", &trackIndex)); + CHECK(msg->findInt32("select", &select)); + err = mSource->selectTrack(trackIndex, select); + } + + sp response = new AMessage; + response->setInt32("err", err); + + response->postReply(replyID); + break; + } + case kWhatPollDuration: { int32_t generation; @@ -1045,7 +1085,7 @@ void NuPlayer::renderBuffer(bool audio, const sp &msg) { mRenderer->queueBuffer(audio, buffer, reply); } -void NuPlayer::notifyListener(int msg, int ext1, int ext2) { +void NuPlayer::notifyListener(int msg, int ext1, int ext2, const Parcel *in) { if (mDriver == NULL) { return; } @@ -1056,7 +1096,7 @@ void NuPlayer::notifyListener(int msg, int ext1, int ext2) { return; } - driver->notifyListener(msg, ext1, ext2); + driver->notifyListener(msg, ext1, ext2, in); } void NuPlayer::flushDecoder(bool audio, bool needShutdown) { @@ -1132,6 +1172,26 @@ status_t NuPlayer::setVideoScalingMode(int32_t mode) { return OK; } +status_t NuPlayer::getTrackInfo(Parcel* reply) const { + sp msg = new AMessage(kWhatGetTrackInfo, id()); + msg->setPointer("reply", reply); + + sp response; + status_t err = msg->postAndAwaitResponse(&response); + return err; +} + +status_t NuPlayer::selectTrack(size_t trackIndex, bool select) { + sp msg = new AMessage(kWhatSelectTrack, id()); + msg->setSize("trackIndex", trackIndex); + msg->setInt32("select", select); + + sp response; + status_t err = msg->postAndAwaitResponse(&response); + + return err; +} + void NuPlayer::schedulePollDuration() { sp msg = new AMessage(kWhatPollDuration, id()); msg->setInt32("generation", mPollDurationGeneration); @@ -1371,6 +1431,29 @@ void NuPlayer::onSourceNotify(const sp &msg) { break; } + case Source::kWhatSubtitleData: + { + sp buffer; + CHECK(msg->findBuffer("buffer", &buffer)); + + int32_t trackIndex; + int64_t timeUs, durationUs; + CHECK(buffer->meta()->findInt32("trackIndex", &trackIndex)); + CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); + CHECK(buffer->meta()->findInt64("durationUs", &durationUs)); + + Parcel in; + in.writeInt32(trackIndex); + in.writeInt64(timeUs); + in.writeInt64(durationUs); + in.writeInt32(buffer->size()); + in.writeInt32(buffer->size()); + in.write(buffer->data(), buffer->size()); + + notifyListener(MEDIA_SUBTITLE_DATA, 0, 0, &in); + break; + } + case Source::kWhatQueueDecoderShutdown: { int32_t audio, video; -- cgit v1.1 From 4b7069dac546ad21cf62ca6132d50ea41857d08e Mon Sep 17 00:00:00 2001 From: Chong Zhang Date: Wed, 11 Sep 2013 12:52:43 -0700 Subject: Add FLAG_CAN_SEEK_BACKWARD and FLAG_CAN_SEEK_FORWARD see flags Also update seek flag in NuPlayerDriver, otherwise MediaPlayer will get wrong flags. Bug: 10676387 Change-Id: Ice30f27a9a04e37b4718d26228a407fea8d9e4fc --- media/libmediaplayerservice/nuplayer/NuPlayer.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'media/libmediaplayerservice/nuplayer/NuPlayer.cpp') diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index e1735fa..750287f 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -1396,6 +1396,11 @@ void NuPlayer::onSourceNotify(const sp &msg) { uint32_t flags; CHECK(msg->findInt32("flags", (int32_t *)&flags)); + sp driver = mDriver.promote(); + if (driver != NULL) { + driver->notifyFlagsChanged(flags); + } + if ((mSourceFlags & Source::FLAG_DYNAMIC_DURATION) && (!(flags & Source::FLAG_DYNAMIC_DURATION))) { cancelPollDuration(); -- cgit v1.1