1a44153c1a57202fb538659eb50706e60454d6273Andreas Huber/* 2a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * Copyright (C) 2010 The Android Open Source Project 3a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * 4a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 5a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * you may not use this file except in compliance with the License. 6a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * You may obtain a copy of the License at 7a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * 8a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * http://www.apache.org/licenses/LICENSE-2.0 9a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * 10a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * Unless required by applicable law or agreed to in writing, software 11a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 12a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * See the License for the specific language governing permissions and 14a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * limitations under the License. 15a44153c1a57202fb538659eb50706e60454d6273Andreas Huber */ 16a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 17a44153c1a57202fb538659eb50706e60454d6273Andreas Huber//#define LOG_NDEBUG 0 18a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#define LOG_TAG "LiveSession" 19a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <utils/Log.h> 20a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 2114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include "LiveSession.h" 225abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang#include "HTTPDownloader.h" 2314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include "M3UParser.h" 2414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include "PlaylistFetcher.h" 25a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 2614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include "mpeg2ts/AnotherPacketSource.h" 27a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 28a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <cutils/properties.h> 291b86fe063badb5f28c467ade39be0f4008688947Andreas Huber#include <media/IMediaHTTPService.h> 30a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <media/stagefright/foundation/ABuffer.h> 31a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <media/stagefright/foundation/ADebug.h> 32a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <media/stagefright/foundation/AMessage.h> 337c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang#include <media/stagefright/foundation/AUtils.h> 340852843d304006e3ab333081fddda13b07193de8Robert Shih#include <media/stagefright/MediaDefs.h> 3514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include <media/stagefright/MetaData.h> 3614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include <media/stagefright/Utils.h> 37a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 381543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih#include <utils/Mutex.h> 391543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 40a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <ctype.h> 41b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross#include <inttypes.h> 42a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 43a44153c1a57202fb538659eb50706e60454d6273Andreas Hubernamespace android { 44a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 45765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang// static 46765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang// Bandwidth Switch Mark Defaults 47d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhangconst int64_t LiveSession::kUpSwitchMarkUs = 15000000ll; 48d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhangconst int64_t LiveSession::kDownSwitchMarkUs = 20000000ll; 49765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhangconst int64_t LiveSession::kUpSwitchMarginUs = 5000000ll; 50d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhangconst int64_t LiveSession::kResumeThresholdUs = 100000ll; 51765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang 52538b6d22a3578c0201d48f8548289aa254d81484Chong Zhangstruct LiveSession::BandwidthEstimator : public RefBase { 53538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang BandwidthEstimator(); 54538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 55538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang void addBandwidthMeasurement(size_t numBytes, int64_t delayUs); 565ef659e010e90175eb5282d9642a02f6105189bfChong Zhang bool estimateBandwidth( 575ef659e010e90175eb5282d9642a02f6105189bfChong Zhang int32_t *bandwidth, 585ef659e010e90175eb5282d9642a02f6105189bfChong Zhang bool *isStable = NULL, 595ef659e010e90175eb5282d9642a02f6105189bfChong Zhang int32_t *shortTermBps = NULL); 60538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 61538b6d22a3578c0201d48f8548289aa254d81484Chong Zhangprivate: 62538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang // Bandwidth estimation parameters 635ef659e010e90175eb5282d9642a02f6105189bfChong Zhang static const int32_t kShortTermBandwidthItems = 3; 6481636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang static const int32_t kMinBandwidthHistoryItems = 20; 6581636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang static const int64_t kMinBandwidthHistoryWindowUs = 5000000ll; // 5 sec 6681636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang static const int64_t kMaxBandwidthHistoryWindowUs = 30000000ll; // 30 sec 675ef659e010e90175eb5282d9642a02f6105189bfChong Zhang static const int64_t kMaxBandwidthHistoryAgeUs = 60000000ll; // 60 sec 68538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 69538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang struct BandwidthEntry { 705ef659e010e90175eb5282d9642a02f6105189bfChong Zhang int64_t mTimestampUs; 71538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang int64_t mDelayUs; 72538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang size_t mNumBytes; 73538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang }; 74538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 75538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang Mutex mLock; 76538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang List<BandwidthEntry> mBandwidthHistory; 77978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang List<int32_t> mPrevEstimates; 785ef659e010e90175eb5282d9642a02f6105189bfChong Zhang int32_t mShortTermEstimate; 79978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang bool mHasNewSample; 80978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang bool mIsStable; 81538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang int64_t mTotalTransferTimeUs; 82538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang size_t mTotalTransferBytes; 83538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 84538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang DISALLOW_EVIL_CONSTRUCTORS(BandwidthEstimator); 85538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang}; 86538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 87538b6d22a3578c0201d48f8548289aa254d81484Chong ZhangLiveSession::BandwidthEstimator::BandwidthEstimator() : 885ef659e010e90175eb5282d9642a02f6105189bfChong Zhang mShortTermEstimate(0), 89978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mHasNewSample(false), 90978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mIsStable(true), 91538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mTotalTransferTimeUs(0), 92538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mTotalTransferBytes(0) { 93538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang} 94538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 95538b6d22a3578c0201d48f8548289aa254d81484Chong Zhangvoid LiveSession::BandwidthEstimator::addBandwidthMeasurement( 96538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang size_t numBytes, int64_t delayUs) { 97538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang AutoMutex autoLock(mLock); 98538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 995ef659e010e90175eb5282d9642a02f6105189bfChong Zhang int64_t nowUs = ALooper::GetNowUs(); 100538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang BandwidthEntry entry; 1015ef659e010e90175eb5282d9642a02f6105189bfChong Zhang entry.mTimestampUs = nowUs; 102538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang entry.mDelayUs = delayUs; 103538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang entry.mNumBytes = numBytes; 104538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mTotalTransferTimeUs += delayUs; 105538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mTotalTransferBytes += numBytes; 106538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mBandwidthHistory.push_back(entry); 107978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mHasNewSample = true; 108538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 10981636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang // Remove no more than 10% of total transfer time at a time 11081636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang // to avoid sudden jump on bandwidth estimation. There might 11181636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang // be long blocking reads that takes up signification time, 11281636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang // we have to keep a longer window in that case. 11381636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang int64_t bandwidthHistoryWindowUs = mTotalTransferTimeUs * 9 / 10; 11481636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang if (bandwidthHistoryWindowUs < kMinBandwidthHistoryWindowUs) { 11581636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang bandwidthHistoryWindowUs = kMinBandwidthHistoryWindowUs; 11681636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang } else if (bandwidthHistoryWindowUs > kMaxBandwidthHistoryWindowUs) { 11781636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang bandwidthHistoryWindowUs = kMaxBandwidthHistoryWindowUs; 11881636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang } 119538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang // trim old samples, keeping at least kMaxBandwidthHistoryItems samples, 120538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang // and total transfer time at least kMaxBandwidthHistoryWindowUs. 12181636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang while (mBandwidthHistory.size() > kMinBandwidthHistoryItems) { 122538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang List<BandwidthEntry>::iterator it = mBandwidthHistory.begin(); 1235ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // remove sample if either absolute age or total transfer time is 1245ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // over kMaxBandwidthHistoryWindowUs 1255ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (nowUs - it->mTimestampUs < kMaxBandwidthHistoryAgeUs && 1265ef659e010e90175eb5282d9642a02f6105189bfChong Zhang mTotalTransferTimeUs - it->mDelayUs < bandwidthHistoryWindowUs) { 127538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang break; 128538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang } 129538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mTotalTransferTimeUs -= it->mDelayUs; 130538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mTotalTransferBytes -= it->mNumBytes; 131538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mBandwidthHistory.erase(mBandwidthHistory.begin()); 132538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang } 133538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang} 134538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 13581636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhangbool LiveSession::BandwidthEstimator::estimateBandwidth( 1365ef659e010e90175eb5282d9642a02f6105189bfChong Zhang int32_t *bandwidthBps, bool *isStable, int32_t *shortTermBps) { 137538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang AutoMutex autoLock(mLock); 138538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 139538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang if (mBandwidthHistory.size() < 2) { 140538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang return false; 141538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang } 142538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 143978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (!mHasNewSample) { 144978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang *bandwidthBps = *(--mPrevEstimates.end()); 145978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (isStable) { 146978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang *isStable = mIsStable; 147978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 1485ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (shortTermBps) { 1495ef659e010e90175eb5282d9642a02f6105189bfChong Zhang *shortTermBps = mShortTermEstimate; 1505ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } 151978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang return true; 152978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 153978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang 154538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang *bandwidthBps = ((double)mTotalTransferBytes * 8E6 / mTotalTransferTimeUs); 155978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mPrevEstimates.push_back(*bandwidthBps); 156978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang while (mPrevEstimates.size() > 3) { 157978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mPrevEstimates.erase(mPrevEstimates.begin()); 158978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 159978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mHasNewSample = false; 160978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang 1615ef659e010e90175eb5282d9642a02f6105189bfChong Zhang int64_t totalTimeUs = 0; 1625ef659e010e90175eb5282d9642a02f6105189bfChong Zhang size_t totalBytes = 0; 1635ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (mBandwidthHistory.size() >= kShortTermBandwidthItems) { 1645ef659e010e90175eb5282d9642a02f6105189bfChong Zhang List<BandwidthEntry>::iterator it = --mBandwidthHistory.end(); 1655ef659e010e90175eb5282d9642a02f6105189bfChong Zhang for (size_t i = 0; i < kShortTermBandwidthItems; i++, it--) { 1665ef659e010e90175eb5282d9642a02f6105189bfChong Zhang totalTimeUs += it->mDelayUs; 1675ef659e010e90175eb5282d9642a02f6105189bfChong Zhang totalBytes += it->mNumBytes; 1685ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } 1695ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } 1705ef659e010e90175eb5282d9642a02f6105189bfChong Zhang mShortTermEstimate = totalTimeUs > 0 ? 1715ef659e010e90175eb5282d9642a02f6105189bfChong Zhang (totalBytes * 8E6 / totalTimeUs) : *bandwidthBps; 1725ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (shortTermBps) { 1735ef659e010e90175eb5282d9642a02f6105189bfChong Zhang *shortTermBps = mShortTermEstimate; 1745ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } 1755ef659e010e90175eb5282d9642a02f6105189bfChong Zhang 176a6ff3a8a9bd17e8a5a421b409b58b8497842ebefRobert Shih int64_t minEstimate = -1, maxEstimate = -1; 177978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang List<int32_t>::iterator it; 178978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang for (it = mPrevEstimates.begin(); it != mPrevEstimates.end(); it++) { 179978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang int32_t estimate = *it; 180978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (minEstimate < 0 || minEstimate > estimate) { 181978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang minEstimate = estimate; 182978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 183978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (maxEstimate < 0 || maxEstimate < estimate) { 184978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang maxEstimate = estimate; 185978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 186978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 1875ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // consider it stable if long-term average is not jumping a lot 1885ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // and short-term average is not much lower than long-term average 1895ef659e010e90175eb5282d9642a02f6105189bfChong Zhang mIsStable = (maxEstimate <= minEstimate * 4 / 3) 1905ef659e010e90175eb5282d9642a02f6105189bfChong Zhang && mShortTermEstimate > minEstimate * 7 / 10; 191978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (isStable) { 1925ef659e010e90175eb5282d9642a02f6105189bfChong Zhang *isStable = mIsStable; 193978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 1945ef659e010e90175eb5282d9642a02f6105189bfChong Zhang 19581636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang#if 0 19681636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang { 19781636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang char dumpStr[1024] = {0}; 19881636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang size_t itemIdx = 0; 19981636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang size_t histSize = mBandwidthHistory.size(); 20081636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang sprintf(dumpStr, "estimate bps=%d stable=%d history (n=%d): {", 20181636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang *bandwidthBps, mIsStable, histSize); 20281636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang List<BandwidthEntry>::iterator it = mBandwidthHistory.begin(); 20381636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang for (; it != mBandwidthHistory.end(); ++it) { 20481636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang if (itemIdx > 50) { 20581636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang sprintf(dumpStr + strlen(dumpStr), 20681636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang "...(%zd more items)... }", histSize - itemIdx); 20781636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang break; 20881636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang } 20981636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang sprintf(dumpStr + strlen(dumpStr), "%dk/%.3fs%s", 21081636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang it->mNumBytes / 1024, 21181636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang (double)it->mDelayUs * 1.0e-6, 21281636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang (it == (--mBandwidthHistory.end())) ? "}" : ", "); 21381636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang itemIdx++; 21481636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang } 21581636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang ALOGE(dumpStr); 21681636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang } 21781636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang#endif 218538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang return true; 219538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang} 220538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 2217c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang//static 2227c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangconst char *LiveSession::getKeyForStream(StreamType type) { 2237c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang switch (type) { 2247c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang case STREAMTYPE_VIDEO: 2257c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return "timeUsVideo"; 2267c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang case STREAMTYPE_AUDIO: 2277c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return "timeUsAudio"; 2287c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang case STREAMTYPE_SUBTITLES: 2297c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return "timeUsSubtitle"; 2300852843d304006e3ab333081fddda13b07193de8Robert Shih case STREAMTYPE_METADATA: 2310852843d304006e3ab333081fddda13b07193de8Robert Shih return "timeUsMetadata"; // unused 2327c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang default: 2337c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang TRESPASS(); 2347c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 2357c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return NULL; 2367c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang} 2377c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 23825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang//static 23925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhangconst char *LiveSession::getNameForStream(StreamType type) { 24025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang switch (type) { 24125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang case STREAMTYPE_VIDEO: 24225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang return "video"; 24325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang case STREAMTYPE_AUDIO: 24425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang return "audio"; 24525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang case STREAMTYPE_SUBTITLES: 24625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang return "subs"; 2470852843d304006e3ab333081fddda13b07193de8Robert Shih case STREAMTYPE_METADATA: 2480852843d304006e3ab333081fddda13b07193de8Robert Shih return "metadata"; 24925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang default: 25025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang break; 25125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang } 25225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang return "unknown"; 25325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang} 25425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 2550852843d304006e3ab333081fddda13b07193de8Robert Shih//static 2560852843d304006e3ab333081fddda13b07193de8Robert ShihATSParser::SourceType LiveSession::getSourceTypeForStream(StreamType type) { 2570852843d304006e3ab333081fddda13b07193de8Robert Shih switch (type) { 2580852843d304006e3ab333081fddda13b07193de8Robert Shih case STREAMTYPE_VIDEO: 2590852843d304006e3ab333081fddda13b07193de8Robert Shih return ATSParser::VIDEO; 2600852843d304006e3ab333081fddda13b07193de8Robert Shih case STREAMTYPE_AUDIO: 2610852843d304006e3ab333081fddda13b07193de8Robert Shih return ATSParser::AUDIO; 2620852843d304006e3ab333081fddda13b07193de8Robert Shih case STREAMTYPE_METADATA: 2630852843d304006e3ab333081fddda13b07193de8Robert Shih return ATSParser::META; 2640852843d304006e3ab333081fddda13b07193de8Robert Shih case STREAMTYPE_SUBTITLES: 2650852843d304006e3ab333081fddda13b07193de8Robert Shih default: 2660852843d304006e3ab333081fddda13b07193de8Robert Shih TRESPASS(); 2670852843d304006e3ab333081fddda13b07193de8Robert Shih } 2680852843d304006e3ab333081fddda13b07193de8Robert Shih return ATSParser::NUM_SOURCE_TYPES; // should not reach here 2690852843d304006e3ab333081fddda13b07193de8Robert Shih} 2700852843d304006e3ab333081fddda13b07193de8Robert Shih 2710df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas HuberLiveSession::LiveSession( 2721b86fe063badb5f28c467ade39be0f4008688947Andreas Huber const sp<AMessage> ¬ify, uint32_t flags, 27381e68448f3361eaf8618930471fdc3c21bdf5cbcAndreas Huber const sp<IMediaHTTPService> &httpService) 2740df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas Huber : mNotify(notify), 2750df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas Huber mFlags(flags), 2761b86fe063badb5f28c467ade39be0f4008688947Andreas Huber mHTTPService(httpService), 2777c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mBuffering(false), 2780df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas Huber mInPreparationPhase(true), 2797c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mPollBufferingGeneration(0), 2807c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mPrevBufferPercentage(-1), 281309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mCurBandwidthIndex(-1), 2827c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mOrigBandwidthIndex(-1), 283a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mLastBandwidthBps(-1ll), 2845ef659e010e90175eb5282d9642a02f6105189bfChong Zhang mLastBandwidthStable(false), 285538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mBandwidthEstimator(new BandwidthEstimator()), 286a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang mMaxWidth(720), 287a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang mMaxHeight(480), 28814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mStreamMask(0), 2891543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih mNewStreamMask(0), 2901543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih mSwapMask(0), 2911543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih mSwitchGeneration(0), 292b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih mSubtitleGeneration(0), 29314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mLastDequeuedTimeUs(0ll), 294dcb89b3b505522efde173c105a851c412f947178Chong Zhang mRealTimeBaseUs(0ll), 29514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mReconfigurationInProgress(false), 2961543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih mSwitchInProgress(false), 297765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang mUpSwitchMark(kUpSwitchMarkUs), 298765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang mDownSwitchMark(kDownSwitchMarkUs), 299765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang mUpSwitchMargin(kUpSwitchMarginUs), 300309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mFirstTimeUsValid(false), 301309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mFirstTimeUs(0), 3020852843d304006e3ab333081fddda13b07193de8Robert Shih mLastSeekTimeUs(0), 3030852843d304006e3ab333081fddda13b07193de8Robert Shih mHasMetadata(false) { 3048ca002eedc747dd854b61cbe364b52c06869273fRobert Shih mStreams[kAudioIndex] = StreamItem("audio"); 3058ca002eedc747dd854b61cbe364b52c06869273fRobert Shih mStreams[kVideoIndex] = StreamItem("video"); 306e4f25c280a8f1655c31a745978e0fcbc61f91deeRobert Shih mStreams[kSubtitleIndex] = StreamItem("subtitles"); 30714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 3080852843d304006e3ab333081fddda13b07193de8Robert Shih for (size_t i = 0; i < kNumSources; ++i) { 3098ca002eedc747dd854b61cbe364b52c06869273fRobert Shih mPacketSources.add(indexToType(i), new AnotherPacketSource(NULL /* meta */)); 3101543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih mPacketSources2.add(indexToType(i), new AnotherPacketSource(NULL /* meta */)); 3118ca002eedc747dd854b61cbe364b52c06869273fRobert Shih } 312a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 313a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 314a44153c1a57202fb538659eb50706e60454d6273Andreas HuberLiveSession::~LiveSession() { 315964adb17885185808398507d2de88665fe193ee2Chong Zhang if (mFetcherLooper != NULL) { 316964adb17885185808398507d2de88665fe193ee2Chong Zhang mFetcherLooper->stop(); 317964adb17885185808398507d2de88665fe193ee2Chong Zhang } 318a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 319a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 3200852843d304006e3ab333081fddda13b07193de8Robert Shihint64_t LiveSession::calculateMediaTimeUs( 3210852843d304006e3ab333081fddda13b07193de8Robert Shih int64_t firstTimeUs, int64_t timeUs, int32_t discontinuitySeq) { 3220852843d304006e3ab333081fddda13b07193de8Robert Shih if (timeUs >= firstTimeUs) { 3230852843d304006e3ab333081fddda13b07193de8Robert Shih timeUs -= firstTimeUs; 3240852843d304006e3ab333081fddda13b07193de8Robert Shih } else { 3250852843d304006e3ab333081fddda13b07193de8Robert Shih timeUs = 0; 3260852843d304006e3ab333081fddda13b07193de8Robert Shih } 3270852843d304006e3ab333081fddda13b07193de8Robert Shih timeUs += mLastSeekTimeUs; 3280852843d304006e3ab333081fddda13b07193de8Robert Shih if (mDiscontinuityOffsetTimesUs.indexOfKey(discontinuitySeq) >= 0) { 3290852843d304006e3ab333081fddda13b07193de8Robert Shih timeUs += mDiscontinuityOffsetTimesUs.valueFor(discontinuitySeq); 3300852843d304006e3ab333081fddda13b07193de8Robert Shih } 3310852843d304006e3ab333081fddda13b07193de8Robert Shih return timeUs; 3320852843d304006e3ab333081fddda13b07193de8Robert Shih} 3330852843d304006e3ab333081fddda13b07193de8Robert Shih 33414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::dequeueAccessUnit( 33514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber StreamType stream, sp<ABuffer> *accessUnit) { 336964adb17885185808398507d2de88665fe193ee2Chong Zhang status_t finalResult = OK; 33714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AnotherPacketSource> packetSource = mPacketSources.valueFor(stream); 33814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 33925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ssize_t streamIdx = typeToIndex(stream); 34025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang if (streamIdx < 0) { 3415abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang return BAD_VALUE; 34225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang } 34325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang const char *streamStr = getNameForStream(stream); 344a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // Do not let client pull data if we don't have data packets yet. 345a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // We might only have a format discontinuity queued without data. 346a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // When NuPlayerDecoder dequeues the format discontinuity, it will 347a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // immediately try to getFormat. If we return NULL, NuPlayerDecoder 348a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // thinks it can do seamless change, so will not shutdown decoder. 349a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // When the actual format arrives, it can't handle it and get stuck. 350a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (!packetSource->hasDataBufferAvailable(&finalResult)) { 35125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("[%s] dequeueAccessUnit: no buffer available (finalResult=%d)", 35225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang streamStr, finalResult); 35325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 354f69c996864844e8f669308af8412cede043062a2Robert Shih if (finalResult == OK) { 355f69c996864844e8f669308af8412cede043062a2Robert Shih return -EAGAIN; 356f69c996864844e8f669308af8412cede043062a2Robert Shih } else { 357f69c996864844e8f669308af8412cede043062a2Robert Shih return finalResult; 358f69c996864844e8f669308af8412cede043062a2Robert Shih } 359f69c996864844e8f669308af8412cede043062a2Robert Shih } 360f69c996864844e8f669308af8412cede043062a2Robert Shih 361a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // Let the client dequeue as long as we have buffers available 362a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // Do not make pause/resume decisions here. 363309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 36414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber status_t err = packetSource->dequeueAccessUnit(accessUnit); 36514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 36614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (err == INFO_DISCONTINUITY) { 367309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih // adaptive streaming, discontinuities in the playlist 36814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int32_t type; 36914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK((*accessUnit)->meta()->findInt32("discontinuity", &type)); 37014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 37114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AMessage> extra; 37214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (!(*accessUnit)->meta()->findMessage("extra", &extra)) { 37314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber extra.clear(); 37414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 37514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 37614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGI("[%s] read discontinuity of type %d, extra = %s", 37714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber streamStr, 37814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber type, 37914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber extra == NULL ? "NULL" : extra->debugString().c_str()); 38014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else if (err == OK) { 381309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 382dcb89b3b505522efde173c105a851c412f947178Chong Zhang if (stream == STREAMTYPE_AUDIO || stream == STREAMTYPE_VIDEO) { 38325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang int64_t timeUs, originalTimeUs; 384309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih int32_t discontinuitySeq = 0; 3850852843d304006e3ab333081fddda13b07193de8Robert Shih StreamItem& strm = mStreams[streamIdx]; 386dcb89b3b505522efde173c105a851c412f947178Chong Zhang CHECK((*accessUnit)->meta()->findInt64("timeUs", &timeUs)); 38725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang originalTimeUs = timeUs; 388309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih (*accessUnit)->meta()->findInt32("discontinuitySeq", &discontinuitySeq); 3897c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (discontinuitySeq > (int32_t) strm.mCurDiscontinuitySeq) { 3907c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang int64_t offsetTimeUs; 3917c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (mDiscontinuityOffsetTimesUs.indexOfKey(strm.mCurDiscontinuitySeq) >= 0) { 3927c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang offsetTimeUs = mDiscontinuityOffsetTimesUs.valueFor(strm.mCurDiscontinuitySeq); 3937c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } else { 3947c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang offsetTimeUs = 0; 3957c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 3967c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 39781636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang if (mDiscontinuityAbsStartTimesUs.indexOfKey(strm.mCurDiscontinuitySeq) >= 0 39881636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang && strm.mLastDequeuedTimeUs >= 0) { 3997c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang int64_t firstTimeUs; 4007c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang firstTimeUs = mDiscontinuityAbsStartTimesUs.valueFor(strm.mCurDiscontinuitySeq); 4017c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang offsetTimeUs += strm.mLastDequeuedTimeUs - firstTimeUs; 4027c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang offsetTimeUs += strm.mLastSampleDurationUs; 4037c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } else { 4047c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang offsetTimeUs += strm.mLastSampleDurationUs; 4057c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 4067c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 4077c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mDiscontinuityOffsetTimesUs.add(discontinuitySeq, offsetTimeUs); 4087c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang strm.mCurDiscontinuitySeq = discontinuitySeq; 4097c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 410309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 411309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih int32_t discard = 0; 412309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih int64_t firstTimeUs; 413309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (mDiscontinuityAbsStartTimesUs.indexOfKey(strm.mCurDiscontinuitySeq) >= 0) { 414309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih int64_t durUs; // approximate sample duration 415309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (timeUs > strm.mLastDequeuedTimeUs) { 416309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih durUs = timeUs - strm.mLastDequeuedTimeUs; 417309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } else { 418309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih durUs = strm.mLastDequeuedTimeUs - timeUs; 419309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 420309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih strm.mLastSampleDurationUs = durUs; 421309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih firstTimeUs = mDiscontinuityAbsStartTimesUs.valueFor(strm.mCurDiscontinuitySeq); 422309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } else if ((*accessUnit)->meta()->findInt32("discard", &discard) && discard) { 423309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih firstTimeUs = timeUs; 424309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } else { 425309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mDiscontinuityAbsStartTimesUs.add(strm.mCurDiscontinuitySeq, timeUs); 426309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih firstTimeUs = timeUs; 427309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 428309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 429309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih strm.mLastDequeuedTimeUs = timeUs; 4300852843d304006e3ab333081fddda13b07193de8Robert Shih timeUs = calculateMediaTimeUs(firstTimeUs, timeUs, discontinuitySeq); 431dcb89b3b505522efde173c105a851c412f947178Chong Zhang 43225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("[%s] dequeueAccessUnit: time %lld us, original %lld us", 43325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang streamStr, (long long)timeUs, (long long)originalTimeUs); 434309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih (*accessUnit)->meta()->setInt64("timeUs", timeUs); 435dcb89b3b505522efde173c105a851c412f947178Chong Zhang mLastDequeuedTimeUs = timeUs; 436dcb89b3b505522efde173c105a851c412f947178Chong Zhang mRealTimeBaseUs = ALooper::GetNowUs() - timeUs; 437dcb89b3b505522efde173c105a851c412f947178Chong Zhang } else if (stream == STREAMTYPE_SUBTITLES) { 438b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih int32_t subtitleGeneration; 439b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih if ((*accessUnit)->meta()->findInt32("subtitleGeneration", &subtitleGeneration) 440b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih && subtitleGeneration != mSubtitleGeneration) { 441b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih return -EAGAIN; 442b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih }; 443dcb89b3b505522efde173c105a851c412f947178Chong Zhang (*accessUnit)->meta()->setInt32( 444dcb89b3b505522efde173c105a851c412f947178Chong Zhang "trackIndex", mPlaylist->getSelectedIndex()); 445dcb89b3b505522efde173c105a851c412f947178Chong Zhang (*accessUnit)->meta()->setInt64("baseUs", mRealTimeBaseUs); 4460852843d304006e3ab333081fddda13b07193de8Robert Shih } else if (stream == STREAMTYPE_METADATA) { 4470852843d304006e3ab333081fddda13b07193de8Robert Shih HLSTime mdTime((*accessUnit)->meta()); 4480852843d304006e3ab333081fddda13b07193de8Robert Shih if (mDiscontinuityAbsStartTimesUs.indexOfKey(mdTime.mSeq) < 0) { 4490852843d304006e3ab333081fddda13b07193de8Robert Shih packetSource->requeueAccessUnit((*accessUnit)); 4500852843d304006e3ab333081fddda13b07193de8Robert Shih return -EAGAIN; 4510852843d304006e3ab333081fddda13b07193de8Robert Shih } else { 4520852843d304006e3ab333081fddda13b07193de8Robert Shih int64_t firstTimeUs = mDiscontinuityAbsStartTimesUs.valueFor(mdTime.mSeq); 4530852843d304006e3ab333081fddda13b07193de8Robert Shih int64_t timeUs = calculateMediaTimeUs(firstTimeUs, mdTime.mTimeUs, mdTime.mSeq); 4540852843d304006e3ab333081fddda13b07193de8Robert Shih (*accessUnit)->meta()->setInt64("timeUs", timeUs); 4550852843d304006e3ab333081fddda13b07193de8Robert Shih (*accessUnit)->meta()->setInt64("baseUs", mRealTimeBaseUs); 4560852843d304006e3ab333081fddda13b07193de8Robert Shih } 457dcb89b3b505522efde173c105a851c412f947178Chong Zhang } 45814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else { 45914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGI("[%s] encountered error %d", streamStr, err); 46014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 46114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 46214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return err; 46314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 46414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 465a83eebb78c3a7d57a769dac965b17a8aad7c7b8fRobert Shihstatus_t LiveSession::getStreamFormatMeta(StreamType stream, sp<MetaData> *meta) { 46614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (!(mStreamMask & stream)) { 46714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return UNKNOWN_ERROR; 46814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 46914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 47014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AnotherPacketSource> packetSource = mPacketSources.valueFor(stream); 47114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 472a83eebb78c3a7d57a769dac965b17a8aad7c7b8fRobert Shih *meta = packetSource->getFormat(); 47314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 474a83eebb78c3a7d57a769dac965b17a8aad7c7b8fRobert Shih if (*meta == NULL) { 4757350b057ca864f5dc9e53d48e34710a8e81133f8Robert Shih return -EWOULDBLOCK; 47614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 47714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 4787c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (stream == STREAMTYPE_AUDIO) { 4797c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // set AAC input buffer size to 32K bytes (256kbps x 1sec) 480a83eebb78c3a7d57a769dac965b17a8aad7c7b8fRobert Shih (*meta)->setInt32(kKeyMaxInputSize, 32 * 1024); 481a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang } else if (stream == STREAMTYPE_VIDEO) { 482a83eebb78c3a7d57a769dac965b17a8aad7c7b8fRobert Shih (*meta)->setInt32(kKeyMaxWidth, mMaxWidth); 483a83eebb78c3a7d57a769dac965b17a8aad7c7b8fRobert Shih (*meta)->setInt32(kKeyMaxHeight, mMaxHeight); 4847c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 4857c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 486a83eebb78c3a7d57a769dac965b17a8aad7c7b8fRobert Shih return OK; 487a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 488a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 4895abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhangsp<HTTPDownloader> LiveSession::getHTTPDownloader() { 4905abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang return new HTTPDownloader(mHTTPService, mExtraHeaders); 491a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang} 492a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 49348fa06d1e80a872c7495804979256e021e566ae0Wei Jiavoid LiveSession::setBufferingSettings( 49448fa06d1e80a872c7495804979256e021e566ae0Wei Jia const BufferingSettings &buffering) { 49548fa06d1e80a872c7495804979256e021e566ae0Wei Jia sp<AMessage> msg = new AMessage(kWhatSetBufferingSettings, this); 49648fa06d1e80a872c7495804979256e021e566ae0Wei Jia writeToAMessage(msg, buffering); 49748fa06d1e80a872c7495804979256e021e566ae0Wei Jia msg->post(); 49848fa06d1e80a872c7495804979256e021e566ae0Wei Jia} 49948fa06d1e80a872c7495804979256e021e566ae0Wei Jia 50014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::connectAsync( 501ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber const char *url, const KeyedVector<String8, String8> *headers) { 5021d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> msg = new AMessage(kWhatConnect, this); 503a44153c1a57202fb538659eb50706e60454d6273Andreas Huber msg->setString("url", url); 504ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber 505ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber if (headers != NULL) { 506ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber msg->setPointer( 507ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber "headers", 508ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber new KeyedVector<String8, String8>(*headers)); 509ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber } 510ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber 511a44153c1a57202fb538659eb50706e60454d6273Andreas Huber msg->post(); 512a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 513a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 51414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::disconnect() { 5151d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> msg = new AMessage(kWhatDisconnect, this); 516ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber 51714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AMessage> response; 51814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber status_t err = msg->postAndAwaitResponse(&response); 519ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber 52014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return err; 521a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 522a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 523c5de09127e9e0d5df7aa587be317e1487d793245Wei Jiastatus_t LiveSession::seekTo(int64_t timeUs, MediaPlayerSeekMode mode) { 5241d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> msg = new AMessage(kWhatSeek, this); 525a44153c1a57202fb538659eb50706e60454d6273Andreas Huber msg->setInt64("timeUs", timeUs); 526c5de09127e9e0d5df7aa587be317e1487d793245Wei Jia msg->setInt32("mode", mode); 527a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 52814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AMessage> response; 52914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber status_t err = msg->postAndAwaitResponse(&response); 53014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 53114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return err; 532a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 533a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 5347c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangbool LiveSession::checkSwitchProgress( 5357c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AMessage> &stopParams, int64_t delayUs, bool *needResumeUntil) { 5367c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang AString newUri; 5377c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang CHECK(stopParams->findString("uri", &newUri)); 5387c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 5397c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang *needResumeUntil = false; 5407c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AMessage> firstNewMeta[kMaxStreams]; 5417c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang for (size_t i = 0; i < kMaxStreams; ++i) { 5427c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang StreamType stream = indexToType(i); 5437c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (!(mSwapMask & mNewStreamMask & stream) 5447c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang || (mStreams[i].mNewUri != newUri)) { 5457c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang continue; 5467c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 5477c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (stream == STREAMTYPE_SUBTITLES) { 5487c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang continue; 5497c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 5507c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AnotherPacketSource> &source = mPacketSources.editValueAt(i); 5517c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 5527c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // First, get latest dequeued meta, which is where the decoder is at. 5537c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // (when upswitching, we take the meta after a certain delay, so that 5547c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // the decoder is left with some cushion) 5557c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AMessage> lastDequeueMeta, lastEnqueueMeta; 5567c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (delayUs > 0) { 5577c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang lastDequeueMeta = source->getMetaAfterLastDequeued(delayUs); 558d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (lastDequeueMeta == NULL) { 559d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // this means we don't have enough cushion, try again later 560d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang ALOGV("[%s] up switching failed due to insufficient buffer", 56125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang getNameForStream(stream)); 562d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang return false; 563d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang } 5647c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } else { 565d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // It's okay for lastDequeueMeta to be NULL here, it means the 566d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // decoder hasn't even started dequeueing 5677c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang lastDequeueMeta = source->getLatestDequeuedMeta(); 5687c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 5697c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // Then, trim off packets at beginning of mPacketSources2 that's before 5707c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // the latest dequeued time. These samples are definitely too late. 571d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang firstNewMeta[i] = mPacketSources2.editValueAt(i) 572d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang ->trimBuffersBeforeMeta(lastDequeueMeta); 573d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang 5747c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // Now firstNewMeta[i] is the first sample after the trim. 5757c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // If it's NULL, we failed because dequeue already past all samples 5767c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // in mPacketSource2, we have to try again. 5777c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (firstNewMeta[i] == NULL) { 578d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang HLSTime dequeueTime(lastDequeueMeta); 5797c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGV("[%s] dequeue time (%d, %lld) past start time", 58025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang getNameForStream(stream), 581d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang dequeueTime.mSeq, (long long) dequeueTime.mTimeUs); 5827c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return false; 5837c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 5847c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 5857c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // Otherwise, we check if mPacketSources2 overlaps with what old fetcher 5867c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // already fetched, and see if we need to resumeUntil 5877c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang lastEnqueueMeta = source->getLatestEnqueuedMeta(); 5887c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // lastEnqueueMeta == NULL means old fetcher stopped at a discontinuity 5897c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // boundary, no need to resume as the content will look different anyways 5907c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (lastEnqueueMeta != NULL) { 591d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang HLSTime lastTime(lastEnqueueMeta), startTime(firstNewMeta[i]); 5927c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 5937c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // no need to resume old fetcher if new fetcher started in different 5947c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // discontinuity sequence, as the content will look different. 595d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang *needResumeUntil |= (startTime.mSeq == lastTime.mSeq 596d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang && startTime.mTimeUs - lastTime.mTimeUs > kResumeThresholdUs); 5977c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 598d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // update the stopTime for resumeUntil 599d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang stopParams->setInt32("discontinuitySeq", startTime.mSeq); 600d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang stopParams->setInt64(getKeyForStream(stream), startTime.mTimeUs); 6017c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 6027c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 6037c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 6047c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // if we're here, it means dequeue progress hasn't passed some samples in 6057c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // mPacketSource2, we can trim off the excess in mPacketSource. 6067c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // (old fetcher might still need to resumeUntil the start time of new fetcher) 6077c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang for (size_t i = 0; i < kMaxStreams; ++i) { 6087c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang StreamType stream = indexToType(i); 6097c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (!(mSwapMask & mNewStreamMask & stream) 610d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang || (newUri != mStreams[i].mNewUri) 611d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang || stream == STREAMTYPE_SUBTITLES) { 6127c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang continue; 6137c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 614d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang mPacketSources.valueFor(stream)->trimBuffersAfterMeta(firstNewMeta[i]); 6157c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 6167c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 6177c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // no resumeUntil if already underflow 6187c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang *needResumeUntil &= !mBuffering; 6197c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 6207c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return true; 6217c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang} 6227c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 623a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onMessageReceived(const sp<AMessage> &msg) { 624a44153c1a57202fb538659eb50706e60454d6273Andreas Huber switch (msg->what()) { 62548fa06d1e80a872c7495804979256e021e566ae0Wei Jia case kWhatSetBufferingSettings: 62648fa06d1e80a872c7495804979256e021e566ae0Wei Jia { 62748fa06d1e80a872c7495804979256e021e566ae0Wei Jia readFromAMessage(msg, &mBufferingSettings); 62848fa06d1e80a872c7495804979256e021e566ae0Wei Jia break; 62948fa06d1e80a872c7495804979256e021e566ae0Wei Jia } 63048fa06d1e80a872c7495804979256e021e566ae0Wei Jia 631a44153c1a57202fb538659eb50706e60454d6273Andreas Huber case kWhatConnect: 63214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 633a44153c1a57202fb538659eb50706e60454d6273Andreas Huber onConnect(msg); 634a44153c1a57202fb538659eb50706e60454d6273Andreas Huber break; 63514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 636a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 637a44153c1a57202fb538659eb50706e60454d6273Andreas Huber case kWhatDisconnect: 63814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 63914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->senderAwaitsResponse(&mDisconnectReplyID)); 64014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 64114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (mReconfigurationInProgress) { 64214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 64314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 64414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 64514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber finishDisconnect(); 646a44153c1a57202fb538659eb50706e60454d6273Andreas Huber break; 64714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 648a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 64914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case kWhatSeek: 65014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 651a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar if (mReconfigurationInProgress) { 652800599cdd50737de1cde483a34b39923750b0658Robert Shih msg->post(50000); 653a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar break; 654800599cdd50737de1cde483a34b39923750b0658Robert Shih } 655a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar 656a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar CHECK(msg->senderAwaitsResponse(&mSeekReplyID)); 657a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar mSeekReply = new AMessage; 658a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar 659a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar onSeek(msg); 66014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 66114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 66214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 66314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case kWhatFetcherNotify: 66414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 66514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int32_t what; 66614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->findInt32("what", &what)); 66714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 66814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber switch (what) { 66914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case PlaylistFetcher::kWhatStarted: 67014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 67114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case PlaylistFetcher::kWhatPaused: 67214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case PlaylistFetcher::kWhatStopped: 67314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 674a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang AString uri; 675a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang CHECK(msg->findString("uri", &uri)); 676a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang ssize_t index = mFetcherInfos.indexOfKey(uri); 677a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (index < 0) { 678a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // ignore msgs from fetchers that's already gone 679a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang break; 680a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 681a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 68225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("fetcher-%d %s", 68325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang mFetcherInfos[index].mFetcher->getFetcherID(), 68425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang what == PlaylistFetcher::kWhatPaused ? 68525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang "paused" : "stopped"); 68625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 68714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (what == PlaylistFetcher::kWhatStopped) { 688964adb17885185808398507d2de88665fe193ee2Chong Zhang mFetcherLooper->unregisterHandler( 689964adb17885185808398507d2de88665fe193ee2Chong Zhang mFetcherInfos[index].mFetcher->id()); 690964adb17885185808398507d2de88665fe193ee2Chong Zhang mFetcherInfos.removeItemsAt(index); 691a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } else if (what == PlaylistFetcher::kWhatPaused) { 692a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang int32_t seekMode; 693a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang CHECK(msg->findInt32("seekMode", &seekMode)); 694a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang for (size_t i = 0; i < kMaxStreams; ++i) { 695a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (mStreams[i].mUri == uri) { 696a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mStreams[i].mSeekMode = (SeekMode) seekMode; 697a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 698309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 69914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 70014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 70114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (mContinuation != NULL) { 70214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK_GT(mContinuationCounter, 0); 70314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (--mContinuationCounter == 0) { 70414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mContinuation->post(); 70514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 70625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("%zu fetcher(s) left", mContinuationCounter); 70714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 70814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 70914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 71014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 71114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case PlaylistFetcher::kWhatDurationUpdate: 71214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 71314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber AString uri; 71414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->findString("uri", &uri)); 71514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 71614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int64_t durationUs; 71714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->findInt64("durationUs", &durationUs)); 71814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 719964adb17885185808398507d2de88665fe193ee2Chong Zhang ssize_t index = mFetcherInfos.indexOfKey(uri); 720964adb17885185808398507d2de88665fe193ee2Chong Zhang if (index >= 0) { 721964adb17885185808398507d2de88665fe193ee2Chong Zhang FetcherInfo *info = &mFetcherInfos.editValueFor(uri); 722964adb17885185808398507d2de88665fe193ee2Chong Zhang info->mDurationUs = durationUs; 723964adb17885185808398507d2de88665fe193ee2Chong Zhang } 72414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 72514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 72614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 7277c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang case PlaylistFetcher::kWhatTargetDurationUpdate: 7287c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang { 7297c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang int64_t targetDurationUs; 7307c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang CHECK(msg->findInt64("targetDurationUs", &targetDurationUs)); 731d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang mUpSwitchMark = min(kUpSwitchMarkUs, targetDurationUs * 7 / 4); 732765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang mDownSwitchMark = min(kDownSwitchMarkUs, targetDurationUs * 9 / 4); 733765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang mUpSwitchMargin = min(kUpSwitchMarginUs, targetDurationUs); 7347c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang break; 7357c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 7367c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 73714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case PlaylistFetcher::kWhatError: 73814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 73914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber status_t err; 74014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->findInt32("err", &err)); 74114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 74214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGE("XXX Received error %d from PlaylistFetcher.", err); 74314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 74415f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih // handle EOS on subtitle tracks independently 74515f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih AString uri; 74615f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih if (err == ERROR_END_OF_STREAM && msg->findString("uri", &uri)) { 74715f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih ssize_t i = mFetcherInfos.indexOfKey(uri); 74815f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih if (i >= 0) { 74915f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih const sp<PlaylistFetcher> &fetcher = mFetcherInfos.valueAt(i).mFetcher; 75015f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih if (fetcher != NULL) { 75115f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih uint32_t type = fetcher->getStreamTypeMask(); 75215f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih if (type == STREAMTYPE_SUBTITLES) { 75315f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih mPacketSources.valueFor( 75415f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih STREAMTYPE_SUBTITLES)->signalEOS(err);; 75515f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih break; 75615f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih } 75715f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih } 75815f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih } 75915f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih } 76015f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih 7615ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // remember the failure index (as mCurBandwidthIndex will be restored 7625ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // after cancelBandwidthSwitch()), and record last fail time 7635ef659e010e90175eb5282d9642a02f6105189bfChong Zhang size_t failureIndex = mCurBandwidthIndex; 7645ef659e010e90175eb5282d9642a02f6105189bfChong Zhang mBandwidthItems.editItemAt( 7655ef659e010e90175eb5282d9642a02f6105189bfChong Zhang failureIndex).mLastFailureUs = ALooper::GetNowUs(); 7665ef659e010e90175eb5282d9642a02f6105189bfChong Zhang 7675ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (mSwitchInProgress) { 7685ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // if error happened when we switch to a variant, try fallback 7695ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // to other variant to save the session 7705ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (tryBandwidthFallback()) { 7715ef659e010e90175eb5282d9642a02f6105189bfChong Zhang break; 7725ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } 7735ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } 7745ef659e010e90175eb5282d9642a02f6105189bfChong Zhang 77514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (mInPreparationPhase) { 77614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber postPrepared(err); 77714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 77814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 7791543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih cancelBandwidthSwitch(); 7801543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 78114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mPacketSources.valueFor(STREAMTYPE_AUDIO)->signalEOS(err); 78214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 78314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mPacketSources.valueFor(STREAMTYPE_VIDEO)->signalEOS(err); 78414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 78514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mPacketSources.valueFor( 78614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber STREAMTYPE_SUBTITLES)->signalEOS(err); 78714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 7887c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang postError(err); 7897c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang break; 7907c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 7917c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 7927c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang case PlaylistFetcher::kWhatStopReached: 7937c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang { 7947c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGV("kWhatStopReached"); 7957c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 796d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang AString oldUri; 797d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang CHECK(msg->findString("uri", &oldUri)); 7987c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 799d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang ssize_t index = mFetcherInfos.indexOfKey(oldUri); 8007c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (index < 0) { 8017c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang break; 8027c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 8037c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 804d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang tryToFinishBandwidthSwitch(oldUri); 80514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 80614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 80714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 8081543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih case PlaylistFetcher::kWhatStartedAt: 8091543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih { 8101543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih int32_t switchGeneration; 8111543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih CHECK(msg->findInt32("switchGeneration", &switchGeneration)); 8121543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 81325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("kWhatStartedAt: switchGen=%d, mSwitchGen=%d", 81425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang switchGeneration, mSwitchGeneration); 81525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 8161543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih if (switchGeneration != mSwitchGeneration) { 8171543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih break; 8181543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 8191543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 820a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang AString uri; 821a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang CHECK(msg->findString("uri", &uri)); 8227c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 8237c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // mark new fetcher mToBeResumed 824a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang ssize_t index = mFetcherInfos.indexOfKey(uri); 825a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (index >= 0) { 826a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mFetcherInfos.editValueAt(index).mToBeResumed = true; 827a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 828a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 8297c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // temporarily disable packet sources to be swapped to prevent 8307c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // NuPlayerDecoder from dequeuing while we check progress 8317c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang for (size_t i = 0; i < mPacketSources.size(); ++i) { 8327c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if ((mSwapMask & mPacketSources.keyAt(i)) 8337c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang && uri == mStreams[i].mNewUri) { 8347c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mPacketSources.editValueAt(i)->enable(false); 8351543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 8361543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 8377c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang bool switchUp = (mCurBandwidthIndex > mOrigBandwidthIndex); 8387c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // If switching up, require a cushion bigger than kUnderflowMark 8397c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // to avoid buffering immediately after the switch. 8407c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // (If we don't have that cushion we'd rather cancel and try again.) 84148fa06d1e80a872c7495804979256e021e566ae0Wei Jia int64_t delayUs = 84248fa06d1e80a872c7495804979256e021e566ae0Wei Jia switchUp ? 84348fa06d1e80a872c7495804979256e021e566ae0Wei Jia (mBufferingSettings.mRebufferingWatermarkLowMs * 1000ll + 1000000ll) 84448fa06d1e80a872c7495804979256e021e566ae0Wei Jia : 0; 8457c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang bool needResumeUntil = false; 8467c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AMessage> stopParams = msg; 8477c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (checkSwitchProgress(stopParams, delayUs, &needResumeUntil)) { 8487c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // playback time hasn't passed startAt time 8497c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (!needResumeUntil) { 85025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("finish switch"); 8517c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang for (size_t i = 0; i < kMaxStreams; ++i) { 8527c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if ((mSwapMask & indexToType(i)) 8537c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang && uri == mStreams[i].mNewUri) { 8547c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // have to make a copy of mStreams[i].mUri because 8557c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // tryToFinishBandwidthSwitch is modifying mStreams[] 8567c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang AString oldURI = mStreams[i].mUri; 8577c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang tryToFinishBandwidthSwitch(oldURI); 8587c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang break; 8597c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 8607c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 8617c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } else { 8627c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // startAt time is after last enqueue time 8637c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // Resume fetcher for the original variant; the resumed fetcher should 8647c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // continue until the timestamps found in msg, which is stored by the 8657c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // new fetcher to indicate where the new variant has started buffering. 86625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("finish switch with resumeUntilAsync"); 8677c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang for (size_t i = 0; i < mFetcherInfos.size(); i++) { 8687c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang const FetcherInfo &info = mFetcherInfos.valueAt(i); 8697c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (info.mToBeRemoved) { 8707c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang info.mFetcher->resumeUntilAsync(stopParams); 8717c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 8727c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 8737c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 8747c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } else { 8757c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // playback time passed startAt time 8767c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (switchUp) { 8777c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // if switching up, cancel and retry if condition satisfies again 87825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("cancel up switch because we're too late"); 8797c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang cancelBandwidthSwitch(true /* resume */); 8807c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } else { 88125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("retry down switch at next sample"); 8827c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang resumeFetcher(uri, mSwapMask, -1, true /* newUri */); 8837c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 8847c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 8857c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // re-enable all packet sources 8867c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang for (size_t i = 0; i < mPacketSources.size(); ++i) { 8877c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mPacketSources.editValueAt(i)->enable(true); 8887c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 8897c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 8901543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih break; 8911543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 8921543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 8935abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang case PlaylistFetcher::kWhatPlaylistFetched: 8945abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang { 8955abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang onMasterPlaylistFetched(msg); 8965abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang break; 8975abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } 8985abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 8990852843d304006e3ab333081fddda13b07193de8Robert Shih case PlaylistFetcher::kWhatMetadataDetected: 9000852843d304006e3ab333081fddda13b07193de8Robert Shih { 9010852843d304006e3ab333081fddda13b07193de8Robert Shih if (!mHasMetadata) { 9020852843d304006e3ab333081fddda13b07193de8Robert Shih mHasMetadata = true; 9030852843d304006e3ab333081fddda13b07193de8Robert Shih sp<AMessage> notify = mNotify->dup(); 9040852843d304006e3ab333081fddda13b07193de8Robert Shih notify->setInt32("what", kWhatMetadataDetected); 9050852843d304006e3ab333081fddda13b07193de8Robert Shih notify->post(); 9060852843d304006e3ab333081fddda13b07193de8Robert Shih } 9070852843d304006e3ab333081fddda13b07193de8Robert Shih break; 9080852843d304006e3ab333081fddda13b07193de8Robert Shih } 9090852843d304006e3ab333081fddda13b07193de8Robert Shih 91014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber default: 91114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber TRESPASS(); 91214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 91314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 91414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 91514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 91614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 917dcb89b3b505522efde173c105a851c412f947178Chong Zhang case kWhatChangeConfiguration: 918dcb89b3b505522efde173c105a851c412f947178Chong Zhang { 919dcb89b3b505522efde173c105a851c412f947178Chong Zhang onChangeConfiguration(msg); 920dcb89b3b505522efde173c105a851c412f947178Chong Zhang break; 921dcb89b3b505522efde173c105a851c412f947178Chong Zhang } 922dcb89b3b505522efde173c105a851c412f947178Chong Zhang 92314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case kWhatChangeConfiguration2: 92414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 92514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber onChangeConfiguration2(msg); 92614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 92714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 92814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 92914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case kWhatChangeConfiguration3: 93014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 93114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber onChangeConfiguration3(msg); 93214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 93314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 93414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 935964adb17885185808398507d2de88665fe193ee2Chong Zhang case kWhatPollBuffering: 9360ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih { 937964adb17885185808398507d2de88665fe193ee2Chong Zhang int32_t generation; 938964adb17885185808398507d2de88665fe193ee2Chong Zhang CHECK(msg->findInt32("generation", &generation)); 939964adb17885185808398507d2de88665fe193ee2Chong Zhang if (generation == mPollBufferingGeneration) { 940964adb17885185808398507d2de88665fe193ee2Chong Zhang onPollBuffering(); 941964adb17885185808398507d2de88665fe193ee2Chong Zhang } 9420ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih break; 9430ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih } 9440ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih 945a44153c1a57202fb538659eb50706e60454d6273Andreas Huber default: 946a44153c1a57202fb538659eb50706e60454d6273Andreas Huber TRESPASS(); 947a44153c1a57202fb538659eb50706e60454d6273Andreas Huber break; 948a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 949a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 950a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 951a44153c1a57202fb538659eb50706e60454d6273Andreas Huber// static 9525ef659e010e90175eb5282d9642a02f6105189bfChong Zhangbool LiveSession::isBandwidthValid(const BandwidthItem &item) { 9535ef659e010e90175eb5282d9642a02f6105189bfChong Zhang static const int64_t kBlacklistWindowUs = 300 * 1000000ll; 9545ef659e010e90175eb5282d9642a02f6105189bfChong Zhang return item.mLastFailureUs < 0 9555ef659e010e90175eb5282d9642a02f6105189bfChong Zhang || ALooper::GetNowUs() - item.mLastFailureUs > kBlacklistWindowUs; 9565ef659e010e90175eb5282d9642a02f6105189bfChong Zhang} 9575ef659e010e90175eb5282d9642a02f6105189bfChong Zhang 9585ef659e010e90175eb5282d9642a02f6105189bfChong Zhang// static 959a44153c1a57202fb538659eb50706e60454d6273Andreas Huberint LiveSession::SortByBandwidth(const BandwidthItem *a, const BandwidthItem *b) { 960a44153c1a57202fb538659eb50706e60454d6273Andreas Huber if (a->mBandwidth < b->mBandwidth) { 961a44153c1a57202fb538659eb50706e60454d6273Andreas Huber return -1; 962a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } else if (a->mBandwidth == b->mBandwidth) { 963a44153c1a57202fb538659eb50706e60454d6273Andreas Huber return 0; 964a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 965a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 966a44153c1a57202fb538659eb50706e60454d6273Andreas Huber return 1; 967a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 968a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 9698ca002eedc747dd854b61cbe364b52c06869273fRobert Shih// static 9708ca002eedc747dd854b61cbe364b52c06869273fRobert ShihLiveSession::StreamType LiveSession::indexToType(int idx) { 9710852843d304006e3ab333081fddda13b07193de8Robert Shih CHECK(idx >= 0 && idx < kNumSources); 9728ca002eedc747dd854b61cbe364b52c06869273fRobert Shih return (StreamType)(1 << idx); 9738ca002eedc747dd854b61cbe364b52c06869273fRobert Shih} 9748ca002eedc747dd854b61cbe364b52c06869273fRobert Shih 975f69c996864844e8f669308af8412cede043062a2Robert Shih// static 976f69c996864844e8f669308af8412cede043062a2Robert Shihssize_t LiveSession::typeToIndex(int32_t type) { 977f69c996864844e8f669308af8412cede043062a2Robert Shih switch (type) { 978f69c996864844e8f669308af8412cede043062a2Robert Shih case STREAMTYPE_AUDIO: 979f69c996864844e8f669308af8412cede043062a2Robert Shih return 0; 980f69c996864844e8f669308af8412cede043062a2Robert Shih case STREAMTYPE_VIDEO: 981f69c996864844e8f669308af8412cede043062a2Robert Shih return 1; 982f69c996864844e8f669308af8412cede043062a2Robert Shih case STREAMTYPE_SUBTITLES: 983f69c996864844e8f669308af8412cede043062a2Robert Shih return 2; 9840852843d304006e3ab333081fddda13b07193de8Robert Shih case STREAMTYPE_METADATA: 9850852843d304006e3ab333081fddda13b07193de8Robert Shih return 3; 986f69c996864844e8f669308af8412cede043062a2Robert Shih default: 987f69c996864844e8f669308af8412cede043062a2Robert Shih return -1; 988f69c996864844e8f669308af8412cede043062a2Robert Shih }; 989f69c996864844e8f669308af8412cede043062a2Robert Shih return -1; 990f69c996864844e8f669308af8412cede043062a2Robert Shih} 991f69c996864844e8f669308af8412cede043062a2Robert Shih 992a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onConnect(const sp<AMessage> &msg) { 9935abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang CHECK(msg->findString("url", &mMasterURL)); 9945abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 9955abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // TODO currently we don't know if we are coming here from incognito mode 9965abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang ALOGI("onConnect %s", uriDebugString(mMasterURL).c_str()); 997a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 998ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber KeyedVector<String8, String8> *headers = NULL; 999ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber if (!msg->findPointer("headers", (void **)&headers)) { 1000ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber mExtraHeaders.clear(); 1001ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber } else { 1002ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber mExtraHeaders = *headers; 1003ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber 1004ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber delete headers; 1005ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber headers = NULL; 1006ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber } 1007ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber 1008964adb17885185808398507d2de88665fe193ee2Chong Zhang // create looper for fetchers 1009964adb17885185808398507d2de88665fe193ee2Chong Zhang if (mFetcherLooper == NULL) { 1010964adb17885185808398507d2de88665fe193ee2Chong Zhang mFetcherLooper = new ALooper(); 1011964adb17885185808398507d2de88665fe193ee2Chong Zhang 1012964adb17885185808398507d2de88665fe193ee2Chong Zhang mFetcherLooper->setName("Fetcher"); 1013964adb17885185808398507d2de88665fe193ee2Chong Zhang mFetcherLooper->start(false, false); 1014964adb17885185808398507d2de88665fe193ee2Chong Zhang } 1015964adb17885185808398507d2de88665fe193ee2Chong Zhang 10165abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // create fetcher to fetch the master playlist 10175abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang addFetcher(mMasterURL.c_str())->fetchPlaylistAsync(); 10185abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang} 10195abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 10205abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhangvoid LiveSession::onMasterPlaylistFetched(const sp<AMessage> &msg) { 10215abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang AString uri; 10225abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang CHECK(msg->findString("uri", &uri)); 10235abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang ssize_t index = mFetcherInfos.indexOfKey(uri); 10245abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang if (index < 0) { 10255abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang ALOGW("fetcher for master playlist is gone."); 10265abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang return; 10275abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } 10285abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 10295abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // no longer useful, remove 10305abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang mFetcherLooper->unregisterHandler(mFetcherInfos[index].mFetcher->id()); 10315abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang mFetcherInfos.removeItemsAt(index); 10325abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 10335abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang CHECK(msg->findObject("playlist", (sp<RefBase> *)&mPlaylist)); 10345abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang if (mPlaylist == NULL) { 10355abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang ALOGE("unable to fetch master playlist %s.", 10365abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang uriDebugString(mMasterURL).c_str()); 10375abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 10385abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang postPrepared(ERROR_IO); 10395abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang return; 10405abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } 104114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // We trust the content provider to make a reasonable choice of preferred 104214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // initial bandwidth by listing it first in the variant playlist. 104314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // At startup we really don't have a good estimate on the available 104414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // network bandwidth since we haven't tranferred any data yet. Once 104514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // we have we can make a better informed choice. 104614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber size_t initialBandwidth = 0; 104714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber size_t initialBandwidthIndex = 0; 104814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 1049a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang int32_t maxWidth = 0; 1050a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang int32_t maxHeight = 0; 1051a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang 105214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (mPlaylist->isVariantPlaylist()) { 1053d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang Vector<BandwidthItem> itemsWithVideo; 105414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber for (size_t i = 0; i < mPlaylist->size(); ++i) { 1055a44153c1a57202fb538659eb50706e60454d6273Andreas Huber BandwidthItem item; 1056a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 105714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber item.mPlaylistIndex = i; 10585ef659e010e90175eb5282d9642a02f6105189bfChong Zhang item.mLastFailureUs = -1ll; 105914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 1060a44153c1a57202fb538659eb50706e60454d6273Andreas Huber sp<AMessage> meta; 106114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber AString uri; 106214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mPlaylist->itemAt(i, &uri, &meta); 1063a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1064a44153c1a57202fb538659eb50706e60454d6273Andreas Huber CHECK(meta->findInt32("bandwidth", (int32_t *)&item.mBandwidth)); 1065a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1066a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang int32_t width, height; 1067a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang if (meta->findInt32("width", &width)) { 1068a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang maxWidth = max(maxWidth, width); 1069a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang } 1070a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang if (meta->findInt32("height", &height)) { 1071a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang maxHeight = max(maxHeight, height); 1072a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang } 1073a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang 1074a44153c1a57202fb538659eb50706e60454d6273Andreas Huber mBandwidthItems.push(item); 1075d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (mPlaylist->hasType(i, "video")) { 1076d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang itemsWithVideo.push(item); 1077d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang } 1078d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang } 1079d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // remove the audio-only variants if we have at least one with video 1080d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (!itemsWithVideo.empty() 1081d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang && itemsWithVideo.size() < mBandwidthItems.size()) { 1082d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang mBandwidthItems.clear(); 1083d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang for (size_t i = 0; i < itemsWithVideo.size(); ++i) { 1084d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang mBandwidthItems.push(itemsWithVideo[i]); 1085d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang } 1086a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1087a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1088a44153c1a57202fb538659eb50706e60454d6273Andreas Huber CHECK_GT(mBandwidthItems.size(), 0u); 1089d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang initialBandwidth = mBandwidthItems[0].mBandwidth; 1090a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1091a44153c1a57202fb538659eb50706e60454d6273Andreas Huber mBandwidthItems.sort(SortByBandwidth); 109214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 109314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber for (size_t i = 0; i < mBandwidthItems.size(); ++i) { 109414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (mBandwidthItems.itemAt(i).mBandwidth == initialBandwidth) { 109514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber initialBandwidthIndex = i; 109614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 109714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 109814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 109914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else { 110014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // dummy item. 110114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber BandwidthItem item; 110214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber item.mPlaylistIndex = 0; 110314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber item.mBandwidth = 0; 110414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mBandwidthItems.push(item); 1105a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1106a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1107a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang mMaxWidth = maxWidth > 0 ? maxWidth : mMaxWidth; 1108a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang mMaxHeight = maxHeight > 0 ? maxHeight : mMaxHeight; 1109a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang 1110309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mPlaylist->pickRandomMediaItems(); 1111dcb89b3b505522efde173c105a851c412f947178Chong Zhang changeConfiguration( 1112309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 0ll /* timeUs */, initialBandwidthIndex, false /* pickTrack */); 1113a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 1114a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 111514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::finishDisconnect() { 1116a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang ALOGV("finishDisconnect"); 1117a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 111814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // No reconfiguration is currently pending, make sure none will trigger 111914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // during disconnection either. 11201543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih cancelBandwidthSwitch(); 11211543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 1122964adb17885185808398507d2de88665fe193ee2Chong Zhang // cancel buffer polling 1123964adb17885185808398507d2de88665fe193ee2Chong Zhang cancelPollBuffering(); 11240ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih 11255abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // TRICKY: don't wait for all fetcher to be stopped when disconnecting 11265abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // 11275abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // Some fetchers might be stuck in connect/getSize at this point. These 11285abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // operations will eventually timeout (as we have a timeout set in 11295abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // MediaHTTPConnection), but we don't want to block the main UI thread 11305abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // until then. Here we just need to make sure we clear all references 11315abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // to the fetchers, so that when they finally exit from the blocking 11325abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // operation, they can be destructed. 11335abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // 11345abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // There is one very tricky point though. For this scheme to work, the 11355abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // fecther must hold a reference to LiveSession, so that LiveSession is 11365abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // destroyed after fetcher. Otherwise LiveSession would get stuck in its 11375abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // own destructor when it waits for mFetcherLooper to stop, which still 11385abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // blocks main UI thread. 113914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber for (size_t i = 0; i < mFetcherInfos.size(); ++i) { 114014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mFetcherInfos.valueAt(i).mFetcher->stopAsync(); 11415abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang mFetcherLooper->unregisterHandler( 11425abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang mFetcherInfos.valueAt(i).mFetcher->id()); 114314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 11445abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang mFetcherInfos.clear(); 114514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 114614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mPacketSources.valueFor(STREAMTYPE_AUDIO)->signalEOS(ERROR_END_OF_STREAM); 114714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mPacketSources.valueFor(STREAMTYPE_VIDEO)->signalEOS(ERROR_END_OF_STREAM); 114814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 114914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mPacketSources.valueFor( 115014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber STREAMTYPE_SUBTITLES)->signalEOS(ERROR_END_OF_STREAM); 115114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 115214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AMessage> response = new AMessage; 115314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber response->setInt32("err", OK); 115414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 115514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber response->postReply(mDisconnectReplyID); 1156c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang mDisconnectReplyID.clear(); 115714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 115814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 115914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubersp<PlaylistFetcher> LiveSession::addFetcher(const char *uri) { 116014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ssize_t index = mFetcherInfos.indexOfKey(uri); 116114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 116214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (index >= 0) { 116314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return NULL; 116414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 116514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 11661d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> notify = new AMessage(kWhatFetcherNotify, this); 116714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->setString("uri", uri); 11681543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih notify->setInt32("switchGeneration", mSwitchGeneration); 116914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 117014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber FetcherInfo info; 117125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang info.mFetcher = new PlaylistFetcher( 117225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang notify, this, uri, mCurBandwidthIndex, mSubtitleGeneration); 117314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber info.mDurationUs = -1ll; 11741543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih info.mToBeRemoved = false; 1175a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang info.mToBeResumed = false; 1176964adb17885185808398507d2de88665fe193ee2Chong Zhang mFetcherLooper->registerHandler(info.mFetcher); 117714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 117814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mFetcherInfos.add(uri, info); 117914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 118014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return info.mFetcher; 1181a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 1182a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1183b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe#if 0 1184a44153c1a57202fb538659eb50706e60454d6273Andreas Huberstatic double uniformRand() { 1185a44153c1a57202fb538659eb50706e60454d6273Andreas Huber return (double)rand() / RAND_MAX; 1186a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 1187b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe#endif 1188a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 11890852843d304006e3ab333081fddda13b07193de8Robert Shihbool LiveSession::UriIsSameAsIndex(const AString &uri, int32_t i, bool newUri) { 119094e2db71cf1ce90f8a74632895e2766b24a80d7fMichal Piechowski ALOGV("[timed_id3] i %d UriIsSameAsIndex newUri %s, %s", i, 11910852843d304006e3ab333081fddda13b07193de8Robert Shih newUri ? "true" : "false", 11920852843d304006e3ab333081fddda13b07193de8Robert Shih newUri ? mStreams[i].mNewUri.c_str() : mStreams[i].mUri.c_str()); 11930852843d304006e3ab333081fddda13b07193de8Robert Shih return i >= 0 11940852843d304006e3ab333081fddda13b07193de8Robert Shih && ((!newUri && uri == mStreams[i].mUri) 11950852843d304006e3ab333081fddda13b07193de8Robert Shih || (newUri && uri == mStreams[i].mNewUri)); 11960852843d304006e3ab333081fddda13b07193de8Robert Shih} 11970852843d304006e3ab333081fddda13b07193de8Robert Shih 11980852843d304006e3ab333081fddda13b07193de8Robert Shihsp<AnotherPacketSource> LiveSession::getPacketSourceForStreamIndex( 11990852843d304006e3ab333081fddda13b07193de8Robert Shih size_t trackIndex, bool newUri) { 12000852843d304006e3ab333081fddda13b07193de8Robert Shih StreamType type = indexToType(trackIndex); 12010852843d304006e3ab333081fddda13b07193de8Robert Shih sp<AnotherPacketSource> source = NULL; 12020852843d304006e3ab333081fddda13b07193de8Robert Shih if (newUri) { 12030852843d304006e3ab333081fddda13b07193de8Robert Shih source = mPacketSources2.valueFor(type); 12040852843d304006e3ab333081fddda13b07193de8Robert Shih source->clear(); 12050852843d304006e3ab333081fddda13b07193de8Robert Shih } else { 12060852843d304006e3ab333081fddda13b07193de8Robert Shih source = mPacketSources.valueFor(type); 12070852843d304006e3ab333081fddda13b07193de8Robert Shih }; 12080852843d304006e3ab333081fddda13b07193de8Robert Shih return source; 12090852843d304006e3ab333081fddda13b07193de8Robert Shih} 12100852843d304006e3ab333081fddda13b07193de8Robert Shih 12110852843d304006e3ab333081fddda13b07193de8Robert Shihsp<AnotherPacketSource> LiveSession::getMetadataSource( 12120852843d304006e3ab333081fddda13b07193de8Robert Shih sp<AnotherPacketSource> sources[kNumSources], uint32_t streamMask, bool newUri) { 12130852843d304006e3ab333081fddda13b07193de8Robert Shih // todo: One case where the following strategy can fail is when audio and video 12140852843d304006e3ab333081fddda13b07193de8Robert Shih // are in separate playlists, both are transport streams, and the metadata 12150852843d304006e3ab333081fddda13b07193de8Robert Shih // is actually contained in the audio stream. 12160852843d304006e3ab333081fddda13b07193de8Robert Shih ALOGV("[timed_id3] getMetadataSourceForUri streamMask %x newUri %s", 12170852843d304006e3ab333081fddda13b07193de8Robert Shih streamMask, newUri ? "true" : "false"); 12180852843d304006e3ab333081fddda13b07193de8Robert Shih 12190852843d304006e3ab333081fddda13b07193de8Robert Shih if ((sources[kVideoIndex] != NULL) // video fetcher; or ... 12200852843d304006e3ab333081fddda13b07193de8Robert Shih || (!(streamMask & STREAMTYPE_VIDEO) && sources[kAudioIndex] != NULL)) { 12210852843d304006e3ab333081fddda13b07193de8Robert Shih // ... audio fetcher for audio only variant 12220852843d304006e3ab333081fddda13b07193de8Robert Shih return getPacketSourceForStreamIndex(kMetaDataIndex, newUri); 12230852843d304006e3ab333081fddda13b07193de8Robert Shih } 12240852843d304006e3ab333081fddda13b07193de8Robert Shih 12250852843d304006e3ab333081fddda13b07193de8Robert Shih return NULL; 12260852843d304006e3ab333081fddda13b07193de8Robert Shih} 12270852843d304006e3ab333081fddda13b07193de8Robert Shih 12287c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangbool LiveSession::resumeFetcher( 12297c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang const AString &uri, uint32_t streamMask, int64_t timeUs, bool newUri) { 12307c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ssize_t index = mFetcherInfos.indexOfKey(uri); 12317c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (index < 0) { 12327c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGE("did not find fetcher for uri: %s", uri.c_str()); 12337c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return false; 12347c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 12357c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 12367c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang bool resume = false; 12370852843d304006e3ab333081fddda13b07193de8Robert Shih sp<AnotherPacketSource> sources[kNumSources]; 12387c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang for (size_t i = 0; i < kMaxStreams; ++i) { 12390852843d304006e3ab333081fddda13b07193de8Robert Shih if ((streamMask & indexToType(i)) && UriIsSameAsIndex(uri, i, newUri)) { 12407c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang resume = true; 12410852843d304006e3ab333081fddda13b07193de8Robert Shih sources[i] = getPacketSourceForStreamIndex(i, newUri); 12427c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 12437c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 12447c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 12457c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (resume) { 124625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang sp<PlaylistFetcher> &fetcher = mFetcherInfos.editValueAt(index).mFetcher; 12477c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang SeekMode seekMode = newUri ? kSeekModeNextSample : kSeekModeExactPosition; 124825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 124925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("resuming fetcher-%d, timeUs=%lld, seekMode=%d", 125025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang fetcher->getFetcherID(), (long long)timeUs, seekMode); 125125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 125225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang fetcher->startAsync( 12537c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sources[kAudioIndex], 12547c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sources[kVideoIndex], 12557c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sources[kSubtitleIndex], 12560852843d304006e3ab333081fddda13b07193de8Robert Shih getMetadataSource(sources, streamMask, newUri), 12577c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang timeUs, -1, -1, seekMode); 12587c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 12597c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 12607c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return resume; 12617c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang} 12627c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 1263a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhangfloat LiveSession::getAbortThreshold( 1264a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang ssize_t currentBWIndex, ssize_t targetBWIndex) const { 1265a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang float abortThreshold = -1.0f; 1266a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (currentBWIndex > 0 && targetBWIndex < currentBWIndex) { 1267a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang /* 1268a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang If we're switching down, we need to decide whether to 1269a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1270a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1) finish last segment of high-bandwidth variant, or 1271a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 2) abort last segment of high-bandwidth variant, and fetch an 1272a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang overlapping portion from low-bandwidth variant. 1273a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1274a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang Here we try to maximize the amount of buffer left when the 1275a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang switch point is met. Given the following parameters: 1276a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1277a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang B: our current buffering level in seconds 1278a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang T: target duration in seconds 1279a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang X: sample duration in seconds remain to fetch in last segment 1280a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang bw0: bandwidth of old variant (as specified in playlist) 1281a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang bw1: bandwidth of new variant (as specified in playlist) 1282a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang bw: measured bandwidth available 1283a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1284a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang If we choose 1), when switch happens at the end of current 1285a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang segment, our buffering will be 1286a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang B + X - X * bw0 / bw 1287a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1288a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang If we choose 2), when switch happens where we aborted current 1289a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang segment, our buffering will be 1290a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang B - (T - X) * bw1 / bw 1291a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1292a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang We should only choose 1) if 1293a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang X/T < bw1 / (bw1 + bw0 - bw) 1294a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang */ 1295a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 12965ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // abort old bandwidth immediately if bandwidth is fluctuating a lot. 12975ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // our estimate could be far off, and fetching old bandwidth could 12985ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // take too long. 12995ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (!mLastBandwidthStable) { 13005ef659e010e90175eb5282d9642a02f6105189bfChong Zhang return 0.0f; 13015ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } 13025ef659e010e90175eb5282d9642a02f6105189bfChong Zhang 13037c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // Taking the measured current bandwidth at 50% face value only, 13047c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // as our bandwidth estimation is a lagging indicator. Being 13057c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // conservative on this, we prefer switching to lower bandwidth 13067c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // unless we're really confident finishing up the last segment 13077c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // of higher bandwidth will be fast. 1308a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang CHECK(mLastBandwidthBps >= 0); 1309a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang abortThreshold = 1310a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang (float)mBandwidthItems.itemAt(targetBWIndex).mBandwidth 1311a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang / ((float)mBandwidthItems.itemAt(targetBWIndex).mBandwidth 1312a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang + (float)mBandwidthItems.itemAt(currentBWIndex).mBandwidth 13137c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang - (float)mLastBandwidthBps * 0.5f); 1314a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (abortThreshold < 0.0f) { 1315a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang abortThreshold = -1.0f; // do not abort 1316a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 1317a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang ALOGV("Switching Down: bps %ld => %ld, measured %d, abort ratio %.2f", 1318a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mBandwidthItems.itemAt(currentBWIndex).mBandwidth, 1319a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mBandwidthItems.itemAt(targetBWIndex).mBandwidth, 1320a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mLastBandwidthBps, 1321a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang abortThreshold); 1322a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 1323a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang return abortThreshold; 1324a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang} 1325a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1326538b6d22a3578c0201d48f8548289aa254d81484Chong Zhangvoid LiveSession::addBandwidthMeasurement(size_t numBytes, int64_t delayUs) { 1327538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mBandwidthEstimator->addBandwidthMeasurement(numBytes, delayUs); 1328538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang} 1329538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 13305ef659e010e90175eb5282d9642a02f6105189bfChong Zhangssize_t LiveSession::getLowestValidBandwidthIndex() const { 13315ef659e010e90175eb5282d9642a02f6105189bfChong Zhang for (size_t index = 0; index < mBandwidthItems.size(); index++) { 13325ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (isBandwidthValid(mBandwidthItems[index])) { 13335ef659e010e90175eb5282d9642a02f6105189bfChong Zhang return index; 13345ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } 13355ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } 13365ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // if playlists are all blacklisted, return 0 and hope it's alive 13375ef659e010e90175eb5282d9642a02f6105189bfChong Zhang return 0; 13385ef659e010e90175eb5282d9642a02f6105189bfChong Zhang} 13395ef659e010e90175eb5282d9642a02f6105189bfChong Zhang 1340538b6d22a3578c0201d48f8548289aa254d81484Chong Zhangsize_t LiveSession::getBandwidthIndex(int32_t bandwidthBps) { 1341538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang if (mBandwidthItems.size() < 2) { 1342538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang // shouldn't be here if we only have 1 bandwidth, check 1343538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang // logic to get rid of redundant bandwidth polling 1344538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang ALOGW("getBandwidthIndex() called for single bandwidth playlist!"); 1345a44153c1a57202fb538659eb50706e60454d6273Andreas Huber return 0; 1346a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1347a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1348a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#if 1 1349a44153c1a57202fb538659eb50706e60454d6273Andreas Huber char value[PROPERTY_VALUE_MAX]; 1350673158582c9589cee1d5e4d7c79622609938b8f8Andreas Huber ssize_t index = -1; 135114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (property_get("media.httplive.bw-index", value, NULL)) { 1352a44153c1a57202fb538659eb50706e60454d6273Andreas Huber char *end; 135314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber index = strtol(value, &end, 10); 135414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(end > value && *end == '\0'); 135514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 135614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (index >= 0 && (size_t)index >= mBandwidthItems.size()) { 135714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber index = mBandwidthItems.size() - 1; 1358a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1359a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1360a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 136114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (index < 0) { 136214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber char value[PROPERTY_VALUE_MAX]; 136314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (property_get("media.httplive.max-bw", value, NULL)) { 136414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber char *end; 136514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber long maxBw = strtoul(value, &end, 10); 136614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (end > value && *end == '\0') { 136714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (maxBw > 0 && bandwidthBps > maxBw) { 136814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGV("bandwidth capped to %ld bps", maxBw); 136914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber bandwidthBps = maxBw; 137014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 137114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 137214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 1373a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 13745ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // Pick the highest bandwidth stream that's not currently blacklisted 13755ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // below or equal to estimated bandwidth. 137614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 137714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber index = mBandwidthItems.size() - 1; 13785ef659e010e90175eb5282d9642a02f6105189bfChong Zhang ssize_t lowestBandwidth = getLowestValidBandwidthIndex(); 13795ef659e010e90175eb5282d9642a02f6105189bfChong Zhang while (index > lowestBandwidth) { 1380538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang // be conservative (70%) to avoid overestimating and immediately 1381538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang // switching down again. 1382538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang size_t adjustedBandwidthBps = bandwidthBps * 7 / 10; 13835ef659e010e90175eb5282d9642a02f6105189bfChong Zhang const BandwidthItem &item = mBandwidthItems[index]; 13845ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (item.mBandwidth <= adjustedBandwidthBps 13855ef659e010e90175eb5282d9642a02f6105189bfChong Zhang && isBandwidthValid(item)) { 138600598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih break; 138700598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih } 138814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber --index; 138914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 1390a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1391a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0 1392a44153c1a57202fb538659eb50706e60454d6273Andreas Huber // Change bandwidth at random() 1393a44153c1a57202fb538659eb50706e60454d6273Andreas Huber size_t index = uniformRand() * mBandwidthItems.size(); 1394a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0 1395a44153c1a57202fb538659eb50706e60454d6273Andreas Huber // There's a 50% chance to stay on the current bandwidth and 1396a44153c1a57202fb538659eb50706e60454d6273Andreas Huber // a 50% chance to switch to the next higher bandwidth (wrapping around 1397a44153c1a57202fb538659eb50706e60454d6273Andreas Huber // to lowest) 1398a44153c1a57202fb538659eb50706e60454d6273Andreas Huber const size_t kMinIndex = 0; 1399a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1400309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih static ssize_t mCurBandwidthIndex = -1; 140114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 1402a44153c1a57202fb538659eb50706e60454d6273Andreas Huber size_t index; 1403309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (mCurBandwidthIndex < 0) { 1404a44153c1a57202fb538659eb50706e60454d6273Andreas Huber index = kMinIndex; 1405a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } else if (uniformRand() < 0.5) { 1406309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih index = (size_t)mCurBandwidthIndex; 1407a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } else { 1408309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih index = mCurBandwidthIndex + 1; 1409a44153c1a57202fb538659eb50706e60454d6273Andreas Huber if (index == mBandwidthItems.size()) { 1410a44153c1a57202fb538659eb50706e60454d6273Andreas Huber index = kMinIndex; 1411a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1412a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1413309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mCurBandwidthIndex = index; 1414a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0 1415a44153c1a57202fb538659eb50706e60454d6273Andreas Huber // Pick the highest bandwidth stream below or equal to 1.2 Mbit/sec 1416a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1417a44153c1a57202fb538659eb50706e60454d6273Andreas Huber size_t index = mBandwidthItems.size() - 1; 1418a44153c1a57202fb538659eb50706e60454d6273Andreas Huber while (index > 0 && mBandwidthItems.itemAt(index).mBandwidth > 1200000) { 1419a44153c1a57202fb538659eb50706e60454d6273Andreas Huber --index; 1420a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 142114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#elif 1 142214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber char value[PROPERTY_VALUE_MAX]; 142314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber size_t index; 142414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (property_get("media.httplive.bw-index", value, NULL)) { 142514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber char *end; 142614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber index = strtoul(value, &end, 10); 142714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(end > value && *end == '\0'); 142814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 142914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (index >= mBandwidthItems.size()) { 143014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber index = mBandwidthItems.size() - 1; 143114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 143214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else { 143314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber index = 0; 143414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 1435a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#else 1436a44153c1a57202fb538659eb50706e60454d6273Andreas Huber size_t index = mBandwidthItems.size() - 1; // Highest bandwidth stream 1437a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#endif 1438a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 143914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK_GE(index, 0); 144014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 1441a44153c1a57202fb538659eb50706e60454d6273Andreas Huber return index; 1442a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 1443a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1444d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong ZhangHLSTime LiveSession::latestMediaSegmentStartTime() const { 1445d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang HLSTime audioTime(mPacketSources.valueFor( 1446d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang STREAMTYPE_AUDIO)->getLatestDequeuedMeta()); 1447b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih 1448d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang HLSTime videoTime(mPacketSources.valueFor( 1449d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang STREAMTYPE_VIDEO)->getLatestDequeuedMeta()); 1450b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih 1451d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang return audioTime < videoTime ? videoTime : audioTime; 1452b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih} 1453b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih 1454a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnarvoid LiveSession::onSeek(const sp<AMessage> &msg) { 145514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int64_t timeUs; 1456c5de09127e9e0d5df7aa587be317e1487d793245Wei Jia int32_t mode; 145714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->findInt64("timeUs", &timeUs)); 1458c5de09127e9e0d5df7aa587be317e1487d793245Wei Jia CHECK(msg->findInt32("mode", &mode)); 1459c5de09127e9e0d5df7aa587be317e1487d793245Wei Jia // TODO: add "mode" to changeConfiguration. 1460c5de09127e9e0d5df7aa587be317e1487d793245Wei Jia changeConfiguration(timeUs/* , (MediaPlayerSeekMode)mode */); 14617e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber} 14627e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber 146314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::getDuration(int64_t *durationUs) const { 1464895651b07fec30b0f9b0d2499599a179d95c9be4Wei Jia int64_t maxDurationUs = -1ll; 146514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber for (size_t i = 0; i < mFetcherInfos.size(); ++i) { 146614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int64_t fetcherDurationUs = mFetcherInfos.valueAt(i).mDurationUs; 1467b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber 1468895651b07fec30b0f9b0d2499599a179d95c9be4Wei Jia if (fetcherDurationUs > maxDurationUs) { 146914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber maxDurationUs = fetcherDurationUs; 1470a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1471a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1472a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 147314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber *durationUs = maxDurationUs; 1474a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 147514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return OK; 147614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 14770f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber 147814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberbool LiveSession::isSeekable() const { 147914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int64_t durationUs; 148014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return getDuration(&durationUs) == OK && durationUs >= 0; 148114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 14820f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber 148314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberbool LiveSession::hasDynamicDuration() const { 148414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return false; 148514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 14860f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber 1487404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhangsize_t LiveSession::getTrackCount() const { 14889d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih if (mPlaylist == NULL) { 14899d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih return 0; 14909d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih } else { 14910852843d304006e3ab333081fddda13b07193de8Robert Shih return mPlaylist->getTrackCount() + (mHasMetadata ? 1 : 0); 14929d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih } 1493404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang} 1494404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang 1495404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhangsp<AMessage> LiveSession::getTrackInfo(size_t trackIndex) const { 14969d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih if (mPlaylist == NULL) { 14979d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih return NULL; 14989d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih } else { 14990852843d304006e3ab333081fddda13b07193de8Robert Shih if (trackIndex == mPlaylist->getTrackCount() && mHasMetadata) { 15000852843d304006e3ab333081fddda13b07193de8Robert Shih sp<AMessage> format = new AMessage(); 15010852843d304006e3ab333081fddda13b07193de8Robert Shih format->setInt32("type", MEDIA_TRACK_TYPE_METADATA); 15020852843d304006e3ab333081fddda13b07193de8Robert Shih format->setString("language", "und"); 15036f9c5e26c710dbee50e57316f1c460dda4850fa5Robert Shih format->setString("mime", MEDIA_MIMETYPE_DATA_TIMED_ID3); 15040852843d304006e3ab333081fddda13b07193de8Robert Shih return format; 15050852843d304006e3ab333081fddda13b07193de8Robert Shih } 15069d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih return mPlaylist->getTrackInfo(trackIndex); 15079d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih } 1508dcb89b3b505522efde173c105a851c412f947178Chong Zhang} 1509dcb89b3b505522efde173c105a851c412f947178Chong Zhang 1510dcb89b3b505522efde173c105a851c412f947178Chong Zhangstatus_t LiveSession::selectTrack(size_t index, bool select) { 1511b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih if (mPlaylist == NULL) { 1512b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih return INVALID_OPERATION; 1513b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih } 1514b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih 151525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("selectTrack: index=%zu, select=%d, mSubtitleGen=%d++", 151625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang index, select, mSubtitleGeneration); 151725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 1518b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih ++mSubtitleGeneration; 1519dcb89b3b505522efde173c105a851c412f947178Chong Zhang status_t err = mPlaylist->selectTrack(index, select); 1520dcb89b3b505522efde173c105a851c412f947178Chong Zhang if (err == OK) { 15211d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> msg = new AMessage(kWhatChangeConfiguration, this); 1522309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih msg->setInt32("pickTrack", select); 1523309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih msg->post(); 1524dcb89b3b505522efde173c105a851c412f947178Chong Zhang } 1525dcb89b3b505522efde173c105a851c412f947178Chong Zhang return err; 1526dcb89b3b505522efde173c105a851c412f947178Chong Zhang} 1527dcb89b3b505522efde173c105a851c412f947178Chong Zhang 152889bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shihssize_t LiveSession::getSelectedTrack(media_track_type type) const { 152989bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih if (mPlaylist == NULL) { 153089bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih return -1; 153189bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih } else { 153289bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih return mPlaylist->getSelectedTrack(type); 153389bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih } 153489bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih} 153589bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih 1536dcb89b3b505522efde173c105a851c412f947178Chong Zhangvoid LiveSession::changeConfiguration( 15377c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang int64_t timeUs, ssize_t bandwidthIndex, bool pickTrack) { 153825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("changeConfiguration: timeUs=%lld us, bwIndex=%zd, pickTrack=%d", 153925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang (long long)timeUs, bandwidthIndex, pickTrack); 154025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 15411543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih cancelBandwidthSwitch(); 15421543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 154314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(!mReconfigurationInProgress); 154414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mReconfigurationInProgress = true; 15457c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (bandwidthIndex >= 0) { 15467c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mOrigBandwidthIndex = mCurBandwidthIndex; 15477c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mCurBandwidthIndex = bandwidthIndex; 15488464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang if (mOrigBandwidthIndex != mCurBandwidthIndex) { 15498464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang ALOGI("#### Starting Bandwidth Switch: %zd => %zd", 15508464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang mOrigBandwidthIndex, mCurBandwidthIndex); 15518464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang } 15527c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 15537c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang CHECK_LT(mCurBandwidthIndex, mBandwidthItems.size()); 15547c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang const BandwidthItem &item = mBandwidthItems.itemAt(mCurBandwidthIndex); 1555a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 15561543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih uint32_t streamMask = 0; // streams that should be fetched by the new fetcher 15571543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih uint32_t resumeMask = 0; // streams that should be fetched by the original fetcher 1558a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 15598ca002eedc747dd854b61cbe364b52c06869273fRobert Shih AString URIs[kMaxStreams]; 15608ca002eedc747dd854b61cbe364b52c06869273fRobert Shih for (size_t i = 0; i < kMaxStreams; ++i) { 15618ca002eedc747dd854b61cbe364b52c06869273fRobert Shih if (mPlaylist->getTypeURI(item.mPlaylistIndex, mStreams[i].mType, &URIs[i])) { 15628ca002eedc747dd854b61cbe364b52c06869273fRobert Shih streamMask |= indexToType(i); 15638ca002eedc747dd854b61cbe364b52c06869273fRobert Shih } 156414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 1565aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber 156614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // Step 1, stop and discard fetchers that are no longer needed. 156714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // Pause those that we'll reuse. 156814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber for (size_t i = 0; i < mFetcherInfos.size(); ++i) { 15697c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // skip fetchers that are marked mToBeRemoved, 15707c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // these are done and can't be reused 15717c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (mFetcherInfos[i].mToBeRemoved) { 15727c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang continue; 15737c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 15747c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 157514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber const AString &uri = mFetcherInfos.keyAt(i); 1576d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang sp<PlaylistFetcher> &fetcher = mFetcherInfos.editValueAt(i).mFetcher; 1577aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber 1578d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang bool discardFetcher = true, delayRemoval = false; 1579c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang for (size_t j = 0; j < kMaxStreams; ++j) { 1580c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang StreamType type = indexToType(j); 1581c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang if ((streamMask & type) && uri == URIs[j]) { 1582c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang resumeMask |= type; 1583c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang streamMask &= ~type; 1584c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang discardFetcher = false; 15856801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber } 158614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 1587d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // Delay fetcher removal if not picking tracks, AND old fetcher 1588d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // has stream mask that overlaps new variant. (Okay to discard 1589d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // old fetcher now, if completely no overlap.) 1590d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (discardFetcher && timeUs < 0ll && !pickTrack 1591d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang && (fetcher->getStreamTypeMask() & streamMask)) { 1592d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang discardFetcher = false; 1593d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang delayRemoval = true; 1594d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang } 1595a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 159614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (discardFetcher) { 159725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("discarding fetcher-%d", fetcher->getFetcherID()); 1598d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang fetcher->stopAsync(); 15996801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber } else { 16008a048338d9291b2db1b3a325fff58cb1aa69f04dChong Zhang float threshold = 0.0f; // default to pause after current block (47Kbytes) 16015abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang bool disconnect = false; 1602a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (timeUs >= 0ll) { 1603a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // seeking, no need to finish fetching 16045abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang disconnect = true; 1605d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang } else if (delayRemoval) { 1606a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // adapting, abort if remaining of current segment is over threshold 1607a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang threshold = getAbortThreshold( 16087c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mOrigBandwidthIndex, mCurBandwidthIndex); 1609a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 1610a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 161125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("pausing fetcher-%d, threshold=%.2f", 161225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang fetcher->getFetcherID(), threshold); 16135abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang fetcher->pauseAsync(threshold, disconnect); 16146801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber } 1615a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1616a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 16171543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih sp<AMessage> msg; 16181543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih if (timeUs < 0ll) { 1619309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih // skip onChangeConfiguration2 (decoder destruction) if not seeking. 16201d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar msg = new AMessage(kWhatChangeConfiguration3, this); 16211543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } else { 16221d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar msg = new AMessage(kWhatChangeConfiguration2, this); 16231543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 162414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber msg->setInt32("streamMask", streamMask); 16251543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih msg->setInt32("resumeMask", resumeMask); 1626309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih msg->setInt32("pickTrack", pickTrack); 162714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber msg->setInt64("timeUs", timeUs); 16288ca002eedc747dd854b61cbe364b52c06869273fRobert Shih for (size_t i = 0; i < kMaxStreams; ++i) { 1629309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if ((streamMask | resumeMask) & indexToType(i)) { 16308ca002eedc747dd854b61cbe364b52c06869273fRobert Shih msg->setString(mStreams[i].uriKey().c_str(), URIs[i].c_str()); 16318ca002eedc747dd854b61cbe364b52c06869273fRobert Shih } 16326e6b1cae2bac1b78205cefab8e4e9e9538982965Andreas Huber } 1633a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 163414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // Every time a fetcher acknowledges the stopAsync or pauseAsync request 163514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // we'll decrement mContinuationCounter, once it reaches zero, i.e. all 163614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // fetchers have completed their asynchronous operation, we'll post 163714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // mContinuation, which then is handled below in onChangeConfiguration2. 163814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mContinuationCounter = mFetcherInfos.size(); 163914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mContinuation = msg; 164088b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber 164114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (mContinuationCounter == 0) { 164214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber msg->post(); 164388b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber } 164414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 1645a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1646dcb89b3b505522efde173c105a851c412f947178Chong Zhangvoid LiveSession::onChangeConfiguration(const sp<AMessage> &msg) { 164725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("onChangeConfiguration"); 164825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 1649dcb89b3b505522efde173c105a851c412f947178Chong Zhang if (!mReconfigurationInProgress) { 16507c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang int32_t pickTrack = 0; 1651309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih msg->findInt32("pickTrack", &pickTrack); 16527c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang changeConfiguration(-1ll /* timeUs */, -1, pickTrack); 1653dcb89b3b505522efde173c105a851c412f947178Chong Zhang } else { 1654dcb89b3b505522efde173c105a851c412f947178Chong Zhang msg->post(1000000ll); // retry in 1 sec 1655dcb89b3b505522efde173c105a851c412f947178Chong Zhang } 1656dcb89b3b505522efde173c105a851c412f947178Chong Zhang} 1657dcb89b3b505522efde173c105a851c412f947178Chong Zhang 165814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::onChangeConfiguration2(const sp<AMessage> &msg) { 165925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("onChangeConfiguration2"); 166025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 166114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mContinuation.clear(); 1662bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber 166314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // All fetchers are either suspended or have been removed now. 1664bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber 1665964adb17885185808398507d2de88665fe193ee2Chong Zhang // If we're seeking, clear all packet sources before we report 1666964adb17885185808398507d2de88665fe193ee2Chong Zhang // seek complete, to prevent decoder from pulling stale data. 1667964adb17885185808398507d2de88665fe193ee2Chong Zhang int64_t timeUs; 1668964adb17885185808398507d2de88665fe193ee2Chong Zhang CHECK(msg->findInt64("timeUs", &timeUs)); 1669964adb17885185808398507d2de88665fe193ee2Chong Zhang 1670964adb17885185808398507d2de88665fe193ee2Chong Zhang if (timeUs >= 0) { 1671964adb17885185808398507d2de88665fe193ee2Chong Zhang mLastSeekTimeUs = timeUs; 16728464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang mLastDequeuedTimeUs = timeUs; 1673964adb17885185808398507d2de88665fe193ee2Chong Zhang 1674964adb17885185808398507d2de88665fe193ee2Chong Zhang for (size_t i = 0; i < mPacketSources.size(); i++) { 16757f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih sp<AnotherPacketSource> packetSource = mPacketSources.editValueAt(i); 16767f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih sp<MetaData> format = packetSource->getFormat(); 16777f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih packetSource->clear(); 16787f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih // Set a tentative format here such that HTTPLiveSource will always have 16797f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih // a format available when NuPlayer queries. Without an available video 16807f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih // format when setting a surface NuPlayer might disable video decoding 16817f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih // altogether. The tentative format will be overwritten by the 16827f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih // authoritative (and possibly same) format once content from the new 16837f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih // position is dequeued. 16847f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih packetSource->setFormat(format); 1685964adb17885185808398507d2de88665fe193ee2Chong Zhang } 1686964adb17885185808398507d2de88665fe193ee2Chong Zhang 16877c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang for (size_t i = 0; i < kMaxStreams; ++i) { 168881636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang mStreams[i].reset(); 16897c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 16907c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 1691964adb17885185808398507d2de88665fe193ee2Chong Zhang mDiscontinuityOffsetTimesUs.clear(); 1692964adb17885185808398507d2de88665fe193ee2Chong Zhang mDiscontinuityAbsStartTimesUs.clear(); 1693964adb17885185808398507d2de88665fe193ee2Chong Zhang 1694c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang if (mSeekReplyID != NULL) { 1695964adb17885185808398507d2de88665fe193ee2Chong Zhang CHECK(mSeekReply != NULL); 1696964adb17885185808398507d2de88665fe193ee2Chong Zhang mSeekReply->setInt32("err", OK); 1697964adb17885185808398507d2de88665fe193ee2Chong Zhang mSeekReply->postReply(mSeekReplyID); 1698c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang mSeekReplyID.clear(); 1699964adb17885185808398507d2de88665fe193ee2Chong Zhang mSeekReply.clear(); 1700964adb17885185808398507d2de88665fe193ee2Chong Zhang } 17017c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 17027c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // restart buffer polling after seek becauese previous 17037c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // buffering position is no longer valid. 17047c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang restartPollBuffering(); 1705964adb17885185808398507d2de88665fe193ee2Chong Zhang } 1706964adb17885185808398507d2de88665fe193ee2Chong Zhang 1707309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih uint32_t streamMask, resumeMask; 170814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->findInt32("streamMask", (int32_t *)&streamMask)); 1709309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih CHECK(msg->findInt32("resumeMask", (int32_t *)&resumeMask)); 1710309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 1711309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih streamMask |= resumeMask; 1712bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber 17138ca002eedc747dd854b61cbe364b52c06869273fRobert Shih AString URIs[kMaxStreams]; 17148ca002eedc747dd854b61cbe364b52c06869273fRobert Shih for (size_t i = 0; i < kMaxStreams; ++i) { 17158ca002eedc747dd854b61cbe364b52c06869273fRobert Shih if (streamMask & indexToType(i)) { 17168ca002eedc747dd854b61cbe364b52c06869273fRobert Shih const AString &uriKey = mStreams[i].uriKey(); 17178ca002eedc747dd854b61cbe364b52c06869273fRobert Shih CHECK(msg->findString(uriKey.c_str(), &URIs[i])); 17188ca002eedc747dd854b61cbe364b52c06869273fRobert Shih ALOGV("%s = '%s'", uriKey.c_str(), URIs[i].c_str()); 17198ca002eedc747dd854b61cbe364b52c06869273fRobert Shih } 172022fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber } 17213831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber 172214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber uint32_t changedMask = 0; 17238ca002eedc747dd854b61cbe364b52c06869273fRobert Shih for (size_t i = 0; i < kMaxStreams && i != kSubtitleIndex; ++i) { 1724c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // stream URI could change even if onChangeConfiguration2 is only 1725c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // used for seek. Seek could happen during a bw switch, in this 1726c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // case bw switch will be cancelled, but the seekTo position will 1727c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // fetch from the new URI. 1728c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang if ((mStreamMask & streamMask & indexToType(i)) 1729c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang && !mStreams[i].mUri.empty() 1730c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang && !(URIs[i] == mStreams[i].mUri)) { 17314604458dfe57b0e91a464aefafea50ae7b9876c1Chong Zhang ALOGV("stream %zu changed: oldURI %s, newURI %s", i, 1732c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang mStreams[i].mUri.c_str(), URIs[i].c_str()); 1733c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang sp<AnotherPacketSource> source = mPacketSources.valueFor(indexToType(i)); 17348464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang if (source->getLatestDequeuedMeta() != NULL) { 17358464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang source->queueDiscontinuity( 17368464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang ATSParser::DISCONTINUITY_FORMATCHANGE, NULL, true); 17378464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang } 1738c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang } 1739c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // Determine which decoders to shutdown on the player side, 1740c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // a decoder has to be shutdown if its streamtype was active 1741c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // before but now longer isn't. 1742c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang if ((mStreamMask & ~streamMask & indexToType(i))) { 17438ca002eedc747dd854b61cbe364b52c06869273fRobert Shih changedMask |= indexToType(i); 17448ca002eedc747dd854b61cbe364b52c06869273fRobert Shih } 1745b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber } 1746b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber 174714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (changedMask == 0) { 174814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // If nothing changed as far as the audio/video decoders 174914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // are concerned we can proceed. 175014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber onChangeConfiguration3(msg); 175114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return; 175214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 175343c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber 175414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // Something changed, inform the player which will shutdown the 175514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // corresponding decoders and will post the reply once that's done. 175614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // Handling the reply will continue executing below in 175714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // onChangeConfiguration3. 175814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AMessage> notify = mNotify->dup(); 175914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->setInt32("what", kWhatStreamsChanged); 176014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->setInt32("changedMask", changedMask); 176120f725ebcef13ded1b4b85c61c8a4b37cd030656Andreas Huber 176214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber msg->setWhat(kWhatChangeConfiguration3); 17631d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar msg->setTarget(this); 1764b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber 176514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->setMessage("reply", msg); 176614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->post(); 176714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 1768b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber 176914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::onChangeConfiguration3(const sp<AMessage> &msg) { 17701543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih mContinuation.clear(); 177114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // All remaining fetchers are still suspended, the player has shutdown 177214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // any decoders that needed it. 1773b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber 17741543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih uint32_t streamMask, resumeMask; 177514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->findInt32("streamMask", (int32_t *)&streamMask)); 17761543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih CHECK(msg->findInt32("resumeMask", (int32_t *)&resumeMask)); 1777a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1778d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang mNewStreamMask = streamMask | resumeMask; 1779d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang 178014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int64_t timeUs; 1781309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih int32_t pickTrack; 17821543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih bool switching = false; 178314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->findInt64("timeUs", &timeUs)); 1784309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih CHECK(msg->findInt32("pickTrack", &pickTrack)); 1785a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 178614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (timeUs < 0ll) { 1787309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (!pickTrack) { 1788d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // mSwapMask contains streams that are in both old and new variant, 1789d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // (in mNewStreamMask & mStreamMask) but with different URIs 1790d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // (not in resumeMask). 1791d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // For example, old variant has video and audio in two separate 1792d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // URIs, and new variant has only audio with unchanged URI. mSwapMask 1793d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // should be 0 as there is nothing to swap. We only need to stop video, 1794d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // and resume audio. 1795d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang mSwapMask = mNewStreamMask & mStreamMask & ~resumeMask; 1796d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang switching = (mSwapMask != 0); 1797309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 1798309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mRealTimeBaseUs = ALooper::GetNowUs() - mLastDequeuedTimeUs; 1799309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } else { 1800309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mRealTimeBaseUs = ALooper::GetNowUs() - timeUs; 180114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 1802a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 180325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("onChangeConfiguration3: timeUs=%lld, switching=%d, pickTrack=%d, " 180425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang "mStreamMask=0x%x, mNewStreamMask=0x%x, mSwapMask=0x%x", 180525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang (long long)timeUs, switching, pickTrack, 180625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang mStreamMask, mNewStreamMask, mSwapMask); 180725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 1808f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih for (size_t i = 0; i < kMaxStreams; ++i) { 1809f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih if (streamMask & indexToType(i)) { 1810f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih if (switching) { 1811f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih CHECK(msg->findString(mStreams[i].uriKey().c_str(), &mStreams[i].mNewUri)); 1812f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } else { 1813f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih CHECK(msg->findString(mStreams[i].uriKey().c_str(), &mStreams[i].mUri)); 1814f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 1815f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 1816f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 1817f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih 18181543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih // Of all existing fetchers: 18191543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih // * Resume fetchers that are still needed and assign them original packet sources. 18201543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih // * Mark otherwise unneeded fetchers for removal. 18211543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih ALOGV("resuming fetchers for mask 0x%08x", resumeMask); 182214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber for (size_t i = 0; i < mFetcherInfos.size(); ++i) { 182314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber const AString &uri = mFetcherInfos.keyAt(i); 18247c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (!resumeFetcher(uri, resumeMask, timeUs)) { 182525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("marking fetcher-%d to be removed", 182625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang mFetcherInfos[i].mFetcher->getFetcherID()); 182725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 18287c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mFetcherInfos.editValueAt(i).mToBeRemoved = true; 18291543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 1830a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1831a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 183214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // streamMask now only contains the types that need a new fetcher created. 183314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (streamMask != 0) { 183414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGV("creating new fetchers for mask 0x%08x", streamMask); 1835a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1836a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 18371543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih // Find out when the original fetchers have buffered up to and start the new fetchers 18381543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih // at a later timestamp. 18398ca002eedc747dd854b61cbe364b52c06869273fRobert Shih for (size_t i = 0; i < kMaxStreams; i++) { 18408ca002eedc747dd854b61cbe364b52c06869273fRobert Shih if (!(indexToType(i) & streamMask)) { 18418ca002eedc747dd854b61cbe364b52c06869273fRobert Shih continue; 18428ca002eedc747dd854b61cbe364b52c06869273fRobert Shih } 18431156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 184414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber AString uri; 1845f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih uri = switching ? mStreams[i].mNewUri : mStreams[i].mUri; 18469b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber 184714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<PlaylistFetcher> fetcher = addFetcher(uri.c_str()); 184814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(fetcher != NULL); 1849a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1850d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang HLSTime startTime; 1851a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang SeekMode seekMode = kSeekModeExactPosition; 18520852843d304006e3ab333081fddda13b07193de8Robert Shih sp<AnotherPacketSource> sources[kNumSources]; 18531543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 1854d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (i == kSubtitleIndex || (!pickTrack && !switching)) { 1855d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang startTime = latestMediaSegmentStartTime(); 1856b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih } 1857b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih 18588ca002eedc747dd854b61cbe364b52c06869273fRobert Shih // TRICKY: looping from i as earlier streams are already removed from streamMask 18598ca002eedc747dd854b61cbe364b52c06869273fRobert Shih for (size_t j = i; j < kMaxStreams; ++j) { 1860f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih const AString &streamUri = switching ? mStreams[j].mNewUri : mStreams[j].mUri; 1861f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih if ((streamMask & indexToType(j)) && uri == streamUri) { 18628ca002eedc747dd854b61cbe364b52c06869273fRobert Shih sources[j] = mPacketSources.valueFor(indexToType(j)); 18631543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 1864309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (timeUs >= 0) { 1865d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang startTime.mTimeUs = timeUs; 18661543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } else { 1867309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih int32_t type; 1868309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih sp<AMessage> meta; 1869d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (!switching) { 1870d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // selecting, or adapting but no swap required 1871309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih meta = sources[j]->getLatestDequeuedMeta(); 1872309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } else { 1873d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // adapting and swap required 1874309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih meta = sources[j]->getLatestEnqueuedMeta(); 18757c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (meta != NULL && mCurBandwidthIndex > mOrigBandwidthIndex) { 18767c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // switching up 18777c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang meta = sources[j]->getMetaAfterLastDequeued(mUpSwitchMargin); 18787c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 1879309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 18801543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 18810852843d304006e3ab333081fddda13b07193de8Robert Shih if ((j == kAudioIndex || j == kVideoIndex) 18820852843d304006e3ab333081fddda13b07193de8Robert Shih && meta != NULL && !meta->findInt32("discontinuity", &type)) { 1883d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang HLSTime tmpTime(meta); 1884d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (startTime < tmpTime) { 1885d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang startTime = tmpTime; 18861543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 18871543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 18881543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 1889d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (!switching) { 1890d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // selecting, or adapting but no swap required 1891309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih sources[j]->clear(); 1892309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (j == kSubtitleIndex) { 1893309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih break; 1894309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 1895964adb17885185808398507d2de88665fe193ee2Chong Zhang 18964604458dfe57b0e91a464aefafea50ae7b9876c1Chong Zhang ALOGV("stream[%zu]: queue format change", j); 1897964adb17885185808398507d2de88665fe193ee2Chong Zhang sources[j]->queueDiscontinuity( 1898a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang ATSParser::DISCONTINUITY_FORMAT_ONLY, NULL, true); 1899309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } else { 1900d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // switching, queue discontinuities after resume 1901309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih sources[j] = mPacketSources2.valueFor(indexToType(j)); 1902309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih sources[j]->clear(); 1903a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // the new fetcher might be providing streams that used to be 1904a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // provided by two different fetchers, if one of the fetcher 1905a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // paused in the middle while the other somehow paused in next 1906a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // seg, we have to start from next seg. 1907a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (seekMode < mStreams[j].mSeekMode) { 1908a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang seekMode = mStreams[j].mSeekMode; 1909309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 19101543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 19111543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 1912a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 19138ca002eedc747dd854b61cbe364b52c06869273fRobert Shih streamMask &= ~indexToType(j); 19148ca002eedc747dd854b61cbe364b52c06869273fRobert Shih } 1915a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 191614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 191725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("[fetcher-%d] startAsync: startTimeUs %lld mLastSeekTimeUs %lld " 191825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang "segmentStartTimeUs %lld seekMode %d", 191925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang fetcher->getFetcherID(), 192025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang (long long)startTime.mTimeUs, 192125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang (long long)mLastSeekTimeUs, 1922978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang (long long)startTime.getSegmentTimeUs(), 192325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang seekMode); 192425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 1925d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // Set the target segment start time to the middle point of the 1926d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // segment where the last sample was. 1927d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // This gives a better guess if segments of the two variants are not 1928d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // perfectly aligned. (If the corresponding segment in new variant 1929d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // starts slightly later than that in the old variant, we still want 1930d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // to pick that segment, not the one before) 19318ca002eedc747dd854b61cbe364b52c06869273fRobert Shih fetcher->startAsync( 19328ca002eedc747dd854b61cbe364b52c06869273fRobert Shih sources[kAudioIndex], 19338ca002eedc747dd854b61cbe364b52c06869273fRobert Shih sources[kVideoIndex], 19348ca002eedc747dd854b61cbe364b52c06869273fRobert Shih sources[kSubtitleIndex], 19350852843d304006e3ab333081fddda13b07193de8Robert Shih getMetadataSource(sources, mNewStreamMask, switching), 1936d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang startTime.mTimeUs < 0 ? mLastSeekTimeUs : startTime.mTimeUs, 1937978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang startTime.getSegmentTimeUs(), 1938d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang startTime.mSeq, 1939a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang seekMode); 1940a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1941a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 194214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // All fetchers have now been started, the configuration change 194314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // has completed. 1944a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 194514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mReconfigurationInProgress = false; 19461543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih if (switching) { 19471543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih mSwitchInProgress = true; 19481543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } else { 19491543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih mStreamMask = mNewStreamMask; 19508464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang if (mOrigBandwidthIndex != mCurBandwidthIndex) { 19518464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang ALOGV("#### Finished Bandwidth Switch Early: %zd => %zd", 19528464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang mOrigBandwidthIndex, mCurBandwidthIndex); 19538464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang mOrigBandwidthIndex = mCurBandwidthIndex; 19548464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang } 19551543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 1956a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 195725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("onChangeConfiguration3: mSwitchInProgress %d, mStreamMask 0x%x", 195825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang mSwitchInProgress, mStreamMask); 195925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 1960c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang if (mDisconnectReplyID != NULL) { 196114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber finishDisconnect(); 1962a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 196314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 1964a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1965a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhangvoid LiveSession::swapPacketSource(StreamType stream) { 196625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("[%s] swapPacketSource", getNameForStream(stream)); 1967a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1968a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // transfer packets from source2 to source 1969a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang sp<AnotherPacketSource> &aps = mPacketSources.editValueFor(stream); 1970a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang sp<AnotherPacketSource> &aps2 = mPacketSources2.editValueFor(stream); 1971a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1972a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // queue discontinuity in mPacketSource 1973a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang aps->queueDiscontinuity(ATSParser::DISCONTINUITY_FORMAT_ONLY, NULL, false); 1974a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1975a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // queue packets in mPacketSource2 to mPacketSource 1976a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang status_t finalResult = OK; 1977a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang sp<ABuffer> accessUnit; 1978a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang while (aps2->hasBufferAvailable(&finalResult) && finalResult == OK && 1979a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang OK == aps2->dequeueAccessUnit(&accessUnit)) { 1980a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang aps->queueAccessUnit(accessUnit); 1981a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 1982a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang aps2->clear(); 1983a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang} 1984a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 19857c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::tryToFinishBandwidthSwitch(const AString &oldUri) { 1986a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (!mSwitchInProgress) { 1987a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang return; 1988a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 1989a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 19907c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ssize_t index = mFetcherInfos.indexOfKey(oldUri); 1991a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (index < 0 || !mFetcherInfos[index].mToBeRemoved) { 19921543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih return; 19931543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 19941543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 1995a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // Swap packet source of streams provided by old variant 1996a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang for (size_t idx = 0; idx < kMaxStreams; idx++) { 19977c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang StreamType stream = indexToType(idx); 19987c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if ((mSwapMask & stream) && (oldUri == mStreams[idx].mUri)) { 1999a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang swapPacketSource(stream); 2000a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 2001a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if ((mNewStreamMask & stream) && mStreams[idx].mNewUri.empty()) { 2002a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang ALOGW("swapping stream type %d %s to empty stream", 2003a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang stream, mStreams[idx].mUri.c_str()); 2004a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 2005a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mStreams[idx].mUri = mStreams[idx].mNewUri; 2006a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mStreams[idx].mNewUri.clear(); 2007a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 2008a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mSwapMask &= ~stream; 2009a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 2010f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 2011f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih 20127c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mFetcherInfos.editValueAt(index).mFetcher->stopAsync(false /* clear */); 2013a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 201425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("tryToFinishBandwidthSwitch: mSwapMask=0x%x", mSwapMask); 2015309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (mSwapMask != 0) { 20161543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih return; 20171543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 20181543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 20191543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih // Check if new variant contains extra streams. 20201543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih uint32_t extraStreams = mNewStreamMask & (~mStreamMask); 20211543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih while (extraStreams) { 2022a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang StreamType stream = (StreamType) (extraStreams & ~(extraStreams - 1)); 2023a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang extraStreams &= ~stream; 2024a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 2025a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang swapPacketSource(stream); 2026f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih 2027a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang ssize_t idx = typeToIndex(stream); 2028f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih CHECK(idx >= 0); 2029f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih if (mStreams[idx].mNewUri.empty()) { 2030f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih ALOGW("swapping extra stream type %d %s to empty stream", 2031a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang stream, mStreams[idx].mUri.c_str()); 2032f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 2033f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih mStreams[idx].mUri = mStreams[idx].mNewUri; 2034f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih mStreams[idx].mNewUri.clear(); 20351543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 20361543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 2037a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // Restart new fetcher (it was paused after the first 47k block) 2038a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // and let it fetch into mPacketSources (not mPacketSources2) 2039a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang for (size_t i = 0; i < mFetcherInfos.size(); ++i) { 2040a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang FetcherInfo &info = mFetcherInfos.editValueAt(i); 2041a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (info.mToBeResumed) { 20427c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang resumeFetcher(mFetcherInfos.keyAt(i), mNewStreamMask); 2043a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang info.mToBeResumed = false; 2044a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 2045a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 2046a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 20477c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGI("#### Finished Bandwidth Switch: %zd => %zd", 20487c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mOrigBandwidthIndex, mCurBandwidthIndex); 20497c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 2050a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mStreamMask = mNewStreamMask; 2051a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mSwitchInProgress = false; 20527c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mOrigBandwidthIndex = mCurBandwidthIndex; 2053a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 20547c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang restartPollBuffering(); 20551543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih} 20561543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 2057964adb17885185808398507d2de88665fe193ee2Chong Zhangvoid LiveSession::schedulePollBuffering() { 2058964adb17885185808398507d2de88665fe193ee2Chong Zhang sp<AMessage> msg = new AMessage(kWhatPollBuffering, this); 2059964adb17885185808398507d2de88665fe193ee2Chong Zhang msg->setInt32("generation", mPollBufferingGeneration); 2060964adb17885185808398507d2de88665fe193ee2Chong Zhang msg->post(1000000ll); 2061964adb17885185808398507d2de88665fe193ee2Chong Zhang} 2062678bcdc852dd8f801f5c46fdc85db587b721d83dApurupa Pattapu 2063964adb17885185808398507d2de88665fe193ee2Chong Zhangvoid LiveSession::cancelPollBuffering() { 2064964adb17885185808398507d2de88665fe193ee2Chong Zhang ++mPollBufferingGeneration; 20657c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mPrevBufferPercentage = -1; 20667c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang} 20677c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 20687c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::restartPollBuffering() { 20697c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang cancelPollBuffering(); 20707c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang onPollBuffering(); 2071964adb17885185808398507d2de88665fe193ee2Chong Zhang} 20720ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih 2073964adb17885185808398507d2de88665fe193ee2Chong Zhangvoid LiveSession::onPollBuffering() { 2074964adb17885185808398507d2de88665fe193ee2Chong Zhang ALOGV("onPollBuffering: mSwitchInProgress %d, mReconfigurationInProgress %d, " 2075a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang "mInPreparationPhase %d, mCurBandwidthIndex %zd, mStreamMask 0x%x", 2076964adb17885185808398507d2de88665fe193ee2Chong Zhang mSwitchInProgress, mReconfigurationInProgress, 2077538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mInPreparationPhase, mCurBandwidthIndex, mStreamMask); 20780ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih 20797c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang bool underflow, ready, down, up; 20807c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (checkBuffering(underflow, ready, down, up)) { 20818464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang if (mInPreparationPhase) { 20828464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang // Allow down switch even if we're still preparing. 20838464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang // 20848464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang // Some streams have a high bandwidth index as default, 20858464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang // when bandwidth is low, it takes a long time to buffer 20868464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang // to ready mark, then it immediately pauses after start 20878464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang // as we have to do a down switch. It's better experience 20888464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang // to restart from a lower index, if we detect low bw. 20898464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang if (!switchBandwidthIfNeeded(false /* up */, down) && ready) { 20908464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang postPrepared(OK); 20918464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang } 20920ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih } 20930ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih 2094538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang if (!mInPreparationPhase) { 20957c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (ready) { 20967c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang stopBufferingIfNecessary(); 20977c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } else if (underflow) { 20987c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang startBufferingIfNecessary(); 20997c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 21007c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang switchBandwidthIfNeeded(up, down); 21018464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang } 21020ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih } 21030ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih 2104964adb17885185808398507d2de88665fe193ee2Chong Zhang schedulePollBuffering(); 21050ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih} 21060ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih 21077c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::cancelBandwidthSwitch(bool resume) { 21087c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGV("cancelBandwidthSwitch: mSwitchGen(%d)++, orig %zd, cur %zd", 21097c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mSwitchGeneration, mOrigBandwidthIndex, mCurBandwidthIndex); 21107c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (!mSwitchInProgress) { 21117c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return; 21127c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 2113f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih 2114f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih for (size_t i = 0; i < mFetcherInfos.size(); ++i) { 2115f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih FetcherInfo& info = mFetcherInfos.editValueAt(i); 2116f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih if (info.mToBeRemoved) { 2117f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih info.mToBeRemoved = false; 21187c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (resume) { 21197c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang resumeFetcher(mFetcherInfos.keyAt(i), mSwapMask); 21207c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 2121f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 2122f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 2123f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih 2124f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih for (size_t i = 0; i < kMaxStreams; ++i) { 21257c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang AString newUri = mStreams[i].mNewUri; 21267c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (!newUri.empty()) { 21277c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // clear all mNewUri matching this newUri 21287c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang for (size_t j = i; j < kMaxStreams; ++j) { 21297c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (mStreams[j].mNewUri == newUri) { 21307c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mStreams[j].mNewUri.clear(); 21317c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 21327c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 21337c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGV("stopping newUri = %s", newUri.c_str()); 21347c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ssize_t index = mFetcherInfos.indexOfKey(newUri); 21357c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (index < 0) { 21367c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGE("did not find fetcher for newUri: %s", newUri.c_str()); 2137f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih continue; 2138f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 21397c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang FetcherInfo &info = mFetcherInfos.editValueAt(index); 21407c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang info.mToBeRemoved = true; 2141f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih info.mFetcher->stopAsync(); 2142f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 2143f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 21447c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 21457c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGI("#### Canceled Bandwidth Switch: %zd => %zd", 214625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang mOrigBandwidthIndex, mCurBandwidthIndex); 21477c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 21487c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mSwitchGeneration++; 21497c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mSwitchInProgress = false; 21507c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mCurBandwidthIndex = mOrigBandwidthIndex; 21517c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mSwapMask = 0; 21521543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih} 21531543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 21547c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangbool LiveSession::checkBuffering( 21557c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang bool &underflow, bool &ready, bool &down, bool &up) { 21567c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang underflow = ready = down = up = false; 2157964adb17885185808398507d2de88665fe193ee2Chong Zhang 21587c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (mReconfigurationInProgress) { 2159964adb17885185808398507d2de88665fe193ee2Chong Zhang ALOGV("Switch/Reconfig in progress, defer buffer polling"); 21601543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih return false; 21611543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 21621543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 21637c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang size_t activeCount, underflowCount, readyCount, downCount, upCount; 21647c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang activeCount = underflowCount = readyCount = downCount = upCount =0; 21657c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang int32_t minBufferPercent = -1; 21667c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang int64_t durationUs; 21677c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (getDuration(&durationUs) != OK) { 21687c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang durationUs = -1; 21697c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 2170964adb17885185808398507d2de88665fe193ee2Chong Zhang for (size_t i = 0; i < mPacketSources.size(); ++i) { 2171964adb17885185808398507d2de88665fe193ee2Chong Zhang // we don't check subtitles for buffering level 2172964adb17885185808398507d2de88665fe193ee2Chong Zhang if (!(mStreamMask & mPacketSources.keyAt(i) 2173964adb17885185808398507d2de88665fe193ee2Chong Zhang & (STREAMTYPE_AUDIO | STREAMTYPE_VIDEO))) { 2174964adb17885185808398507d2de88665fe193ee2Chong Zhang continue; 2175964adb17885185808398507d2de88665fe193ee2Chong Zhang } 2176964adb17885185808398507d2de88665fe193ee2Chong Zhang // ignore streams that never had any packet queued. 2177964adb17885185808398507d2de88665fe193ee2Chong Zhang // (it's possible that the variant only has audio or video) 2178964adb17885185808398507d2de88665fe193ee2Chong Zhang sp<AMessage> meta = mPacketSources[i]->getLatestEnqueuedMeta(); 2179964adb17885185808398507d2de88665fe193ee2Chong Zhang if (meta == NULL) { 2180964adb17885185808398507d2de88665fe193ee2Chong Zhang continue; 2181964adb17885185808398507d2de88665fe193ee2Chong Zhang } 2182964adb17885185808398507d2de88665fe193ee2Chong Zhang 21830dd229bb306df68b88e7419b3cc11fc6175be1daRobert Shih status_t finalResult; 2184964adb17885185808398507d2de88665fe193ee2Chong Zhang int64_t bufferedDurationUs = 21850dd229bb306df68b88e7419b3cc11fc6175be1daRobert Shih mPacketSources[i]->getBufferedDurationUs(&finalResult); 218625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("[%s] buffered %lld us", 218725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang getNameForStream(mPacketSources.keyAt(i)), 218825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang (long long)bufferedDurationUs); 21897c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (durationUs >= 0) { 21907c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang int32_t percent; 21917c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (mPacketSources[i]->isFinished(0 /* duration */)) { 21927c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang percent = 100; 21937c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } else { 21948464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang percent = (int32_t)(100.0 * 21958464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang (mLastDequeuedTimeUs + bufferedDurationUs) / durationUs); 21967c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 21977c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (minBufferPercent < 0 || percent < minBufferPercent) { 21987c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang minBufferPercent = percent; 21997c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 2200964adb17885185808398507d2de88665fe193ee2Chong Zhang } 22017c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 22027c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ++activeCount; 220348fa06d1e80a872c7495804979256e021e566ae0Wei Jia int64_t readyMarkUs = 220448fa06d1e80a872c7495804979256e021e566ae0Wei Jia (mInPreparationPhase ? 220548fa06d1e80a872c7495804979256e021e566ae0Wei Jia mBufferingSettings.mInitialWatermarkMs : 220648fa06d1e80a872c7495804979256e021e566ae0Wei Jia mBufferingSettings.mRebufferingWatermarkHighMs) * 1000ll; 220748fa06d1e80a872c7495804979256e021e566ae0Wei Jia if (bufferedDurationUs > readyMarkUs 22087c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang || mPacketSources[i]->isFinished(0)) { 22097c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ++readyCount; 22107c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 22117c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (!mPacketSources[i]->isFinished(0)) { 221248fa06d1e80a872c7495804979256e021e566ae0Wei Jia if (bufferedDurationUs < mBufferingSettings.mRebufferingWatermarkLowMs * 1000ll) { 22137c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ++underflowCount; 22147c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 22157c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (bufferedDurationUs > mUpSwitchMark) { 22167c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ++upCount; 2217d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang } 2218d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (bufferedDurationUs < mDownSwitchMark) { 22197c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ++downCount; 22207c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 22217c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 22227c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 22237c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 22247c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (minBufferPercent >= 0) { 22257c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notifyBufferingUpdate(minBufferPercent); 222614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 222714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 2228964adb17885185808398507d2de88665fe193ee2Chong Zhang if (activeCount > 0) { 22297c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang up = (upCount == activeCount); 22307c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang down = (downCount > 0); 22317c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ready = (readyCount == activeCount); 22327c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang underflow = (underflowCount > 0); 22331543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih return true; 22341543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 2235964adb17885185808398507d2de88665fe193ee2Chong Zhang 2236964adb17885185808398507d2de88665fe193ee2Chong Zhang return false; 22371543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih} 22381543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 22397c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::startBufferingIfNecessary() { 22407c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGV("startBufferingIfNecessary: mInPreparationPhase=%d, mBuffering=%d", 22417c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mInPreparationPhase, mBuffering); 22427c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (!mBuffering) { 22437c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mBuffering = true; 22447c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 22457c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AMessage> notify = mNotify->dup(); 22467c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->setInt32("what", kWhatBufferingStart); 22477c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->post(); 22487c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 22497c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang} 22507c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 22517c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::stopBufferingIfNecessary() { 22527c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGV("stopBufferingIfNecessary: mInPreparationPhase=%d, mBuffering=%d", 22537c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mInPreparationPhase, mBuffering); 22547c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 22557c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (mBuffering) { 22567c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mBuffering = false; 22577c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 22587c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AMessage> notify = mNotify->dup(); 22597c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->setInt32("what", kWhatBufferingEnd); 22607c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->post(); 22617c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 22627c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang} 22637c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 22647c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::notifyBufferingUpdate(int32_t percentage) { 22657c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (percentage < mPrevBufferPercentage) { 22667c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang percentage = mPrevBufferPercentage; 22677c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } else if (percentage > 100) { 22687c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang percentage = 100; 22697c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 22707c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 22717c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mPrevBufferPercentage = percentage; 22727c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 22737c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGV("notifyBufferingUpdate: percentage=%d%%", percentage); 22747c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 22757c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AMessage> notify = mNotify->dup(); 22767c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->setInt32("what", kWhatBufferingUpdate); 22777c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->setInt32("percentage", percentage); 22787c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->post(); 22797c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang} 22807c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 22815ef659e010e90175eb5282d9642a02f6105189bfChong Zhangbool LiveSession::tryBandwidthFallback() { 22825ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (mInPreparationPhase || mReconfigurationInProgress) { 22835ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // Don't try fallback during prepare or reconfig. 22845ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // If error happens there, it's likely unrecoverable. 22855ef659e010e90175eb5282d9642a02f6105189bfChong Zhang return false; 22865ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } 22875ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (mCurBandwidthIndex > mOrigBandwidthIndex) { 22885ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // if we're switching up, simply cancel and resume old variant 22895ef659e010e90175eb5282d9642a02f6105189bfChong Zhang cancelBandwidthSwitch(true /* resume */); 22905ef659e010e90175eb5282d9642a02f6105189bfChong Zhang return true; 22915ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } else { 22925ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // if we're switching down, we're likely about to underflow (if 22935ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // not already underflowing). try the lowest viable bandwidth if 22945ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // not on that variant already. 22955ef659e010e90175eb5282d9642a02f6105189bfChong Zhang ssize_t lowestValid = getLowestValidBandwidthIndex(); 22965ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (mCurBandwidthIndex > lowestValid) { 22975ef659e010e90175eb5282d9642a02f6105189bfChong Zhang cancelBandwidthSwitch(); 22985ef659e010e90175eb5282d9642a02f6105189bfChong Zhang changeConfiguration(-1ll, lowestValid); 22995ef659e010e90175eb5282d9642a02f6105189bfChong Zhang return true; 23005ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } 23015ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } 23025ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // return false if we couldn't find any fallback 23035ef659e010e90175eb5282d9642a02f6105189bfChong Zhang return false; 23045ef659e010e90175eb5282d9642a02f6105189bfChong Zhang} 23055ef659e010e90175eb5282d9642a02f6105189bfChong Zhang 23068464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang/* 23078464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang * returns true if a bandwidth switch is actually needed (and started), 23088464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang * returns false otherwise 23098464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang */ 23108464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhangbool LiveSession::switchBandwidthIfNeeded(bool bufferHigh, bool bufferLow) { 2311538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang // no need to check bandwidth if we only have 1 bandwidth settings 23125ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (mBandwidthItems.size() < 2) { 23135ef659e010e90175eb5282d9642a02f6105189bfChong Zhang return false; 23145ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } 23155ef659e010e90175eb5282d9642a02f6105189bfChong Zhang 23165ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (mSwitchInProgress) { 23175ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (mBuffering) { 23185ef659e010e90175eb5282d9642a02f6105189bfChong Zhang tryBandwidthFallback(); 23195ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } 23208464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang return false; 2321538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang } 2322538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 23235ef659e010e90175eb5282d9642a02f6105189bfChong Zhang int32_t bandwidthBps, shortTermBps; 2324978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang bool isStable; 23255ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (mBandwidthEstimator->estimateBandwidth( 23265ef659e010e90175eb5282d9642a02f6105189bfChong Zhang &bandwidthBps, &isStable, &shortTermBps)) { 23275ef659e010e90175eb5282d9642a02f6105189bfChong Zhang ALOGV("bandwidth estimated at %.2f kbps, " 23285ef659e010e90175eb5282d9642a02f6105189bfChong Zhang "stable %d, shortTermBps %.2f kbps", 23295ef659e010e90175eb5282d9642a02f6105189bfChong Zhang bandwidthBps / 1024.0f, isStable, shortTermBps / 1024.0f); 2330a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mLastBandwidthBps = bandwidthBps; 23315ef659e010e90175eb5282d9642a02f6105189bfChong Zhang mLastBandwidthStable = isStable; 2332538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang } else { 2333538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang ALOGV("no bandwidth estimate."); 23348464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang return false; 2335538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang } 2336538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 2337538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang int32_t curBandwidth = mBandwidthItems.itemAt(mCurBandwidthIndex).mBandwidth; 2338d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // canSwithDown and canSwitchUp can't both be true. 2339d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // we only want to switch up when measured bw is 120% higher than current variant, 2340d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // and we only want to switch down when measured bw is below current variant. 2341978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang bool canSwitchDown = bufferLow 2342d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang && (bandwidthBps < (int32_t)curBandwidth); 2343d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang bool canSwitchUp = bufferHigh 2344d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang && (bandwidthBps > (int32_t)curBandwidth * 12 / 10); 2345d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang 2346978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (canSwitchDown || canSwitchUp) { 2347978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang // bandwidth estimating has some delay, if we have to downswitch when 23485ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // it hasn't stabilized, use the short term to guess real bandwidth, 23495ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // since it may be dropping too fast. 23505ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // (note this doesn't apply to upswitch, always use longer average there) 2351978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (!isStable && canSwitchDown) { 23525ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (shortTermBps < bandwidthBps) { 23535ef659e010e90175eb5282d9642a02f6105189bfChong Zhang bandwidthBps = shortTermBps; 23545ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } 2355978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 2356978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang 2357538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang ssize_t bandwidthIndex = getBandwidthIndex(bandwidthBps); 2358538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 2359d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // it's possible that we're checking for canSwitchUp case, but the returned 2360d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // bandwidthIndex is < mCurBandwidthIndex, as getBandwidthIndex() only uses 70% 2361d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // of measured bw. In that case we don't want to do anything, since we have 2362d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // both enough buffer and enough bw. 23638464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang if ((canSwitchUp && bandwidthIndex > mCurBandwidthIndex) 2364978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang || (canSwitchDown && bandwidthIndex < mCurBandwidthIndex)) { 23658464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang // if not yet prepared, just restart again with new bw index. 23668464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang // this is faster and playback experience is cleaner. 23678464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang changeConfiguration( 23688464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang mInPreparationPhase ? 0 : -1ll, bandwidthIndex); 23698464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang return true; 2370538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang } 237114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 23728464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang return false; 2373a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 2374a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 23757c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::postError(status_t err) { 23767c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // if we reached EOS, notify buffering of 100% 23777c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (err == ERROR_END_OF_STREAM) { 23787c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notifyBufferingUpdate(100); 23797c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 23807c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // we'll stop buffer polling now, before that notify 23817c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // stop buffering to stop the spinning icon 23827c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang stopBufferingIfNecessary(); 23837c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang cancelPollBuffering(); 23847c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 23857c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AMessage> notify = mNotify->dup(); 23867c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->setInt32("what", kWhatError); 23877c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->setInt32("err", err); 23887c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->post(); 23897c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang} 23907c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 239114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::postPrepared(status_t err) { 239214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(mInPreparationPhase); 2393a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 239414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AMessage> notify = mNotify->dup(); 239514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (err == OK || err == ERROR_END_OF_STREAM) { 239614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->setInt32("what", kWhatPrepared); 239714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else { 23987c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang cancelPollBuffering(); 23997c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 240014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->setInt32("what", kWhatPreparationFailed); 240114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->setInt32("err", err); 240214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 2403a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 240414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->post(); 2405a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 240614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mInPreparationPhase = false; 2407b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber} 2408b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber 2409964adb17885185808398507d2de88665fe193ee2Chong Zhang 2410a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} // namespace android 2411a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 2412