diff options
author | Andreas Huber <andih@google.com> | 2013-02-06 10:44:39 -0800 |
---|---|---|
committer | Andreas Huber <andih@google.com> | 2013-02-06 10:44:39 -0800 |
commit | 0c3f0fa983107a8b5a4d6274179d15333fde8d3c (patch) | |
tree | 6ede9b14751812fcd5b9101e3f53a1910a3ac7a5 /media | |
parent | 7f475c34ffc8e35345f2cceee2ef56a50bb5fea6 (diff) | |
download | frameworks_av-0c3f0fa983107a8b5a4d6274179d15333fde8d3c.zip frameworks_av-0c3f0fa983107a8b5a4d6274179d15333fde8d3c.tar.gz frameworks_av-0c3f0fa983107a8b5a4d6274179d15333fde8d3c.tar.bz2 |
HLS now properly publishes its "seekable" flags after connection
has successfully completed and a sufficient amount of data fetched,
and only then signals that preparation is completed.
Change-Id: I7684a14238b826909f518f2af506966e522dfcfc
Diffstat (limited to 'media')
-rw-r--r-- | media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp | 74 | ||||
-rw-r--r-- | media/libmediaplayerservice/nuplayer/HTTPLiveSource.h | 8 | ||||
-rw-r--r-- | media/libstagefright/foundation/ALooperRoster.cpp | 3 | ||||
-rw-r--r-- | media/libstagefright/httplive/LiveSession.cpp | 53 | ||||
-rw-r--r-- | media/libstagefright/include/LiveSession.h | 15 |
5 files changed, 125 insertions, 28 deletions
diff --git a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp index ae67906..655ee55 100644 --- a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp +++ b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp @@ -71,7 +71,10 @@ void NuPlayer::HTTPLiveSource::prepareAsync() { mLiveLooper->setName("http live"); mLiveLooper->start(); + sp<AMessage> notify = new AMessage(kWhatSessionNotify, id()); + mLiveSession = new LiveSession( + notify, (mFlags & kFlagIncognito) ? LiveSession::kFlagIncognito : 0, mUIDValid, mUID); @@ -81,23 +84,6 @@ void NuPlayer::HTTPLiveSource::prepareAsync() { mURL.c_str(), mExtraHeaders.isEmpty() ? NULL : &mExtraHeaders); mTSParser = new ATSParser; - - notifyVideoSizeChanged(0, 0); - - uint32_t flags = FLAG_CAN_PAUSE; - if (mLiveSession->isSeekable()) { - flags |= FLAG_CAN_SEEK; - flags |= FLAG_CAN_SEEK_BACKWARD; - flags |= FLAG_CAN_SEEK_FORWARD; - } - - if (mLiveSession->hasDynamicDuration()) { - flags |= FLAG_DYNAMIC_DURATION; - } - - notifyFlagsChanged(flags); - - notifyPrepared(); } void NuPlayer::HTTPLiveSource::start() { @@ -214,5 +200,59 @@ status_t NuPlayer::HTTPLiveSource::seekTo(int64_t seekTimeUs) { return OK; } +void NuPlayer::HTTPLiveSource::onMessageReceived(const sp<AMessage> &msg) { + switch (msg->what()) { + case kWhatSessionNotify: + { + onSessionNotify(msg); + break; + } + + default: + Source::onMessageReceived(msg); + break; + } +} + +void NuPlayer::HTTPLiveSource::onSessionNotify(const sp<AMessage> &msg) { + int32_t what; + CHECK(msg->findInt32("what", &what)); + + switch (what) { + case LiveSession::kWhatPrepared: + { + notifyVideoSizeChanged(0, 0); + + uint32_t flags = FLAG_CAN_PAUSE; + if (mLiveSession->isSeekable()) { + flags |= FLAG_CAN_SEEK; + flags |= FLAG_CAN_SEEK_BACKWARD; + flags |= FLAG_CAN_SEEK_FORWARD; + } + + if (mLiveSession->hasDynamicDuration()) { + flags |= FLAG_DYNAMIC_DURATION; + } + + notifyFlagsChanged(flags); + + notifyPrepared(); + break; + } + + case LiveSession::kWhatPreparationFailed: + { + status_t err; + CHECK(msg->findInt32("err", &err)); + + notifyPrepared(err); + break; + } + + default: + TRESPASS(); + } +} + } // namespace android diff --git a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h index 269f3c0..067d1da 100644 --- a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h +++ b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h @@ -49,12 +49,18 @@ protected: virtual sp<MetaData> getFormatMeta(bool audio); + virtual void onMessageReceived(const sp<AMessage> &msg); + private: enum Flags { // Don't log any URLs. kFlagIncognito = 1, }; + enum { + kWhatSessionNotify, + }; + AString mURL; KeyedVector<String8, String8> mExtraHeaders; bool mUIDValid; @@ -66,6 +72,8 @@ private: sp<LiveSession> mLiveSession; sp<ATSParser> mTSParser; + void onSessionNotify(const sp<AMessage> &msg); + DISALLOW_EVIL_CONSTRUCTORS(HTTPLiveSource); }; diff --git a/media/libstagefright/foundation/ALooperRoster.cpp b/media/libstagefright/foundation/ALooperRoster.cpp index dff931d..ad10d2b 100644 --- a/media/libstagefright/foundation/ALooperRoster.cpp +++ b/media/libstagefright/foundation/ALooperRoster.cpp @@ -82,7 +82,8 @@ status_t ALooperRoster::postMessage_l( ssize_t index = mHandlers.indexOfKey(msg->target()); if (index < 0) { - ALOGW("failed to post message. Target handler not registered."); + ALOGW("failed to post message '%s'. Target handler not registered.", + msg->debugString().c_str()); return -ENOENT; } diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp index 733753b..962b01c 100644 --- a/media/libstagefright/httplive/LiveSession.cpp +++ b/media/libstagefright/httplive/LiveSession.cpp @@ -40,10 +40,13 @@ namespace android { -LiveSession::LiveSession(uint32_t flags, bool uidValid, uid_t uid) - : mFlags(flags), +LiveSession::LiveSession( + const sp<AMessage> ¬ify, uint32_t flags, bool uidValid, uid_t uid) + : mNotify(notify), + mFlags(flags), mUIDValid(uidValid), mUID(uid), + mInPreparationPhase(true), mDataSource(new LiveDataSource), mHTTPDataSource( HTTPBase::Create( @@ -179,7 +182,7 @@ void LiveSession::onConnect(const sp<AMessage> &msg) { if (playlist == NULL) { ALOGE("unable to fetch master playlist '%s'.", url.c_str()); - mDataSource->queueEOS(ERROR_IO); + signalEOS(ERROR_IO); return; } @@ -207,7 +210,7 @@ void LiveSession::onConnect(const sp<AMessage> &msg) { void LiveSession::onDisconnect() { ALOGI("onDisconnect"); - mDataSource->queueEOS(ERROR_END_OF_STREAM); + signalEOS(ERROR_END_OF_STREAM); Mutex::Autolock autoLock(mLock); mDisconnectPending = false; @@ -561,7 +564,8 @@ rinse_repeat: // unchanged from the last time we tried. } else { ALOGE("failed to load playlist at url '%s'", url.c_str()); - mDataSource->queueEOS(ERROR_IO); + signalEOS(ERROR_IO); + return; } } else { @@ -704,7 +708,7 @@ rinse_repeat: mSeqNumber, firstSeqNumberInPlaylist, firstSeqNumberInPlaylist + mPlaylist->size() - 1); - mDataSource->queueEOS(ERROR_END_OF_STREAM); + signalEOS(ERROR_END_OF_STREAM); return; } } @@ -737,7 +741,7 @@ rinse_repeat: status_t err = fetchFile(uri.c_str(), &buffer, range_offset, range_length); if (err != OK) { ALOGE("failed to fetch .ts segment at url '%s'", uri.c_str()); - mDataSource->queueEOS(err); + signalEOS(err); return; } @@ -748,7 +752,7 @@ rinse_repeat: if (err != OK) { ALOGE("decryptBuffer failed w/ error %d", err); - mDataSource->queueEOS(err); + signalEOS(err); return; } @@ -760,7 +764,7 @@ rinse_repeat: mBandwidthItems.removeAt(bandwidthIndex); if (mBandwidthItems.isEmpty()) { - mDataSource->queueEOS(ERROR_UNSUPPORTED); + signalEOS(ERROR_UNSUPPORTED); return; } @@ -824,11 +828,42 @@ rinse_repeat: postMonitorQueue(); } +void LiveSession::signalEOS(status_t err) { + if (mInPreparationPhase && mNotify != NULL) { + sp<AMessage> notify = mNotify->dup(); + + notify->setInt32( + "what", + err == ERROR_END_OF_STREAM + ? kWhatPrepared : kWhatPreparationFailed); + + if (err != ERROR_END_OF_STREAM) { + notify->setInt32("err", err); + } + + notify->post(); + + mInPreparationPhase = false; + } + + mDataSource->queueEOS(err); +} + void LiveSession::onMonitorQueue() { if (mSeekTimeUs >= 0 || mDataSource->countQueuedBuffers() < kMaxNumQueuedFragments) { onDownloadNext(); } else { + if (mInPreparationPhase) { + if (mNotify != NULL) { + sp<AMessage> notify = mNotify->dup(); + notify->setInt32("what", kWhatPrepared); + notify->post(); + } + + mInPreparationPhase = false; + } + postMonitorQueue(1000000ll); } } diff --git a/media/libstagefright/include/LiveSession.h b/media/libstagefright/include/LiveSession.h index f329cc9..db44a33 100644 --- a/media/libstagefright/include/LiveSession.h +++ b/media/libstagefright/include/LiveSession.h @@ -35,7 +35,9 @@ struct LiveSession : public AHandler { // Don't log any URLs. kFlagIncognito = 1, }; - LiveSession(uint32_t flags = 0, bool uidValid = false, uid_t uid = 0); + LiveSession( + const sp<AMessage> ¬ify, + uint32_t flags = 0, bool uidValid = false, uid_t uid = 0); sp<DataSource> getDataSource(); @@ -53,6 +55,12 @@ struct LiveSession : public AHandler { bool isSeekable() const; bool hasDynamicDuration() const; + // Posted notification's "what" field will carry one of the following: + enum { + kWhatPrepared, + kWhatPreparationFailed, + }; + protected: virtual ~LiveSession(); @@ -76,10 +84,13 @@ private: unsigned long mBandwidth; }; + sp<AMessage> mNotify; uint32_t mFlags; bool mUIDValid; uid_t mUID; + bool mInPreparationPhase; + sp<LiveDataSource> mDataSource; sp<HTTPBase> mHTTPDataSource; @@ -144,6 +155,8 @@ private: // This is computed by summing the durations of all segments before it. int64_t getSegmentStartTimeUs(int32_t seqNumber) const; + void signalEOS(status_t err); + DISALLOW_EVIL_CONSTRUCTORS(LiveSession); }; |