summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/httplive/LiveSession.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'media/libstagefright/httplive/LiveSession.cpp')
-rw-r--r--media/libstagefright/httplive/LiveSession.cpp86
1 files changed, 62 insertions, 24 deletions
diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp
index 26f8da1..4886000 100644
--- a/media/libstagefright/httplive/LiveSession.cpp
+++ b/media/libstagefright/httplive/LiveSession.cpp
@@ -171,6 +171,8 @@ LiveSession::LiveSession(
mOrigBandwidthIndex(-1),
mLastBandwidthBps(-1ll),
mBandwidthEstimator(new BandwidthEstimator()),
+ mMaxWidth(720),
+ mMaxHeight(480),
mStreamMask(0),
mNewStreamMask(0),
mSwapMask(0),
@@ -345,6 +347,9 @@ status_t LiveSession::getStreamFormat(StreamType stream, sp<AMessage> *format) {
if (stream == STREAMTYPE_AUDIO) {
// set AAC input buffer size to 32K bytes (256kbps x 1sec)
meta->setInt32(kKeyMaxInputSize, 32 * 1024);
+ } else if (stream == STREAMTYPE_VIDEO) {
+ meta->setInt32(kKeyMaxWidth, mMaxWidth);
+ meta->setInt32(kKeyMaxHeight, mMaxHeight);
}
return convertMetaDataToMessage(meta, format);
@@ -847,6 +852,9 @@ void LiveSession::onConnect(const sp<AMessage> &msg) {
size_t initialBandwidth = 0;
size_t initialBandwidthIndex = 0;
+ int32_t maxWidth = 0;
+ int32_t maxHeight = 0;
+
if (mPlaylist->isVariantPlaylist()) {
Vector<BandwidthItem> itemsWithVideo;
for (size_t i = 0; i < mPlaylist->size(); ++i) {
@@ -860,6 +868,14 @@ void LiveSession::onConnect(const sp<AMessage> &msg) {
CHECK(meta->findInt32("bandwidth", (int32_t *)&item.mBandwidth));
+ int32_t width, height;
+ if (meta->findInt32("width", &width)) {
+ maxWidth = max(maxWidth, width);
+ }
+ if (meta->findInt32("height", &height)) {
+ maxHeight = max(maxHeight, height);
+ }
+
mBandwidthItems.push(item);
if (mPlaylist->hasType(i, "video")) {
itemsWithVideo.push(item);
@@ -893,6 +909,9 @@ void LiveSession::onConnect(const sp<AMessage> &msg) {
mBandwidthItems.push(item);
}
+ mMaxWidth = maxWidth > 0 ? maxWidth : mMaxWidth;
+ mMaxHeight = maxHeight > 0 ? maxHeight : mMaxHeight;
+
mPlaylist->pickRandomMediaItems();
changeConfiguration(
0ll /* timeUs */, initialBandwidthIndex, false /* pickTrack */);
@@ -1455,6 +1474,10 @@ void LiveSession::changeConfiguration(
if (bandwidthIndex >= 0) {
mOrigBandwidthIndex = mCurBandwidthIndex;
mCurBandwidthIndex = bandwidthIndex;
+ if (mOrigBandwidthIndex != mCurBandwidthIndex) {
+ ALOGI("#### Starting Bandwidth Switch: %zd => %zd",
+ mOrigBandwidthIndex, mCurBandwidthIndex);
+ }
}
CHECK_LT(mCurBandwidthIndex, mBandwidthItems.size());
const BandwidthItem &item = mBandwidthItems.itemAt(mCurBandwidthIndex);
@@ -1574,6 +1597,7 @@ void LiveSession::onChangeConfiguration2(const sp<AMessage> &msg) {
if (timeUs >= 0) {
mLastSeekTimeUs = timeUs;
+ mLastDequeuedTimeUs = timeUs;
for (size_t i = 0; i < mPacketSources.size(); i++) {
mPacketSources.editValueAt(i)->clear();
@@ -1626,8 +1650,10 @@ void LiveSession::onChangeConfiguration2(const sp<AMessage> &msg) {
ALOGV("stream %zu changed: oldURI %s, newURI %s", i,
mStreams[i].mUri.c_str(), URIs[i].c_str());
sp<AnotherPacketSource> source = mPacketSources.valueFor(indexToType(i));
- source->queueDiscontinuity(
- ATSParser::DISCONTINUITY_FORMATCHANGE, NULL, true);
+ if (source->getLatestDequeuedMeta() != NULL) {
+ source->queueDiscontinuity(
+ ATSParser::DISCONTINUITY_FORMATCHANGE, NULL, true);
+ }
}
// Determine which decoders to shutdown on the player side,
// a decoder has to be shutdown if its streamtype was active
@@ -1687,10 +1713,6 @@ void LiveSession::onChangeConfiguration3(const sp<AMessage> &msg) {
// and resume audio.
mSwapMask = mNewStreamMask & mStreamMask & ~resumeMask;
switching = (mSwapMask != 0);
- if (!switching) {
- ALOGV("#### Finishing Bandwidth Switch Early: %zd => %zd",
- mOrigBandwidthIndex, mCurBandwidthIndex);
- }
}
mRealTimeBaseUs = ALooper::GetNowUs() - mLastDequeuedTimeUs;
} else {
@@ -1843,7 +1865,11 @@ void LiveSession::onChangeConfiguration3(const sp<AMessage> &msg) {
mSwitchInProgress = true;
} else {
mStreamMask = mNewStreamMask;
- mOrigBandwidthIndex = mCurBandwidthIndex;
+ if (mOrigBandwidthIndex != mCurBandwidthIndex) {
+ ALOGV("#### Finished Bandwidth Switch Early: %zd => %zd",
+ mOrigBandwidthIndex, mCurBandwidthIndex);
+ mOrigBandwidthIndex = mCurBandwidthIndex;
+ }
}
ALOGV("onChangeConfiguration3: mSwitchInProgress %d, mStreamMask 0x%x",
@@ -1970,11 +1996,19 @@ void LiveSession::onPollBuffering() {
bool underflow, ready, down, up;
if (checkBuffering(underflow, ready, down, up)) {
- if (mInPreparationPhase && ready) {
- postPrepared(OK);
+ if (mInPreparationPhase) {
+ // Allow down switch even if we're still preparing.
+ //
+ // Some streams have a high bandwidth index as default,
+ // when bandwidth is low, it takes a long time to buffer
+ // to ready mark, then it immediately pauses after start
+ // as we have to do a down switch. It's better experience
+ // to restart from a lower index, if we detect low bw.
+ if (!switchBandwidthIfNeeded(false /* up */, down) && ready) {
+ postPrepared(OK);
+ }
}
- // don't switch before we report prepared
if (!mInPreparationPhase) {
if (ready) {
stopBufferingIfNecessary();
@@ -1982,8 +2016,7 @@ void LiveSession::onPollBuffering() {
startBufferingIfNecessary();
}
switchBandwidthIfNeeded(up, down);
- }
-
+ }
}
schedulePollBuffering();
@@ -2075,7 +2108,8 @@ bool LiveSession::checkBuffering(
if (mPacketSources[i]->isFinished(0 /* duration */)) {
percent = 100;
} else {
- percent = (int32_t)(100.0 * (mLastDequeuedTimeUs + bufferedDurationUs) / durationUs);
+ percent = (int32_t)(100.0 *
+ (mLastDequeuedTimeUs + bufferedDurationUs) / durationUs);
}
if (minBufferPercent < 0 || percent < minBufferPercent) {
minBufferPercent = percent;
@@ -2158,10 +2192,14 @@ void LiveSession::notifyBufferingUpdate(int32_t percentage) {
notify->post();
}
-void LiveSession::switchBandwidthIfNeeded(bool bufferHigh, bool bufferLow) {
+/*
+ * returns true if a bandwidth switch is actually needed (and started),
+ * returns false otherwise
+ */
+bool LiveSession::switchBandwidthIfNeeded(bool bufferHigh, bool bufferLow) {
// no need to check bandwidth if we only have 1 bandwidth settings
if (mSwitchInProgress || mBandwidthItems.size() < 2) {
- return;
+ return false;
}
int32_t bandwidthBps;
@@ -2170,7 +2208,7 @@ void LiveSession::switchBandwidthIfNeeded(bool bufferHigh, bool bufferLow) {
mLastBandwidthBps = bandwidthBps;
} else {
ALOGV("no bandwidth estimate.");
- return;
+ return false;
}
int32_t curBandwidth = mBandwidthItems.itemAt(mCurBandwidthIndex).mBandwidth;
@@ -2189,16 +2227,16 @@ void LiveSession::switchBandwidthIfNeeded(bool bufferHigh, bool bufferLow) {
// bandwidthIndex is < mCurBandwidthIndex, as getBandwidthIndex() only uses 70%
// of measured bw. In that case we don't want to do anything, since we have
// both enough buffer and enough bw.
- if (bandwidthIndex == mCurBandwidthIndex
- || (canSwitchUp && bandwidthIndex < mCurBandwidthIndex)
- || (canSwithDown && bandwidthIndex > mCurBandwidthIndex)) {
- return;
+ if ((canSwitchUp && bandwidthIndex > mCurBandwidthIndex)
+ || (canSwithDown && bandwidthIndex < mCurBandwidthIndex)) {
+ // if not yet prepared, just restart again with new bw index.
+ // this is faster and playback experience is cleaner.
+ changeConfiguration(
+ mInPreparationPhase ? 0 : -1ll, bandwidthIndex);
+ return true;
}
-
- ALOGI("#### Starting Bandwidth Switch: %zd => %zd",
- mCurBandwidthIndex, bandwidthIndex);
- changeConfiguration(-1, bandwidthIndex, false);
}
+ return false;
}
void LiveSession::postError(status_t err) {