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/libstagefright/httplive/Android.mk | 1 + media/libstagefright/httplive/LiveSession.cpp | 59 +++++++++++--- media/libstagefright/httplive/LiveSession.h | 9 ++- media/libstagefright/httplive/M3UParser.cpp | 95 ++++++++++++++++++++++- media/libstagefright/httplive/M3UParser.h | 4 + media/libstagefright/httplive/PlaylistFetcher.cpp | 15 +++- media/libstagefright/httplive/PlaylistFetcher.h | 3 +- 7 files changed, 168 insertions(+), 18 deletions(-) (limited to 'media/libstagefright') diff --git a/media/libstagefright/httplive/Android.mk b/media/libstagefright/httplive/Android.mk index 85bd492..f3529f9 100644 --- a/media/libstagefright/httplive/Android.mk +++ b/media/libstagefright/httplive/Android.mk @@ -14,6 +14,7 @@ LOCAL_C_INCLUDES:= \ $(TOP)/external/openssl/include LOCAL_SHARED_LIBRARIES := \ + libbinder \ libcrypto \ libcutils \ libmedia \ diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp index e91c60b..bd12ddc 100644 --- a/media/libstagefright/httplive/LiveSession.cpp +++ b/media/libstagefright/httplive/LiveSession.cpp @@ -59,6 +59,7 @@ LiveSession::LiveSession( mStreamMask(0), mCheckBandwidthGeneration(0), mLastDequeuedTimeUs(0ll), + mRealTimeBaseUs(0ll), mReconfigurationInProgress(false), mDisconnectReplyID(0) { if (mUIDValid) { @@ -122,11 +123,18 @@ status_t LiveSession::dequeueAccessUnit( type, extra == NULL ? "NULL" : extra->debugString().c_str()); } else if (err == OK) { - int64_t timeUs; - CHECK((*accessUnit)->meta()->findInt64("timeUs", &timeUs)); - ALOGV("[%s] read buffer at time %lld us", streamStr, timeUs); - - mLastDequeuedTimeUs = timeUs; + if (stream == STREAMTYPE_AUDIO || stream == STREAMTYPE_VIDEO) { + int64_t timeUs; + CHECK((*accessUnit)->meta()->findInt64("timeUs", &timeUs)); + ALOGV("[%s] read buffer at time %lld us", streamStr, timeUs); + + mLastDequeuedTimeUs = timeUs; + mRealTimeBaseUs = ALooper::GetNowUs() - timeUs; + } else if (stream == STREAMTYPE_SUBTITLES) { + (*accessUnit)->meta()->setInt32( + "trackIndex", mPlaylist->getSelectedIndex()); + (*accessUnit)->meta()->setInt64("baseUs", mRealTimeBaseUs); + } } else { ALOGI("[%s] encountered error %d", streamStr, err); } @@ -325,6 +333,12 @@ void LiveSession::onMessageReceived(const sp &msg) { break; } + case kWhatChangeConfiguration: + { + onChangeConfiguration(msg); + break; + } + case kWhatChangeConfiguration2: { onChangeConfiguration2(msg); @@ -438,7 +452,8 @@ void LiveSession::onConnect(const sp &msg) { mBandwidthItems.push(item); } - changeConfiguration(0ll /* timeUs */, initialBandwidthIndex); + changeConfiguration( + 0ll /* timeUs */, initialBandwidthIndex, true /* pickTrack */); } void LiveSession::finishDisconnect() { @@ -783,16 +798,31 @@ bool LiveSession::hasDynamicDuration() const { return false; } -void LiveSession::changeConfiguration(int64_t timeUs, size_t bandwidthIndex) { +status_t LiveSession::getTrackInfo(Parcel *reply) const { + return mPlaylist->getTrackInfo(reply); +} + +status_t LiveSession::selectTrack(size_t index, bool select) { + status_t err = mPlaylist->selectTrack(index, select); + if (err == OK) { + (new AMessage(kWhatChangeConfiguration, id()))->post(); + } + return err; +} + +void LiveSession::changeConfiguration( + int64_t timeUs, size_t bandwidthIndex, bool pickTrack) { CHECK(!mReconfigurationInProgress); mReconfigurationInProgress = true; mPrevBandwidthIndex = bandwidthIndex; - ALOGV("changeConfiguration => timeUs:%lld us, bwIndex:%d", - timeUs, bandwidthIndex); + ALOGV("changeConfiguration => timeUs:%lld us, bwIndex:%d, pickTrack:%d", + timeUs, bandwidthIndex, pickTrack); - mPlaylist->pickRandomMediaItems(); + if (pickTrack) { + mPlaylist->pickRandomMediaItems(); + } CHECK_LT(bandwidthIndex, mBandwidthItems.size()); const BandwidthItem &item = mBandwidthItems.itemAt(bandwidthIndex); @@ -862,6 +892,14 @@ void LiveSession::changeConfiguration(int64_t timeUs, size_t bandwidthIndex) { } } +void LiveSession::onChangeConfiguration(const sp &msg) { + if (!mReconfigurationInProgress) { + changeConfiguration(-1ll /* timeUs */, getBandwidthIndex()); + } else { + msg->post(1000000ll); // retry in 1 sec + } +} + void LiveSession::onChangeConfiguration2(const sp &msg) { mContinuation.clear(); @@ -948,6 +986,7 @@ void LiveSession::onChangeConfiguration3(const sp &msg) { if (timeUs < 0ll) { timeUs = mLastDequeuedTimeUs; } + mRealTimeBaseUs = ALooper::GetNowUs() - timeUs; mStreamMask = streamMask; mAudioURI = audioURI; diff --git a/media/libstagefright/httplive/LiveSession.h b/media/libstagefright/httplive/LiveSession.h index b134725..99b480a8 100644 --- a/media/libstagefright/httplive/LiveSession.h +++ b/media/libstagefright/httplive/LiveSession.h @@ -31,6 +31,7 @@ struct HTTPBase; struct LiveDataSource; struct M3UParser; struct PlaylistFetcher; +struct Parcel; struct LiveSession : public AHandler { enum Flags { @@ -60,6 +61,8 @@ struct LiveSession : public AHandler { status_t seekTo(int64_t timeUs); status_t getDuration(int64_t *durationUs) const; + status_t getTrackInfo(Parcel *reply) const; + status_t selectTrack(size_t index, bool select); bool isSeekable() const; bool hasDynamicDuration() const; @@ -85,6 +88,7 @@ private: kWhatSeek = 'seek', kWhatFetcherNotify = 'notf', kWhatCheckBandwidth = 'bndw', + kWhatChangeConfiguration = 'chC0', kWhatChangeConfiguration2 = 'chC2', kWhatChangeConfiguration3 = 'chC3', kWhatFinishDisconnect2 = 'fin2', @@ -130,6 +134,7 @@ private: sp mContinuation; int64_t mLastDequeuedTimeUs; + int64_t mRealTimeBaseUs; bool mReconfigurationInProgress; uint32_t mDisconnectReplyID; @@ -151,7 +156,9 @@ private: static int SortByBandwidth(const BandwidthItem *, const BandwidthItem *); - void changeConfiguration(int64_t timeUs, size_t bandwidthIndex); + void changeConfiguration( + int64_t timeUs, size_t bandwidthIndex, bool pickTrack = false); + void onChangeConfiguration(const sp &msg); void onChangeConfiguration2(const sp &msg); void onChangeConfiguration3(const sp &msg); diff --git a/media/libstagefright/httplive/M3UParser.cpp b/media/libstagefright/httplive/M3UParser.cpp index be66252..bc6d629 100644 --- a/media/libstagefright/httplive/M3UParser.cpp +++ b/media/libstagefright/httplive/M3UParser.cpp @@ -19,11 +19,12 @@ #include #include "M3UParser.h" - +#include #include #include #include #include +#include namespace android { @@ -55,6 +56,9 @@ struct M3UParser::MediaGroup : public RefBase { bool getActiveURI(AString *uri) const; void pickRandomMediaItems(); + status_t selectTrack(size_t index, bool select); + void getTrackInfo(Parcel* reply) const; + size_t countTracks() const; protected: virtual ~MediaGroup(); @@ -150,6 +154,59 @@ void M3UParser::MediaGroup::pickRandomMediaItems() { #endif } +status_t M3UParser::MediaGroup::selectTrack(size_t index, bool select) { + if (mType != TYPE_SUBS) { + ALOGE("only select subtitile tracks for now!"); + return INVALID_OPERATION; + } + + if (select) { + if (index >= mMediaItems.size()) { + ALOGE("track %d does not exist", index); + return INVALID_OPERATION; + } + if (mSelectedIndex == index) { + ALOGE("track %d already selected", index); + return BAD_VALUE; + } + ALOGV("selected track %d", index); + mSelectedIndex = index; + } else { + if (mSelectedIndex != index) { + ALOGE("track %d is not selected", index); + return BAD_VALUE; + } + ALOGV("unselected track %d", index); + mSelectedIndex = -1; + } + + return OK; +} + +void M3UParser::MediaGroup::getTrackInfo(Parcel* reply) const { + for (size_t i = 0; i < mMediaItems.size(); ++i) { + reply->writeInt32(2); // 2 fields + + if (mType == TYPE_AUDIO) { + reply->writeInt32(MEDIA_TRACK_TYPE_AUDIO); + } else if (mType == TYPE_VIDEO) { + reply->writeInt32(MEDIA_TRACK_TYPE_VIDEO); + } else if (mType == TYPE_SUBS) { + reply->writeInt32(MEDIA_TRACK_TYPE_SUBTITLE); + } else { + reply->writeInt32(MEDIA_TRACK_TYPE_UNKNOWN); + } + + const Media &item = mMediaItems.itemAt(i); + const char *lang = item.mLanguage.empty() ? "und" : item.mLanguage.c_str(); + reply->writeString16(String16(lang)); + } +} + +size_t M3UParser::MediaGroup::countTracks() const { + return mMediaItems.size(); +} + bool M3UParser::MediaGroup::getActiveURI(AString *uri) const { for (size_t i = 0; i < mMediaItems.size(); ++i) { if (mSelectedIndex >= 0 && i == (size_t)mSelectedIndex) { @@ -172,7 +229,8 @@ M3UParser::M3UParser( mIsExtM3U(false), mIsVariantPlaylist(false), mIsComplete(false), - mIsEvent(false) { + mIsEvent(false), + mSelectedIndex(-1) { mInitCheck = parse(data, size); } @@ -237,6 +295,39 @@ void M3UParser::pickRandomMediaItems() { } } +status_t M3UParser::selectTrack(size_t index, bool select) { + for (size_t i = 0, ii = index; i < mMediaGroups.size(); ++i) { + sp group = mMediaGroups.valueAt(i); + size_t tracks = group->countTracks(); + if (ii < tracks) { + status_t err = group->selectTrack(ii, select); + if (err == OK) { + mSelectedIndex = select ? index : -1; + } + return err; + } + ii -= tracks; + } + return INVALID_OPERATION; +} + +status_t M3UParser::getTrackInfo(Parcel* reply) const { + size_t trackCount = 0; + for (size_t i = 0; i < mMediaGroups.size(); ++i) { + trackCount += mMediaGroups.valueAt(i)->countTracks(); + } + reply->writeInt32(trackCount); + + for (size_t i = 0; i < mMediaGroups.size(); ++i) { + mMediaGroups.valueAt(i)->getTrackInfo(reply); + } + return OK; +} + +ssize_t M3UParser::getSelectedIndex() const { + return mSelectedIndex; +} + bool M3UParser::getTypeURI(size_t index, const char *key, AString *uri) const { if (!mIsVariantPlaylist) { *uri = mBaseURI; diff --git a/media/libstagefright/httplive/M3UParser.h b/media/libstagefright/httplive/M3UParser.h index abea286..5248004 100644 --- a/media/libstagefright/httplive/M3UParser.h +++ b/media/libstagefright/httplive/M3UParser.h @@ -41,6 +41,9 @@ struct M3UParser : public RefBase { bool itemAt(size_t index, AString *uri, sp *meta = NULL); void pickRandomMediaItems(); + status_t selectTrack(size_t index, bool select); + status_t getTrackInfo(Parcel* reply) const; + ssize_t getSelectedIndex() const; bool getAudioURI(size_t index, AString *uri) const; bool getVideoURI(size_t index, AString *uri) const; @@ -67,6 +70,7 @@ private: sp mMeta; Vector mItems; + ssize_t mSelectedIndex; // Media groups keyed by group ID. KeyedVector > mMediaGroups; diff --git a/media/libstagefright/httplive/PlaylistFetcher.cpp b/media/libstagefright/httplive/PlaylistFetcher.cpp index 8ae70b7..973b779 100644 --- a/media/libstagefright/httplive/PlaylistFetcher.cpp +++ b/media/libstagefright/httplive/PlaylistFetcher.cpp @@ -462,7 +462,11 @@ void PlaylistFetcher::onMonitorQueue() { sp packetSource = mPacketSources.valueFor(LiveSession::STREAMTYPE_SUBTITLES); - downloadMore = packetSource->hasBufferAvailable(&finalResult); + int64_t bufferedDurationUs = + packetSource->getBufferedDurationUs(&finalResult); + + downloadMore = (bufferedDurationUs < kMinBufferedDurationUs); + finalResult = OK; } else { bool first = true; int64_t minBufferedDurationUs = 0ll; @@ -659,7 +663,7 @@ void PlaylistFetcher::onDownloadNext() { } } - err = extractAndQueueAccessUnits(buffer); + err = extractAndQueueAccessUnits(buffer, itemMeta); if (err != OK) { notifyError(err); @@ -706,7 +710,7 @@ int32_t PlaylistFetcher::getSeqNumberForTime(int64_t timeUs) const { } status_t PlaylistFetcher::extractAndQueueAccessUnits( - const sp &buffer) { + const sp &buffer, const sp &itemMeta) { if (buffer->size() > 0 && buffer->data()[0] == 0x47) { // Let's assume this is an MPEG2 transport stream. @@ -802,7 +806,10 @@ status_t PlaylistFetcher::extractAndQueueAccessUnits( const sp packetSource = mPacketSources.valueFor(LiveSession::STREAMTYPE_SUBTITLES); - buffer->meta()->setInt64("timeUs", 0ll); + int64_t durationUs; + CHECK(itemMeta->findInt64("durationUs", &durationUs)); + buffer->meta()->setInt64("timeUs", getSegmentStartTimeUs(mSeqNumber)); + buffer->meta()->setInt64("durationUs", durationUs); packetSource->queueAccessUnit(buffer); return OK; diff --git a/media/libstagefright/httplive/PlaylistFetcher.h b/media/libstagefright/httplive/PlaylistFetcher.h index 5a2b901..1648e02 100644 --- a/media/libstagefright/httplive/PlaylistFetcher.h +++ b/media/libstagefright/httplive/PlaylistFetcher.h @@ -135,7 +135,8 @@ private: void onMonitorQueue(); void onDownloadNext(); - status_t extractAndQueueAccessUnits(const sp &buffer); + status_t extractAndQueueAccessUnits( + const sp &buffer, const sp &itemMeta); void notifyError(status_t err); -- cgit v1.1