diff options
author | Chong Zhang <chz@google.com> | 2015-04-12 01:03:51 -0700 |
---|---|---|
committer | Chong Zhang <chz@google.com> | 2015-04-17 14:26:32 -0700 |
commit | 978449984366946a2e5c9f7cf350746f4306caf8 (patch) | |
tree | 21d406ec763c97554a5db234b49807ecb7a659b2 /media/libstagefright/httplive/LiveSession.cpp | |
parent | 2170233c49e50f3986cdc4f726016d6003cb5b8e (diff) | |
download | frameworks_av-978449984366946a2e5c9f7cf350746f4306caf8.zip frameworks_av-978449984366946a2e5c9f7cf350746f4306caf8.tar.gz frameworks_av-978449984366946a2e5c9f7cf350746f4306caf8.tar.bz2 |
HLS: reduce number of guessed wrong seq numbers
- account for playlist age in live streaming when calculating
segment time
- be more conservative on downswitching if bandwidth is unstable
- adjust forward or backward if guessed wrong seq number
- code refactor
bug: 19567254
Change-Id: I0b61cea888fdffd1b3ee2446747ed10152e9e7d7
Diffstat (limited to 'media/libstagefright/httplive/LiveSession.cpp')
-rw-r--r-- | media/libstagefright/httplive/LiveSession.cpp | 58 |
1 files changed, 50 insertions, 8 deletions
diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp index 203444a..764ff82 100644 --- a/media/libstagefright/httplive/LiveSession.cpp +++ b/media/libstagefright/httplive/LiveSession.cpp @@ -67,7 +67,7 @@ struct LiveSession::BandwidthEstimator : public RefBase { BandwidthEstimator(); void addBandwidthMeasurement(size_t numBytes, int64_t delayUs); - bool estimateBandwidth(int32_t *bandwidth); + bool estimateBandwidth(int32_t *bandwidth, bool *isStable = NULL); private: // Bandwidth estimation parameters @@ -81,6 +81,9 @@ private: Mutex mLock; List<BandwidthEntry> mBandwidthHistory; + List<int32_t> mPrevEstimates; + bool mHasNewSample; + bool mIsStable; int64_t mTotalTransferTimeUs; size_t mTotalTransferBytes; @@ -88,6 +91,8 @@ private: }; LiveSession::BandwidthEstimator::BandwidthEstimator() : + mHasNewSample(false), + mIsStable(true), mTotalTransferTimeUs(0), mTotalTransferBytes(0) { } @@ -102,6 +107,7 @@ void LiveSession::BandwidthEstimator::addBandwidthMeasurement( mTotalTransferTimeUs += delayUs; mTotalTransferBytes += numBytes; mBandwidthHistory.push_back(entry); + mHasNewSample = true; // trim old samples, keeping at least kMaxBandwidthHistoryItems samples, // and total transfer time at least kMaxBandwidthHistoryWindowUs. @@ -116,14 +122,43 @@ void LiveSession::BandwidthEstimator::addBandwidthMeasurement( } } -bool LiveSession::BandwidthEstimator::estimateBandwidth(int32_t *bandwidthBps) { +bool LiveSession::BandwidthEstimator::estimateBandwidth(int32_t *bandwidthBps, bool *isStable) { AutoMutex autoLock(mLock); if (mBandwidthHistory.size() < 2) { return false; } + if (!mHasNewSample) { + *bandwidthBps = *(--mPrevEstimates.end()); + if (isStable) { + *isStable = mIsStable; + } + return true; + } + *bandwidthBps = ((double)mTotalTransferBytes * 8E6 / mTotalTransferTimeUs); + mPrevEstimates.push_back(*bandwidthBps); + while (mPrevEstimates.size() > 3) { + mPrevEstimates.erase(mPrevEstimates.begin()); + } + mHasNewSample = false; + + int32_t minEstimate = -1, maxEstimate = -1; + List<int32_t>::iterator it; + for (it = mPrevEstimates.begin(); it != mPrevEstimates.end(); it++) { + int32_t estimate = *it; + if (minEstimate < 0 || minEstimate > estimate) { + minEstimate = estimate; + } + if (maxEstimate < 0 || maxEstimate < estimate) { + maxEstimate = estimate; + } + } + mIsStable = (maxEstimate <= minEstimate * 4 / 3); + if (isStable) { + *isStable = mIsStable; + } return true; } @@ -1930,7 +1965,7 @@ void LiveSession::onChangeConfiguration3(const sp<AMessage> &msg) { fetcher->getFetcherID(), (long long)startTime.mTimeUs, (long long)mLastSeekTimeUs, - (long long)startTime.getSegmentTimeUs(true /* midpoint */), + (long long)startTime.getSegmentTimeUs(), seekMode); // Set the target segment start time to the middle point of the @@ -1945,7 +1980,7 @@ void LiveSession::onChangeConfiguration3(const sp<AMessage> &msg) { sources[kSubtitleIndex], getMetadataSource(sources, mNewStreamMask, switching), startTime.mTimeUs < 0 ? mLastSeekTimeUs : startTime.mTimeUs, - startTime.getSegmentTimeUs(true /* midpoint */), + startTime.getSegmentTimeUs(), startTime.mSeq, seekMode); } @@ -2296,7 +2331,8 @@ bool LiveSession::switchBandwidthIfNeeded(bool bufferHigh, bool bufferLow) { } int32_t bandwidthBps; - if (mBandwidthEstimator->estimateBandwidth(&bandwidthBps)) { + bool isStable; + if (mBandwidthEstimator->estimateBandwidth(&bandwidthBps, &isStable)) { ALOGV("bandwidth estimated at %.2f kbps", bandwidthBps / 1024.0f); mLastBandwidthBps = bandwidthBps; } else { @@ -2308,12 +2344,18 @@ bool LiveSession::switchBandwidthIfNeeded(bool bufferHigh, bool bufferLow) { // canSwithDown and canSwitchUp can't both be true. // we only want to switch up when measured bw is 120% higher than current variant, // and we only want to switch down when measured bw is below current variant. - bool canSwithDown = bufferLow + bool canSwitchDown = bufferLow && (bandwidthBps < (int32_t)curBandwidth); bool canSwitchUp = bufferHigh && (bandwidthBps > (int32_t)curBandwidth * 12 / 10); - if (canSwithDown || canSwitchUp) { + if (canSwitchDown || canSwitchUp) { + // bandwidth estimating has some delay, if we have to downswitch when + // it hasn't stabilized, be very conservative on bandwidth. + if (!isStable && canSwitchDown) { + bandwidthBps /= 2; + } + ssize_t bandwidthIndex = getBandwidthIndex(bandwidthBps); // it's possible that we're checking for canSwitchUp case, but the returned @@ -2321,7 +2363,7 @@ bool LiveSession::switchBandwidthIfNeeded(bool bufferHigh, bool bufferLow) { // of measured bw. In that case we don't want to do anything, since we have // both enough buffer and enough bw. if ((canSwitchUp && bandwidthIndex > mCurBandwidthIndex) - || (canSwithDown && bandwidthIndex < mCurBandwidthIndex)) { + || (canSwitchDown && bandwidthIndex < mCurBandwidthIndex)) { // if not yet prepared, just restart again with new bw index. // this is faster and playback experience is cleaner. changeConfiguration( |