From 6472badc497a9e748411f8c8c9ed5d83ef335a85 Mon Sep 17 00:00:00 2001 From: Insun Kang Date: Mon, 18 Jun 2012 16:51:48 +0900 Subject: Fix: status checking in TimedTextDriver. o fixes seeking error when there's no enabled text track. o clean up status checking code for deselectTrack. o fixes a potential bug : pause->backward seek can trigger unwanted resume. Bug: 6682160 Change-Id: I03d8788b27fb9c0a6092be83ad3578ccf3266905 (cherry picked from commit 2dafb6071d4f14e0e208912500694912211aa26b) --- media/libstagefright/timedtext/TimedTextDriver.cpp | 36 ++++++++--- media/libstagefright/timedtext/TimedTextPlayer.cpp | 75 +++++++++++++++------- media/libstagefright/timedtext/TimedTextPlayer.h | 5 +- 3 files changed, 84 insertions(+), 32 deletions(-) (limited to 'media/libstagefright') diff --git a/media/libstagefright/timedtext/TimedTextDriver.cpp b/media/libstagefright/timedtext/TimedTextDriver.cpp index 1a0dc7b..71da803 100644 --- a/media/libstagefright/timedtext/TimedTextDriver.cpp +++ b/media/libstagefright/timedtext/TimedTextDriver.cpp @@ -145,21 +145,41 @@ status_t TimedTextDriver::selectTrack(size_t index) { } status_t TimedTextDriver::unselectTrack(size_t index) { + Mutex::Autolock autoLock(mLock); if (mCurrentTrackIndex != index) { return INVALID_OPERATION; } - status_t err = pause(); - if (err != OK) { - return err; + switch (mState) { + case UNINITIALIZED: + return INVALID_OPERATION; + case PLAYING: + mPlayer->pause(); + mState = UNINITIALIZED; + return OK; + case PAUSED: + mState = UNINITIALIZED; + return OK; + default: + TRESPASS(); } - Mutex::Autolock autoLock(mLock); - mState = UNINITIALIZED; - return OK; + return UNKNOWN_ERROR; } status_t TimedTextDriver::seekToAsync(int64_t timeUs) { - mPlayer->seekToAsync(timeUs); - return OK; + Mutex::Autolock autoLock(mLock); + switch (mState) { + case UNINITIALIZED: + return INVALID_OPERATION; + case PAUSED: + mPlayer->seekToAsync(timeUs); + return OK; + case PLAYING: + mPlayer->seekToAsync(timeUs); + return OK; + defaut: + TRESPASS(); + } + return UNKNOWN_ERROR; } status_t TimedTextDriver::addInBandTextSource( diff --git a/media/libstagefright/timedtext/TimedTextPlayer.cpp b/media/libstagefright/timedtext/TimedTextPlayer.cpp index b9cac78..df7eb39 100644 --- a/media/libstagefright/timedtext/TimedTextPlayer.cpp +++ b/media/libstagefright/timedtext/TimedTextPlayer.cpp @@ -41,6 +41,8 @@ static const int64_t kInvalidTimeUs = INT_MIN; TimedTextPlayer::TimedTextPlayer(const wp &listener) : mListener(listener), mSource(NULL), + mPendingSeekTimeUs(kInvalidTimeUs), + mPaused(false), mSendSubtitleGeneration(0) { } @@ -53,9 +55,7 @@ TimedTextPlayer::~TimedTextPlayer() { } void TimedTextPlayer::start() { - sp msg = new AMessage(kWhatSeek, id()); - msg->setInt64("seekTimeUs", kInvalidTimeUs); - msg->post(); + (new AMessage(kWhatStart, id()))->post(); } void TimedTextPlayer::pause() { @@ -81,11 +81,34 @@ void TimedTextPlayer::setDataSource(sp source) { void TimedTextPlayer::onMessageReceived(const sp &msg) { switch (msg->what()) { case kWhatPause: { - mSendSubtitleGeneration++; + mPaused = true; break; } case kWhatResume: { - doRead(); + mPaused = false; + if (mPendingSeekTimeUs != kInvalidTimeUs) { + seekToAsync(mPendingSeekTimeUs); + mPendingSeekTimeUs = kInvalidTimeUs; + } else { + doRead(); + } + break; + } + case kWhatStart: { + sp listener = mListener.promote(); + if (listener == NULL) { + ALOGE("Listener is NULL when kWhatStart is received."); + break; + } + mPaused = false; + mPendingSeekTimeUs = kInvalidTimeUs; + int32_t positionMs = 0; + listener->getCurrentPosition(&positionMs); + int64_t seekTimeUs = positionMs * 1000ll; + + notifyListener(); + mSendSubtitleGeneration++; + doSeekAndRead(seekTimeUs); break; } case kWhatRetryRead: { @@ -110,7 +133,6 @@ void TimedTextPlayer::onMessageReceived(const sp &msg) { break; } case kWhatSeek: { - mSendSubtitleGeneration++; int64_t seekTimeUs = kInvalidTimeUs; // Clear a displayed timed text before seeking. notifyListener(); @@ -123,6 +145,11 @@ void TimedTextPlayer::onMessageReceived(const sp &msg) { seekTimeUs = positionMs * 1000ll; } } + if (mPaused) { + mPendingSeekTimeUs = seekTimeUs; + break; + } + mSendSubtitleGeneration++; doSeekAndRead(seekTimeUs); break; } @@ -221,22 +248,20 @@ void TimedTextPlayer::doRead(MediaSource::ReadOptions* options) { void TimedTextPlayer::postTextEvent(const sp& parcel, int64_t timeUs) { int64_t delayUs = delayUsFromCurrentTime(timeUs); - sp listener = mListener.promote(); - if (listener != NULL) { - sp msg = new AMessage(kWhatSendSubtitle, id()); - msg->setInt32("generation", mSendSubtitleGeneration); - if (parcel != NULL) { - msg->setObject("subtitle", parcel); - } - msg->setInt64("fireTimeUs", timeUs); - msg->post(delayUs); + sp msg = new AMessage(kWhatSendSubtitle, id()); + msg->setInt32("generation", mSendSubtitleGeneration); + if (parcel != NULL) { + msg->setObject("subtitle", parcel); } + msg->setInt64("fireTimeUs", timeUs); + msg->post(delayUs); } int64_t TimedTextPlayer::delayUsFromCurrentTime(int64_t fireTimeUs) { sp listener = mListener.promote(); if (listener == NULL) { // TODO: it may be better to return kInvalidTimeUs + ALOGE("%s: Listener is NULL.", __FUNCTION__, fireTimeUs); return 0; } int32_t positionMs = 0; @@ -256,19 +281,23 @@ int64_t TimedTextPlayer::delayUsFromCurrentTime(int64_t fireTimeUs) { void TimedTextPlayer::notifyError(int error) { sp listener = mListener.promote(); - if (listener != NULL) { - listener->sendEvent(MEDIA_INFO, MEDIA_INFO_TIMED_TEXT_ERROR, error); + if (listener == NULL) { + ALOGE("%s(error=%d): Listener is NULL.", __FUNCTION__, error); + return; } + listener->sendEvent(MEDIA_INFO, MEDIA_INFO_TIMED_TEXT_ERROR, error); } void TimedTextPlayer::notifyListener(const Parcel *parcel) { sp listener = mListener.promote(); - if (listener != NULL) { - if (parcel != NULL && (parcel->dataSize() > 0)) { - listener->sendEvent(MEDIA_TIMED_TEXT, 0, 0, parcel); - } else { // send an empty timed text to clear the screen - listener->sendEvent(MEDIA_TIMED_TEXT); - } + if (listener == NULL) { + ALOGE("%s: Listener is NULL.", __FUNCTION__); + return; + } + if (parcel != NULL && (parcel->dataSize() > 0)) { + listener->sendEvent(MEDIA_TIMED_TEXT, 0, 0, parcel); + } else { // send an empty timed text to clear the screen + listener->sendEvent(MEDIA_TIMED_TEXT); } } diff --git a/media/libstagefright/timedtext/TimedTextPlayer.h b/media/libstagefright/timedtext/TimedTextPlayer.h index d8f83af..ec8ed25 100644 --- a/media/libstagefright/timedtext/TimedTextPlayer.h +++ b/media/libstagefright/timedtext/TimedTextPlayer.h @@ -50,8 +50,9 @@ protected: private: enum { kWhatPause = 'paus', - kWhatSeek = 'seek', kWhatResume = 'resm', + kWhatStart = 'strt', + kWhatSeek = 'seek', kWhatRetryRead = 'read', kWhatSendSubtitle = 'send', kWhatSetSource = 'ssrc', @@ -64,6 +65,8 @@ private: wp mListener; sp mSource; + int64_t mPendingSeekTimeUs; + bool mPaused; int32_t mSendSubtitleGeneration; void doSeekAndRead(int64_t seekTimeUs); -- cgit v1.1