summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/httplive
diff options
context:
space:
mode:
authorChong Zhang <chz@google.com>2013-08-06 09:44:47 -0700
committerChong Zhang <chz@google.com>2013-08-19 10:53:52 -0700
commitdcb89b3b505522efde173c105a851c412f947178 (patch)
treeeb89386fb07021a6527b35ea3d8ecf80584c73b7 /media/libstagefright/httplive
parent1cb4e1661e4144cb188c2c79b89804fcb902fd19 (diff)
downloadframeworks_av-dcb89b3b505522efde173c105a851c412f947178.zip
frameworks_av-dcb89b3b505522efde173c105a851c412f947178.tar.gz
frameworks_av-dcb89b3b505522efde173c105a851c412f947178.tar.bz2
MediaPlayer: add listener for raw track data
Bug: 10326117 Change-Id: I2c0bdf8adc67b11f8dc633423bee66897548f181
Diffstat (limited to 'media/libstagefright/httplive')
-rw-r--r--media/libstagefright/httplive/Android.mk1
-rw-r--r--media/libstagefright/httplive/LiveSession.cpp59
-rw-r--r--media/libstagefright/httplive/LiveSession.h9
-rw-r--r--media/libstagefright/httplive/M3UParser.cpp95
-rw-r--r--media/libstagefright/httplive/M3UParser.h4
-rw-r--r--media/libstagefright/httplive/PlaylistFetcher.cpp15
-rw-r--r--media/libstagefright/httplive/PlaylistFetcher.h3
7 files changed, 168 insertions, 18 deletions
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<AMessage> &msg) {
break;
}
+ case kWhatChangeConfiguration:
+ {
+ onChangeConfiguration(msg);
+ break;
+ }
+
case kWhatChangeConfiguration2:
{
onChangeConfiguration2(msg);
@@ -438,7 +452,8 @@ void LiveSession::onConnect(const sp<AMessage> &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<AMessage> &msg) {
+ if (!mReconfigurationInProgress) {
+ changeConfiguration(-1ll /* timeUs */, getBandwidthIndex());
+ } else {
+ msg->post(1000000ll); // retry in 1 sec
+ }
+}
+
void LiveSession::onChangeConfiguration2(const sp<AMessage> &msg) {
mContinuation.clear();
@@ -948,6 +986,7 @@ void LiveSession::onChangeConfiguration3(const sp<AMessage> &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<AMessage> 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<AMessage> &msg);
void onChangeConfiguration2(const sp<AMessage> &msg);
void onChangeConfiguration3(const sp<AMessage> &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 <utils/Log.h>
#include "M3UParser.h"
-
+#include <binder/Parcel.h>
#include <cutils/properties.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/MediaErrors.h>
+#include <media/mediaplayer.h>
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<MediaGroup> 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<AMessage> *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<AMessage> mMeta;
Vector<Item> mItems;
+ ssize_t mSelectedIndex;
// Media groups keyed by group ID.
KeyedVector<AString, sp<MediaGroup> > 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<AnotherPacketSource> 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<ABuffer> &buffer) {
+ const sp<ABuffer> &buffer, const sp<AMessage> &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<AnotherPacketSource> 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<ABuffer> &buffer);
+ status_t extractAndQueueAccessUnits(
+ const sp<ABuffer> &buffer, const sp<AMessage> &itemMeta);
void notifyError(status_t err);