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 52765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang// Buffer Prepare/Ready/Underflow Marks 53765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhangconst int64_t LiveSession::kReadyMarkUs = 5000000ll; 54765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhangconst int64_t LiveSession::kPrepareMarkUs = 1500000ll; 55765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhangconst int64_t LiveSession::kUnderflowMarkUs = 1000000ll; 56765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang 57538b6d22a3578c0201d48f8548289aa254d81484Chong Zhangstruct LiveSession::BandwidthEstimator : public RefBase { 58538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang BandwidthEstimator(); 59538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 60538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang void addBandwidthMeasurement(size_t numBytes, int64_t delayUs); 615ef659e010e90175eb5282d9642a02f6105189bfChong Zhang bool estimateBandwidth( 625ef659e010e90175eb5282d9642a02f6105189bfChong Zhang int32_t *bandwidth, 635ef659e010e90175eb5282d9642a02f6105189bfChong Zhang bool *isStable = NULL, 645ef659e010e90175eb5282d9642a02f6105189bfChong Zhang int32_t *shortTermBps = NULL); 65538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 66538b6d22a3578c0201d48f8548289aa254d81484Chong Zhangprivate: 67538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang // Bandwidth estimation parameters 685ef659e010e90175eb5282d9642a02f6105189bfChong Zhang static const int32_t kShortTermBandwidthItems = 3; 6981636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang static const int32_t kMinBandwidthHistoryItems = 20; 7081636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang static const int64_t kMinBandwidthHistoryWindowUs = 5000000ll; // 5 sec 7181636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang static const int64_t kMaxBandwidthHistoryWindowUs = 30000000ll; // 30 sec 725ef659e010e90175eb5282d9642a02f6105189bfChong Zhang static const int64_t kMaxBandwidthHistoryAgeUs = 60000000ll; // 60 sec 73538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 74538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang struct BandwidthEntry { 755ef659e010e90175eb5282d9642a02f6105189bfChong Zhang int64_t mTimestampUs; 76538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang int64_t mDelayUs; 77538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang size_t mNumBytes; 78538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang }; 79538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 80538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang Mutex mLock; 81538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang List<BandwidthEntry> mBandwidthHistory; 82978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang List<int32_t> mPrevEstimates; 835ef659e010e90175eb5282d9642a02f6105189bfChong Zhang int32_t mShortTermEstimate; 84978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang bool mHasNewSample; 85978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang bool mIsStable; 86538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang int64_t mTotalTransferTimeUs; 87538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang size_t mTotalTransferBytes; 88538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 89538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang DISALLOW_EVIL_CONSTRUCTORS(BandwidthEstimator); 90538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang}; 91538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 92538b6d22a3578c0201d48f8548289aa254d81484Chong ZhangLiveSession::BandwidthEstimator::BandwidthEstimator() : 935ef659e010e90175eb5282d9642a02f6105189bfChong Zhang mShortTermEstimate(0), 94978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mHasNewSample(false), 95978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mIsStable(true), 96538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mTotalTransferTimeUs(0), 97538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mTotalTransferBytes(0) { 98538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang} 99538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 100538b6d22a3578c0201d48f8548289aa254d81484Chong Zhangvoid LiveSession::BandwidthEstimator::addBandwidthMeasurement( 101538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang size_t numBytes, int64_t delayUs) { 102538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang AutoMutex autoLock(mLock); 103538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 1045ef659e010e90175eb5282d9642a02f6105189bfChong Zhang int64_t nowUs = ALooper::GetNowUs(); 105538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang BandwidthEntry entry; 1065ef659e010e90175eb5282d9642a02f6105189bfChong Zhang entry.mTimestampUs = nowUs; 107538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang entry.mDelayUs = delayUs; 108538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang entry.mNumBytes = numBytes; 109538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mTotalTransferTimeUs += delayUs; 110538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mTotalTransferBytes += numBytes; 111538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mBandwidthHistory.push_back(entry); 112978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mHasNewSample = true; 113538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 11481636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang // Remove no more than 10% of total transfer time at a time 11581636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang // to avoid sudden jump on bandwidth estimation. There might 11681636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang // be long blocking reads that takes up signification time, 11781636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang // we have to keep a longer window in that case. 11881636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang int64_t bandwidthHistoryWindowUs = mTotalTransferTimeUs * 9 / 10; 11981636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang if (bandwidthHistoryWindowUs < kMinBandwidthHistoryWindowUs) { 12081636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang bandwidthHistoryWindowUs = kMinBandwidthHistoryWindowUs; 12181636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang } else if (bandwidthHistoryWindowUs > kMaxBandwidthHistoryWindowUs) { 12281636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang bandwidthHistoryWindowUs = kMaxBandwidthHistoryWindowUs; 12381636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang } 124538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang // trim old samples, keeping at least kMaxBandwidthHistoryItems samples, 125538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang // and total transfer time at least kMaxBandwidthHistoryWindowUs. 12681636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang while (mBandwidthHistory.size() > kMinBandwidthHistoryItems) { 127538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang List<BandwidthEntry>::iterator it = mBandwidthHistory.begin(); 1285ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // remove sample if either absolute age or total transfer time is 1295ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // over kMaxBandwidthHistoryWindowUs 1305ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (nowUs - it->mTimestampUs < kMaxBandwidthHistoryAgeUs && 1315ef659e010e90175eb5282d9642a02f6105189bfChong Zhang mTotalTransferTimeUs - it->mDelayUs < bandwidthHistoryWindowUs) { 132538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang break; 133538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang } 134538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mTotalTransferTimeUs -= it->mDelayUs; 135538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mTotalTransferBytes -= it->mNumBytes; 136538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mBandwidthHistory.erase(mBandwidthHistory.begin()); 137538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang } 138538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang} 139538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 14081636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhangbool LiveSession::BandwidthEstimator::estimateBandwidth( 1415ef659e010e90175eb5282d9642a02f6105189bfChong Zhang int32_t *bandwidthBps, bool *isStable, int32_t *shortTermBps) { 142538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang AutoMutex autoLock(mLock); 143538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 144538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang if (mBandwidthHistory.size() < 2) { 145538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang return false; 146538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang } 147538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 148978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (!mHasNewSample) { 149978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang *bandwidthBps = *(--mPrevEstimates.end()); 150978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (isStable) { 151978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang *isStable = mIsStable; 152978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 1535ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (shortTermBps) { 1545ef659e010e90175eb5282d9642a02f6105189bfChong Zhang *shortTermBps = mShortTermEstimate; 1555ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } 156978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang return true; 157978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 158978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang 159538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang *bandwidthBps = ((double)mTotalTransferBytes * 8E6 / mTotalTransferTimeUs); 160978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mPrevEstimates.push_back(*bandwidthBps); 161978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang while (mPrevEstimates.size() > 3) { 162978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mPrevEstimates.erase(mPrevEstimates.begin()); 163978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 164978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mHasNewSample = false; 165978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang 1665ef659e010e90175eb5282d9642a02f6105189bfChong Zhang int64_t totalTimeUs = 0; 1675ef659e010e90175eb5282d9642a02f6105189bfChong Zhang size_t totalBytes = 0; 1685ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (mBandwidthHistory.size() >= kShortTermBandwidthItems) { 1695ef659e010e90175eb5282d9642a02f6105189bfChong Zhang List<BandwidthEntry>::iterator it = --mBandwidthHistory.end(); 1705ef659e010e90175eb5282d9642a02f6105189bfChong Zhang for (size_t i = 0; i < kShortTermBandwidthItems; i++, it--) { 1715ef659e010e90175eb5282d9642a02f6105189bfChong Zhang totalTimeUs += it->mDelayUs; 1725ef659e010e90175eb5282d9642a02f6105189bfChong Zhang totalBytes += it->mNumBytes; 1735ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } 1745ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } 1755ef659e010e90175eb5282d9642a02f6105189bfChong Zhang mShortTermEstimate = totalTimeUs > 0 ? 1765ef659e010e90175eb5282d9642a02f6105189bfChong Zhang (totalBytes * 8E6 / totalTimeUs) : *bandwidthBps; 1775ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (shortTermBps) { 1785ef659e010e90175eb5282d9642a02f6105189bfChong Zhang *shortTermBps = mShortTermEstimate; 1795ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } 1805ef659e010e90175eb5282d9642a02f6105189bfChong Zhang 181978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang int32_t minEstimate = -1, maxEstimate = -1; 182978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang List<int32_t>::iterator it; 183978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang for (it = mPrevEstimates.begin(); it != mPrevEstimates.end(); it++) { 184978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang int32_t estimate = *it; 185978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (minEstimate < 0 || minEstimate > estimate) { 186978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang minEstimate = estimate; 187978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 188978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (maxEstimate < 0 || maxEstimate < estimate) { 189978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang maxEstimate = estimate; 190978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 191978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 1925ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // consider it stable if long-term average is not jumping a lot 1935ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // and short-term average is not much lower than long-term average 1945ef659e010e90175eb5282d9642a02f6105189bfChong Zhang mIsStable = (maxEstimate <= minEstimate * 4 / 3) 1955ef659e010e90175eb5282d9642a02f6105189bfChong Zhang && mShortTermEstimate > minEstimate * 7 / 10; 196978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (isStable) { 1975ef659e010e90175eb5282d9642a02f6105189bfChong Zhang *isStable = mIsStable; 198978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 1995ef659e010e90175eb5282d9642a02f6105189bfChong Zhang 20081636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang#if 0 20181636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang { 20281636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang char dumpStr[1024] = {0}; 20381636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang size_t itemIdx = 0; 20481636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang size_t histSize = mBandwidthHistory.size(); 20581636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang sprintf(dumpStr, "estimate bps=%d stable=%d history (n=%d): {", 20681636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang *bandwidthBps, mIsStable, histSize); 20781636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang List<BandwidthEntry>::iterator it = mBandwidthHistory.begin(); 20881636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang for (; it != mBandwidthHistory.end(); ++it) { 20981636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang if (itemIdx > 50) { 21081636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang sprintf(dumpStr + strlen(dumpStr), 21181636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang "...(%zd more items)... }", histSize - itemIdx); 21281636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang break; 21381636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang } 21481636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang sprintf(dumpStr + strlen(dumpStr), "%dk/%.3fs%s", 21581636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang it->mNumBytes / 1024, 21681636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang (double)it->mDelayUs * 1.0e-6, 21781636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang (it == (--mBandwidthHistory.end())) ? "}" : ", "); 21881636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang itemIdx++; 21981636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang } 22081636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang ALOGE(dumpStr); 22181636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang } 22281636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang#endif 223538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang return true; 224538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang} 225538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 2267c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang//static 2277c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangconst char *LiveSession::getKeyForStream(StreamType type) { 2287c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang switch (type) { 2297c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang case STREAMTYPE_VIDEO: 2307c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return "timeUsVideo"; 2317c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang case STREAMTYPE_AUDIO: 2327c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return "timeUsAudio"; 2337c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang case STREAMTYPE_SUBTITLES: 2347c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return "timeUsSubtitle"; 2350852843d304006e3ab333081fddda13b07193de8Robert Shih case STREAMTYPE_METADATA: 2360852843d304006e3ab333081fddda13b07193de8Robert Shih return "timeUsMetadata"; // unused 2377c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang default: 2387c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang TRESPASS(); 2397c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 2407c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return NULL; 2417c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang} 2427c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 24325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang//static 24425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhangconst char *LiveSession::getNameForStream(StreamType type) { 24525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang switch (type) { 24625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang case STREAMTYPE_VIDEO: 24725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang return "video"; 24825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang case STREAMTYPE_AUDIO: 24925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang return "audio"; 25025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang case STREAMTYPE_SUBTITLES: 25125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang return "subs"; 2520852843d304006e3ab333081fddda13b07193de8Robert Shih case STREAMTYPE_METADATA: 2530852843d304006e3ab333081fddda13b07193de8Robert Shih return "metadata"; 25425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang default: 25525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang break; 25625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang } 25725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang return "unknown"; 25825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang} 25925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 2600852843d304006e3ab333081fddda13b07193de8Robert Shih//static 2610852843d304006e3ab333081fddda13b07193de8Robert ShihATSParser::SourceType LiveSession::getSourceTypeForStream(StreamType type) { 2620852843d304006e3ab333081fddda13b07193de8Robert Shih switch (type) { 2630852843d304006e3ab333081fddda13b07193de8Robert Shih case STREAMTYPE_VIDEO: 2640852843d304006e3ab333081fddda13b07193de8Robert Shih return ATSParser::VIDEO; 2650852843d304006e3ab333081fddda13b07193de8Robert Shih case STREAMTYPE_AUDIO: 2660852843d304006e3ab333081fddda13b07193de8Robert Shih return ATSParser::AUDIO; 2670852843d304006e3ab333081fddda13b07193de8Robert Shih case STREAMTYPE_METADATA: 2680852843d304006e3ab333081fddda13b07193de8Robert Shih return ATSParser::META; 2690852843d304006e3ab333081fddda13b07193de8Robert Shih case STREAMTYPE_SUBTITLES: 2700852843d304006e3ab333081fddda13b07193de8Robert Shih default: 2710852843d304006e3ab333081fddda13b07193de8Robert Shih TRESPASS(); 2720852843d304006e3ab333081fddda13b07193de8Robert Shih } 2730852843d304006e3ab333081fddda13b07193de8Robert Shih return ATSParser::NUM_SOURCE_TYPES; // should not reach here 2740852843d304006e3ab333081fddda13b07193de8Robert Shih} 2750852843d304006e3ab333081fddda13b07193de8Robert Shih 2760df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas HuberLiveSession::LiveSession( 2771b86fe063badb5f28c467ade39be0f4008688947Andreas Huber const sp<AMessage> ¬ify, uint32_t flags, 27881e68448f3361eaf8618930471fdc3c21bdf5cbcAndreas Huber const sp<IMediaHTTPService> &httpService) 2790df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas Huber : mNotify(notify), 2800df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas Huber mFlags(flags), 2811b86fe063badb5f28c467ade39be0f4008688947Andreas Huber mHTTPService(httpService), 2827c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mBuffering(false), 2830df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas Huber mInPreparationPhase(true), 2847c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mPollBufferingGeneration(0), 2857c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mPrevBufferPercentage(-1), 286309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mCurBandwidthIndex(-1), 2877c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mOrigBandwidthIndex(-1), 288a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mLastBandwidthBps(-1ll), 2895ef659e010e90175eb5282d9642a02f6105189bfChong Zhang mLastBandwidthStable(false), 290538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mBandwidthEstimator(new BandwidthEstimator()), 291a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang mMaxWidth(720), 292a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang mMaxHeight(480), 29314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mStreamMask(0), 2941543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih mNewStreamMask(0), 2951543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih mSwapMask(0), 2961543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih mSwitchGeneration(0), 297b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih mSubtitleGeneration(0), 29814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mLastDequeuedTimeUs(0ll), 299dcb89b3b505522efde173c105a851c412f947178Chong Zhang mRealTimeBaseUs(0ll), 30014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mReconfigurationInProgress(false), 3011543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih mSwitchInProgress(false), 302765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang mUpSwitchMark(kUpSwitchMarkUs), 303765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang mDownSwitchMark(kDownSwitchMarkUs), 304765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang mUpSwitchMargin(kUpSwitchMarginUs), 305309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mFirstTimeUsValid(false), 306309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mFirstTimeUs(0), 3070852843d304006e3ab333081fddda13b07193de8Robert Shih mLastSeekTimeUs(0), 3080852843d304006e3ab333081fddda13b07193de8Robert Shih mHasMetadata(false) { 3098ca002eedc747dd854b61cbe364b52c06869273fRobert Shih mStreams[kAudioIndex] = StreamItem("audio"); 3108ca002eedc747dd854b61cbe364b52c06869273fRobert Shih mStreams[kVideoIndex] = StreamItem("video"); 311e4f25c280a8f1655c31a745978e0fcbc61f91deeRobert Shih mStreams[kSubtitleIndex] = StreamItem("subtitles"); 31214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 3130852843d304006e3ab333081fddda13b07193de8Robert Shih for (size_t i = 0; i < kNumSources; ++i) { 3148ca002eedc747dd854b61cbe364b52c06869273fRobert Shih mPacketSources.add(indexToType(i), new AnotherPacketSource(NULL /* meta */)); 3151543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih mPacketSources2.add(indexToType(i), new AnotherPacketSource(NULL /* meta */)); 3168ca002eedc747dd854b61cbe364b52c06869273fRobert Shih } 317a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 318a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 319a44153c1a57202fb538659eb50706e60454d6273Andreas HuberLiveSession::~LiveSession() { 320964adb17885185808398507d2de88665fe193ee2Chong Zhang if (mFetcherLooper != NULL) { 321964adb17885185808398507d2de88665fe193ee2Chong Zhang mFetcherLooper->stop(); 322964adb17885185808398507d2de88665fe193ee2Chong Zhang } 323a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 324a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 3250852843d304006e3ab333081fddda13b07193de8Robert Shihint64_t LiveSession::calculateMediaTimeUs( 3260852843d304006e3ab333081fddda13b07193de8Robert Shih int64_t firstTimeUs, int64_t timeUs, int32_t discontinuitySeq) { 3270852843d304006e3ab333081fddda13b07193de8Robert Shih if (timeUs >= firstTimeUs) { 3280852843d304006e3ab333081fddda13b07193de8Robert Shih timeUs -= firstTimeUs; 3290852843d304006e3ab333081fddda13b07193de8Robert Shih } else { 3300852843d304006e3ab333081fddda13b07193de8Robert Shih timeUs = 0; 3310852843d304006e3ab333081fddda13b07193de8Robert Shih } 3320852843d304006e3ab333081fddda13b07193de8Robert Shih timeUs += mLastSeekTimeUs; 3330852843d304006e3ab333081fddda13b07193de8Robert Shih if (mDiscontinuityOffsetTimesUs.indexOfKey(discontinuitySeq) >= 0) { 3340852843d304006e3ab333081fddda13b07193de8Robert Shih timeUs += mDiscontinuityOffsetTimesUs.valueFor(discontinuitySeq); 3350852843d304006e3ab333081fddda13b07193de8Robert Shih } 3360852843d304006e3ab333081fddda13b07193de8Robert Shih return timeUs; 3370852843d304006e3ab333081fddda13b07193de8Robert Shih} 3380852843d304006e3ab333081fddda13b07193de8Robert Shih 33914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::dequeueAccessUnit( 34014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber StreamType stream, sp<ABuffer> *accessUnit) { 341964adb17885185808398507d2de88665fe193ee2Chong Zhang status_t finalResult = OK; 34214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AnotherPacketSource> packetSource = mPacketSources.valueFor(stream); 34314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 34425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ssize_t streamIdx = typeToIndex(stream); 34525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang if (streamIdx < 0) { 3465abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang return BAD_VALUE; 34725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang } 34825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang const char *streamStr = getNameForStream(stream); 349a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // Do not let client pull data if we don't have data packets yet. 350a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // We might only have a format discontinuity queued without data. 351a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // When NuPlayerDecoder dequeues the format discontinuity, it will 352a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // immediately try to getFormat. If we return NULL, NuPlayerDecoder 353a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // thinks it can do seamless change, so will not shutdown decoder. 354a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // When the actual format arrives, it can't handle it and get stuck. 355a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (!packetSource->hasDataBufferAvailable(&finalResult)) { 35625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("[%s] dequeueAccessUnit: no buffer available (finalResult=%d)", 35725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang streamStr, finalResult); 35825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 359f69c996864844e8f669308af8412cede043062a2Robert Shih if (finalResult == OK) { 360f69c996864844e8f669308af8412cede043062a2Robert Shih return -EAGAIN; 361f69c996864844e8f669308af8412cede043062a2Robert Shih } else { 362f69c996864844e8f669308af8412cede043062a2Robert Shih return finalResult; 363f69c996864844e8f669308af8412cede043062a2Robert Shih } 364f69c996864844e8f669308af8412cede043062a2Robert Shih } 365f69c996864844e8f669308af8412cede043062a2Robert Shih 366a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // Let the client dequeue as long as we have buffers available 367a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // Do not make pause/resume decisions here. 368309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 36914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber status_t err = packetSource->dequeueAccessUnit(accessUnit); 37014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 37114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (err == INFO_DISCONTINUITY) { 372309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih // adaptive streaming, discontinuities in the playlist 37314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int32_t type; 37414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK((*accessUnit)->meta()->findInt32("discontinuity", &type)); 37514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 37614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AMessage> extra; 37714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (!(*accessUnit)->meta()->findMessage("extra", &extra)) { 37814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber extra.clear(); 37914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 38014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 38114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGI("[%s] read discontinuity of type %d, extra = %s", 38214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber streamStr, 38314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber type, 38414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber extra == NULL ? "NULL" : extra->debugString().c_str()); 38514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else if (err == OK) { 386309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 387dcb89b3b505522efde173c105a851c412f947178Chong Zhang if (stream == STREAMTYPE_AUDIO || stream == STREAMTYPE_VIDEO) { 38825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang int64_t timeUs, originalTimeUs; 389309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih int32_t discontinuitySeq = 0; 3900852843d304006e3ab333081fddda13b07193de8Robert Shih StreamItem& strm = mStreams[streamIdx]; 391dcb89b3b505522efde173c105a851c412f947178Chong Zhang CHECK((*accessUnit)->meta()->findInt64("timeUs", &timeUs)); 39225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang originalTimeUs = timeUs; 393309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih (*accessUnit)->meta()->findInt32("discontinuitySeq", &discontinuitySeq); 3947c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (discontinuitySeq > (int32_t) strm.mCurDiscontinuitySeq) { 3957c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang int64_t offsetTimeUs; 3967c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (mDiscontinuityOffsetTimesUs.indexOfKey(strm.mCurDiscontinuitySeq) >= 0) { 3977c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang offsetTimeUs = mDiscontinuityOffsetTimesUs.valueFor(strm.mCurDiscontinuitySeq); 3987c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } else { 3997c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang offsetTimeUs = 0; 4007c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 4017c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 40281636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang if (mDiscontinuityAbsStartTimesUs.indexOfKey(strm.mCurDiscontinuitySeq) >= 0 40381636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang && strm.mLastDequeuedTimeUs >= 0) { 4047c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang int64_t firstTimeUs; 4057c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang firstTimeUs = mDiscontinuityAbsStartTimesUs.valueFor(strm.mCurDiscontinuitySeq); 4067c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang offsetTimeUs += strm.mLastDequeuedTimeUs - firstTimeUs; 4077c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang offsetTimeUs += strm.mLastSampleDurationUs; 4087c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } else { 4097c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang offsetTimeUs += strm.mLastSampleDurationUs; 4107c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 4117c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 4127c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mDiscontinuityOffsetTimesUs.add(discontinuitySeq, offsetTimeUs); 4137c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang strm.mCurDiscontinuitySeq = discontinuitySeq; 4147c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 415309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 416309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih int32_t discard = 0; 417309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih int64_t firstTimeUs; 418309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (mDiscontinuityAbsStartTimesUs.indexOfKey(strm.mCurDiscontinuitySeq) >= 0) { 419309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih int64_t durUs; // approximate sample duration 420309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (timeUs > strm.mLastDequeuedTimeUs) { 421309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih durUs = timeUs - strm.mLastDequeuedTimeUs; 422309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } else { 423309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih durUs = strm.mLastDequeuedTimeUs - timeUs; 424309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 425309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih strm.mLastSampleDurationUs = durUs; 426309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih firstTimeUs = mDiscontinuityAbsStartTimesUs.valueFor(strm.mCurDiscontinuitySeq); 427309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } else if ((*accessUnit)->meta()->findInt32("discard", &discard) && discard) { 428309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih firstTimeUs = timeUs; 429309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } else { 430309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mDiscontinuityAbsStartTimesUs.add(strm.mCurDiscontinuitySeq, timeUs); 431309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih firstTimeUs = timeUs; 432309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 433309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 434309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih strm.mLastDequeuedTimeUs = timeUs; 4350852843d304006e3ab333081fddda13b07193de8Robert Shih timeUs = calculateMediaTimeUs(firstTimeUs, timeUs, discontinuitySeq); 436dcb89b3b505522efde173c105a851c412f947178Chong Zhang 43725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("[%s] dequeueAccessUnit: time %lld us, original %lld us", 43825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang streamStr, (long long)timeUs, (long long)originalTimeUs); 439309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih (*accessUnit)->meta()->setInt64("timeUs", timeUs); 440dcb89b3b505522efde173c105a851c412f947178Chong Zhang mLastDequeuedTimeUs = timeUs; 441dcb89b3b505522efde173c105a851c412f947178Chong Zhang mRealTimeBaseUs = ALooper::GetNowUs() - timeUs; 442dcb89b3b505522efde173c105a851c412f947178Chong Zhang } else if (stream == STREAMTYPE_SUBTITLES) { 443b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih int32_t subtitleGeneration; 444b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih if ((*accessUnit)->meta()->findInt32("subtitleGeneration", &subtitleGeneration) 445b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih && subtitleGeneration != mSubtitleGeneration) { 446b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih return -EAGAIN; 447b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih }; 448dcb89b3b505522efde173c105a851c412f947178Chong Zhang (*accessUnit)->meta()->setInt32( 449dcb89b3b505522efde173c105a851c412f947178Chong Zhang "trackIndex", mPlaylist->getSelectedIndex()); 450dcb89b3b505522efde173c105a851c412f947178Chong Zhang (*accessUnit)->meta()->setInt64("baseUs", mRealTimeBaseUs); 4510852843d304006e3ab333081fddda13b07193de8Robert Shih } else if (stream == STREAMTYPE_METADATA) { 4520852843d304006e3ab333081fddda13b07193de8Robert Shih HLSTime mdTime((*accessUnit)->meta()); 4530852843d304006e3ab333081fddda13b07193de8Robert Shih if (mDiscontinuityAbsStartTimesUs.indexOfKey(mdTime.mSeq) < 0) { 4540852843d304006e3ab333081fddda13b07193de8Robert Shih packetSource->requeueAccessUnit((*accessUnit)); 4550852843d304006e3ab333081fddda13b07193de8Robert Shih return -EAGAIN; 4560852843d304006e3ab333081fddda13b07193de8Robert Shih } else { 4570852843d304006e3ab333081fddda13b07193de8Robert Shih int64_t firstTimeUs = mDiscontinuityAbsStartTimesUs.valueFor(mdTime.mSeq); 4580852843d304006e3ab333081fddda13b07193de8Robert Shih int64_t timeUs = calculateMediaTimeUs(firstTimeUs, mdTime.mTimeUs, mdTime.mSeq); 4590852843d304006e3ab333081fddda13b07193de8Robert Shih (*accessUnit)->meta()->setInt64("timeUs", timeUs); 4600852843d304006e3ab333081fddda13b07193de8Robert Shih (*accessUnit)->meta()->setInt64("baseUs", mRealTimeBaseUs); 4610852843d304006e3ab333081fddda13b07193de8Robert Shih } 462dcb89b3b505522efde173c105a851c412f947178Chong Zhang } 46314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else { 46414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGI("[%s] encountered error %d", streamStr, err); 46514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 46614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 46714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return err; 46814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 46914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 47014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::getStreamFormat(StreamType stream, sp<AMessage> *format) { 47114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (!(mStreamMask & stream)) { 47214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return UNKNOWN_ERROR; 47314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 47414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 47514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AnotherPacketSource> packetSource = mPacketSources.valueFor(stream); 47614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 47714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<MetaData> meta = packetSource->getFormat(); 47814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 47914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (meta == NULL) { 4807350b057ca864f5dc9e53d48e34710a8e81133f8Robert Shih return -EWOULDBLOCK; 48114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 48214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 4837c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (stream == STREAMTYPE_AUDIO) { 4847c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // set AAC input buffer size to 32K bytes (256kbps x 1sec) 4857c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang meta->setInt32(kKeyMaxInputSize, 32 * 1024); 486a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang } else if (stream == STREAMTYPE_VIDEO) { 487a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang meta->setInt32(kKeyMaxWidth, mMaxWidth); 488a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang meta->setInt32(kKeyMaxHeight, mMaxHeight); 4897c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 4907c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 49114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return convertMetaDataToMessage(meta, format); 492a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 493a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 4945abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhangsp<HTTPDownloader> LiveSession::getHTTPDownloader() { 4955abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang return new HTTPDownloader(mHTTPService, mExtraHeaders); 496a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang} 497a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 49814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::connectAsync( 499ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber const char *url, const KeyedVector<String8, String8> *headers) { 5001d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> msg = new AMessage(kWhatConnect, this); 501a44153c1a57202fb538659eb50706e60454d6273Andreas Huber msg->setString("url", url); 502ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber 503ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber if (headers != NULL) { 504ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber msg->setPointer( 505ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber "headers", 506ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber new KeyedVector<String8, String8>(*headers)); 507ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber } 508ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber 509a44153c1a57202fb538659eb50706e60454d6273Andreas Huber msg->post(); 510a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 511a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 51214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::disconnect() { 5131d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> msg = new AMessage(kWhatDisconnect, this); 514ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber 51514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AMessage> response; 51614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber status_t err = msg->postAndAwaitResponse(&response); 517ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber 51814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return err; 519a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 520a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 52114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::seekTo(int64_t timeUs) { 5221d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> msg = new AMessage(kWhatSeek, this); 523a44153c1a57202fb538659eb50706e60454d6273Andreas Huber msg->setInt64("timeUs", timeUs); 524a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 52514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AMessage> response; 52614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber status_t err = msg->postAndAwaitResponse(&response); 52714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 52814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return err; 529a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 530a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 5317c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangbool LiveSession::checkSwitchProgress( 5327c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AMessage> &stopParams, int64_t delayUs, bool *needResumeUntil) { 5337c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang AString newUri; 5347c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang CHECK(stopParams->findString("uri", &newUri)); 5357c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 5367c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang *needResumeUntil = false; 5377c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AMessage> firstNewMeta[kMaxStreams]; 5387c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang for (size_t i = 0; i < kMaxStreams; ++i) { 5397c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang StreamType stream = indexToType(i); 5407c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (!(mSwapMask & mNewStreamMask & stream) 5417c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang || (mStreams[i].mNewUri != newUri)) { 5427c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang continue; 5437c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 5447c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (stream == STREAMTYPE_SUBTITLES) { 5457c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang continue; 5467c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 5477c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AnotherPacketSource> &source = mPacketSources.editValueAt(i); 5487c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 5497c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // First, get latest dequeued meta, which is where the decoder is at. 5507c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // (when upswitching, we take the meta after a certain delay, so that 5517c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // the decoder is left with some cushion) 5527c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AMessage> lastDequeueMeta, lastEnqueueMeta; 5537c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (delayUs > 0) { 5547c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang lastDequeueMeta = source->getMetaAfterLastDequeued(delayUs); 555d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (lastDequeueMeta == NULL) { 556d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // this means we don't have enough cushion, try again later 557d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang ALOGV("[%s] up switching failed due to insufficient buffer", 55825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang getNameForStream(stream)); 559d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang return false; 560d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang } 5617c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } else { 562d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // It's okay for lastDequeueMeta to be NULL here, it means the 563d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // decoder hasn't even started dequeueing 5647c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang lastDequeueMeta = source->getLatestDequeuedMeta(); 5657c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 5667c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // Then, trim off packets at beginning of mPacketSources2 that's before 5677c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // the latest dequeued time. These samples are definitely too late. 568d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang firstNewMeta[i] = mPacketSources2.editValueAt(i) 569d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang ->trimBuffersBeforeMeta(lastDequeueMeta); 570d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang 5717c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // Now firstNewMeta[i] is the first sample after the trim. 5727c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // If it's NULL, we failed because dequeue already past all samples 5737c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // in mPacketSource2, we have to try again. 5747c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (firstNewMeta[i] == NULL) { 575d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang HLSTime dequeueTime(lastDequeueMeta); 5767c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGV("[%s] dequeue time (%d, %lld) past start time", 57725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang getNameForStream(stream), 578d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang dequeueTime.mSeq, (long long) dequeueTime.mTimeUs); 5797c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return false; 5807c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 5817c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 5827c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // Otherwise, we check if mPacketSources2 overlaps with what old fetcher 5837c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // already fetched, and see if we need to resumeUntil 5847c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang lastEnqueueMeta = source->getLatestEnqueuedMeta(); 5857c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // lastEnqueueMeta == NULL means old fetcher stopped at a discontinuity 5867c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // boundary, no need to resume as the content will look different anyways 5877c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (lastEnqueueMeta != NULL) { 588d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang HLSTime lastTime(lastEnqueueMeta), startTime(firstNewMeta[i]); 5897c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 5907c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // no need to resume old fetcher if new fetcher started in different 5917c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // discontinuity sequence, as the content will look different. 592d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang *needResumeUntil |= (startTime.mSeq == lastTime.mSeq 593d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang && startTime.mTimeUs - lastTime.mTimeUs > kResumeThresholdUs); 5947c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 595d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // update the stopTime for resumeUntil 596d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang stopParams->setInt32("discontinuitySeq", startTime.mSeq); 597d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang stopParams->setInt64(getKeyForStream(stream), startTime.mTimeUs); 5987c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 5997c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 6007c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 6017c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // if we're here, it means dequeue progress hasn't passed some samples in 6027c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // mPacketSource2, we can trim off the excess in mPacketSource. 6037c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // (old fetcher might still need to resumeUntil the start time of new fetcher) 6047c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang for (size_t i = 0; i < kMaxStreams; ++i) { 6057c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang StreamType stream = indexToType(i); 6067c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (!(mSwapMask & mNewStreamMask & stream) 607d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang || (newUri != mStreams[i].mNewUri) 608d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang || stream == STREAMTYPE_SUBTITLES) { 6097c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang continue; 6107c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 611d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang mPacketSources.valueFor(stream)->trimBuffersAfterMeta(firstNewMeta[i]); 6127c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 6137c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 6147c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // no resumeUntil if already underflow 6157c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang *needResumeUntil &= !mBuffering; 6167c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 6177c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return true; 6187c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang} 6197c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 620a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onMessageReceived(const sp<AMessage> &msg) { 621a44153c1a57202fb538659eb50706e60454d6273Andreas Huber switch (msg->what()) { 622a44153c1a57202fb538659eb50706e60454d6273Andreas Huber case kWhatConnect: 62314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 624a44153c1a57202fb538659eb50706e60454d6273Andreas Huber onConnect(msg); 625a44153c1a57202fb538659eb50706e60454d6273Andreas Huber break; 62614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 627a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 628a44153c1a57202fb538659eb50706e60454d6273Andreas Huber case kWhatDisconnect: 62914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 63014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->senderAwaitsResponse(&mDisconnectReplyID)); 63114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 63214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (mReconfigurationInProgress) { 63314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 63414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 63514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 63614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber finishDisconnect(); 637a44153c1a57202fb538659eb50706e60454d6273Andreas Huber break; 63814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 639a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 64014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case kWhatSeek: 64114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 642a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar if (mReconfigurationInProgress) { 643800599cdd50737de1cde483a34b39923750b0658Robert Shih msg->post(50000); 644a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar break; 645800599cdd50737de1cde483a34b39923750b0658Robert Shih } 646a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar 647a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar CHECK(msg->senderAwaitsResponse(&mSeekReplyID)); 648a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar mSeekReply = new AMessage; 649a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar 650a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar onSeek(msg); 65114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 65214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 65314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 65414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case kWhatFetcherNotify: 65514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 65614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int32_t what; 65714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->findInt32("what", &what)); 65814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 65914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber switch (what) { 66014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case PlaylistFetcher::kWhatStarted: 66114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 66214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case PlaylistFetcher::kWhatPaused: 66314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case PlaylistFetcher::kWhatStopped: 66414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 665a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang AString uri; 666a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang CHECK(msg->findString("uri", &uri)); 667a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang ssize_t index = mFetcherInfos.indexOfKey(uri); 668a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (index < 0) { 669a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // ignore msgs from fetchers that's already gone 670a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang break; 671a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 672a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 67325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("fetcher-%d %s", 67425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang mFetcherInfos[index].mFetcher->getFetcherID(), 67525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang what == PlaylistFetcher::kWhatPaused ? 67625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang "paused" : "stopped"); 67725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 67814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (what == PlaylistFetcher::kWhatStopped) { 679964adb17885185808398507d2de88665fe193ee2Chong Zhang mFetcherLooper->unregisterHandler( 680964adb17885185808398507d2de88665fe193ee2Chong Zhang mFetcherInfos[index].mFetcher->id()); 681964adb17885185808398507d2de88665fe193ee2Chong Zhang mFetcherInfos.removeItemsAt(index); 682a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } else if (what == PlaylistFetcher::kWhatPaused) { 683a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang int32_t seekMode; 684a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang CHECK(msg->findInt32("seekMode", &seekMode)); 685a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang for (size_t i = 0; i < kMaxStreams; ++i) { 686a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (mStreams[i].mUri == uri) { 687a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mStreams[i].mSeekMode = (SeekMode) seekMode; 688a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 689309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 69014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 69114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 69214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (mContinuation != NULL) { 69314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK_GT(mContinuationCounter, 0); 69414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (--mContinuationCounter == 0) { 69514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mContinuation->post(); 69614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 69725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("%zu fetcher(s) left", mContinuationCounter); 69814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 69914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 70014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 70114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 70214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case PlaylistFetcher::kWhatDurationUpdate: 70314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 70414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber AString uri; 70514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->findString("uri", &uri)); 70614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 70714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int64_t durationUs; 70814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->findInt64("durationUs", &durationUs)); 70914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 710964adb17885185808398507d2de88665fe193ee2Chong Zhang ssize_t index = mFetcherInfos.indexOfKey(uri); 711964adb17885185808398507d2de88665fe193ee2Chong Zhang if (index >= 0) { 712964adb17885185808398507d2de88665fe193ee2Chong Zhang FetcherInfo *info = &mFetcherInfos.editValueFor(uri); 713964adb17885185808398507d2de88665fe193ee2Chong Zhang info->mDurationUs = durationUs; 714964adb17885185808398507d2de88665fe193ee2Chong Zhang } 71514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 71614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 71714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 7187c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang case PlaylistFetcher::kWhatTargetDurationUpdate: 7197c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang { 7207c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang int64_t targetDurationUs; 7217c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang CHECK(msg->findInt64("targetDurationUs", &targetDurationUs)); 722d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang mUpSwitchMark = min(kUpSwitchMarkUs, targetDurationUs * 7 / 4); 723765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang mDownSwitchMark = min(kDownSwitchMarkUs, targetDurationUs * 9 / 4); 724765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang mUpSwitchMargin = min(kUpSwitchMarginUs, targetDurationUs); 7257c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang break; 7267c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 7277c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 72814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case PlaylistFetcher::kWhatError: 72914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 73014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber status_t err; 73114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->findInt32("err", &err)); 73214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 73314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGE("XXX Received error %d from PlaylistFetcher.", err); 73414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 73515f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih // handle EOS on subtitle tracks independently 73615f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih AString uri; 73715f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih if (err == ERROR_END_OF_STREAM && msg->findString("uri", &uri)) { 73815f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih ssize_t i = mFetcherInfos.indexOfKey(uri); 73915f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih if (i >= 0) { 74015f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih const sp<PlaylistFetcher> &fetcher = mFetcherInfos.valueAt(i).mFetcher; 74115f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih if (fetcher != NULL) { 74215f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih uint32_t type = fetcher->getStreamTypeMask(); 74315f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih if (type == STREAMTYPE_SUBTITLES) { 74415f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih mPacketSources.valueFor( 74515f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih STREAMTYPE_SUBTITLES)->signalEOS(err);; 74615f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih break; 74715f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih } 74815f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih } 74915f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih } 75015f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih } 75115f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih 7525ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // remember the failure index (as mCurBandwidthIndex will be restored 7535ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // after cancelBandwidthSwitch()), and record last fail time 7545ef659e010e90175eb5282d9642a02f6105189bfChong Zhang size_t failureIndex = mCurBandwidthIndex; 7555ef659e010e90175eb5282d9642a02f6105189bfChong Zhang mBandwidthItems.editItemAt( 7565ef659e010e90175eb5282d9642a02f6105189bfChong Zhang failureIndex).mLastFailureUs = ALooper::GetNowUs(); 7575ef659e010e90175eb5282d9642a02f6105189bfChong Zhang 7585ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (mSwitchInProgress) { 7595ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // if error happened when we switch to a variant, try fallback 7605ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // to other variant to save the session 7615ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (tryBandwidthFallback()) { 7625ef659e010e90175eb5282d9642a02f6105189bfChong Zhang break; 7635ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } 7645ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } 7655ef659e010e90175eb5282d9642a02f6105189bfChong Zhang 76614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (mInPreparationPhase) { 76714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber postPrepared(err); 76814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 76914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 7701543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih cancelBandwidthSwitch(); 7711543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 77214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mPacketSources.valueFor(STREAMTYPE_AUDIO)->signalEOS(err); 77314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 77414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mPacketSources.valueFor(STREAMTYPE_VIDEO)->signalEOS(err); 77514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 77614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mPacketSources.valueFor( 77714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber STREAMTYPE_SUBTITLES)->signalEOS(err); 77814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 7797c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang postError(err); 7807c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang break; 7817c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 7827c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 7837c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang case PlaylistFetcher::kWhatStopReached: 7847c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang { 7857c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGV("kWhatStopReached"); 7867c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 787d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang AString oldUri; 788d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang CHECK(msg->findString("uri", &oldUri)); 7897c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 790d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang ssize_t index = mFetcherInfos.indexOfKey(oldUri); 7917c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (index < 0) { 7927c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang break; 7937c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 7947c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 795d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang tryToFinishBandwidthSwitch(oldUri); 79614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 79714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 79814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 7991543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih case PlaylistFetcher::kWhatStartedAt: 8001543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih { 8011543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih int32_t switchGeneration; 8021543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih CHECK(msg->findInt32("switchGeneration", &switchGeneration)); 8031543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 80425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("kWhatStartedAt: switchGen=%d, mSwitchGen=%d", 80525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang switchGeneration, mSwitchGeneration); 80625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 8071543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih if (switchGeneration != mSwitchGeneration) { 8081543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih break; 8091543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 8101543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 811a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang AString uri; 812a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang CHECK(msg->findString("uri", &uri)); 8137c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 8147c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // mark new fetcher mToBeResumed 815a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang ssize_t index = mFetcherInfos.indexOfKey(uri); 816a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (index >= 0) { 817a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mFetcherInfos.editValueAt(index).mToBeResumed = true; 818a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 819a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 8207c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // temporarily disable packet sources to be swapped to prevent 8217c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // NuPlayerDecoder from dequeuing while we check progress 8227c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang for (size_t i = 0; i < mPacketSources.size(); ++i) { 8237c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if ((mSwapMask & mPacketSources.keyAt(i)) 8247c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang && uri == mStreams[i].mNewUri) { 8257c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mPacketSources.editValueAt(i)->enable(false); 8261543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 8271543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 8287c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang bool switchUp = (mCurBandwidthIndex > mOrigBandwidthIndex); 8297c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // If switching up, require a cushion bigger than kUnderflowMark 8307c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // to avoid buffering immediately after the switch. 8317c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // (If we don't have that cushion we'd rather cancel and try again.) 832765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang int64_t delayUs = switchUp ? (kUnderflowMarkUs + 1000000ll) : 0; 8337c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang bool needResumeUntil = false; 8347c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AMessage> stopParams = msg; 8357c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (checkSwitchProgress(stopParams, delayUs, &needResumeUntil)) { 8367c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // playback time hasn't passed startAt time 8377c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (!needResumeUntil) { 83825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("finish switch"); 8397c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang for (size_t i = 0; i < kMaxStreams; ++i) { 8407c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if ((mSwapMask & indexToType(i)) 8417c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang && uri == mStreams[i].mNewUri) { 8427c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // have to make a copy of mStreams[i].mUri because 8437c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // tryToFinishBandwidthSwitch is modifying mStreams[] 8447c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang AString oldURI = mStreams[i].mUri; 8457c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang tryToFinishBandwidthSwitch(oldURI); 8467c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang break; 8477c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 8487c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 8497c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } else { 8507c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // startAt time is after last enqueue time 8517c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // Resume fetcher for the original variant; the resumed fetcher should 8527c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // continue until the timestamps found in msg, which is stored by the 8537c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // new fetcher to indicate where the new variant has started buffering. 85425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("finish switch with resumeUntilAsync"); 8557c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang for (size_t i = 0; i < mFetcherInfos.size(); i++) { 8567c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang const FetcherInfo &info = mFetcherInfos.valueAt(i); 8577c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (info.mToBeRemoved) { 8587c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang info.mFetcher->resumeUntilAsync(stopParams); 8597c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 8607c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 8617c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 8627c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } else { 8637c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // playback time passed startAt time 8647c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (switchUp) { 8657c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // if switching up, cancel and retry if condition satisfies again 86625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("cancel up switch because we're too late"); 8677c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang cancelBandwidthSwitch(true /* resume */); 8687c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } else { 86925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("retry down switch at next sample"); 8707c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang resumeFetcher(uri, mSwapMask, -1, true /* newUri */); 8717c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 8727c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 8737c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // re-enable all packet sources 8747c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang for (size_t i = 0; i < mPacketSources.size(); ++i) { 8757c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mPacketSources.editValueAt(i)->enable(true); 8767c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 8777c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 8781543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih break; 8791543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 8801543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 8815abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang case PlaylistFetcher::kWhatPlaylistFetched: 8825abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang { 8835abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang onMasterPlaylistFetched(msg); 8845abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang break; 8855abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } 8865abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 8870852843d304006e3ab333081fddda13b07193de8Robert Shih case PlaylistFetcher::kWhatMetadataDetected: 8880852843d304006e3ab333081fddda13b07193de8Robert Shih { 8890852843d304006e3ab333081fddda13b07193de8Robert Shih if (!mHasMetadata) { 8900852843d304006e3ab333081fddda13b07193de8Robert Shih mHasMetadata = true; 8910852843d304006e3ab333081fddda13b07193de8Robert Shih sp<AMessage> notify = mNotify->dup(); 8920852843d304006e3ab333081fddda13b07193de8Robert Shih notify->setInt32("what", kWhatMetadataDetected); 8930852843d304006e3ab333081fddda13b07193de8Robert Shih notify->post(); 8940852843d304006e3ab333081fddda13b07193de8Robert Shih } 8950852843d304006e3ab333081fddda13b07193de8Robert Shih break; 8960852843d304006e3ab333081fddda13b07193de8Robert Shih } 8970852843d304006e3ab333081fddda13b07193de8Robert Shih 89814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber default: 89914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber TRESPASS(); 90014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 90114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 90214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 90314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 90414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 905dcb89b3b505522efde173c105a851c412f947178Chong Zhang case kWhatChangeConfiguration: 906dcb89b3b505522efde173c105a851c412f947178Chong Zhang { 907dcb89b3b505522efde173c105a851c412f947178Chong Zhang onChangeConfiguration(msg); 908dcb89b3b505522efde173c105a851c412f947178Chong Zhang break; 909dcb89b3b505522efde173c105a851c412f947178Chong Zhang } 910dcb89b3b505522efde173c105a851c412f947178Chong Zhang 91114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case kWhatChangeConfiguration2: 91214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 91314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber onChangeConfiguration2(msg); 91414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 91514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 91614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 91714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case kWhatChangeConfiguration3: 91814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 91914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber onChangeConfiguration3(msg); 92014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 92114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 92214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 923964adb17885185808398507d2de88665fe193ee2Chong Zhang case kWhatPollBuffering: 9240ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih { 925964adb17885185808398507d2de88665fe193ee2Chong Zhang int32_t generation; 926964adb17885185808398507d2de88665fe193ee2Chong Zhang CHECK(msg->findInt32("generation", &generation)); 927964adb17885185808398507d2de88665fe193ee2Chong Zhang if (generation == mPollBufferingGeneration) { 928964adb17885185808398507d2de88665fe193ee2Chong Zhang onPollBuffering(); 929964adb17885185808398507d2de88665fe193ee2Chong Zhang } 9300ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih break; 9310ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih } 9320ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih 933a44153c1a57202fb538659eb50706e60454d6273Andreas Huber default: 934a44153c1a57202fb538659eb50706e60454d6273Andreas Huber TRESPASS(); 935a44153c1a57202fb538659eb50706e60454d6273Andreas Huber break; 936a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 937a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 938a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 939a44153c1a57202fb538659eb50706e60454d6273Andreas Huber// static 9405ef659e010e90175eb5282d9642a02f6105189bfChong Zhangbool LiveSession::isBandwidthValid(const BandwidthItem &item) { 9415ef659e010e90175eb5282d9642a02f6105189bfChong Zhang static const int64_t kBlacklistWindowUs = 300 * 1000000ll; 9425ef659e010e90175eb5282d9642a02f6105189bfChong Zhang return item.mLastFailureUs < 0 9435ef659e010e90175eb5282d9642a02f6105189bfChong Zhang || ALooper::GetNowUs() - item.mLastFailureUs > kBlacklistWindowUs; 9445ef659e010e90175eb5282d9642a02f6105189bfChong Zhang} 9455ef659e010e90175eb5282d9642a02f6105189bfChong Zhang 9465ef659e010e90175eb5282d9642a02f6105189bfChong Zhang// static 947a44153c1a57202fb538659eb50706e60454d6273Andreas Huberint LiveSession::SortByBandwidth(const BandwidthItem *a, const BandwidthItem *b) { 948a44153c1a57202fb538659eb50706e60454d6273Andreas Huber if (a->mBandwidth < b->mBandwidth) { 949a44153c1a57202fb538659eb50706e60454d6273Andreas Huber return -1; 950a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } else if (a->mBandwidth == b->mBandwidth) { 951a44153c1a57202fb538659eb50706e60454d6273Andreas Huber return 0; 952a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 953a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 954a44153c1a57202fb538659eb50706e60454d6273Andreas Huber return 1; 955a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 956a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 9578ca002eedc747dd854b61cbe364b52c06869273fRobert Shih// static 9588ca002eedc747dd854b61cbe364b52c06869273fRobert ShihLiveSession::StreamType LiveSession::indexToType(int idx) { 9590852843d304006e3ab333081fddda13b07193de8Robert Shih CHECK(idx >= 0 && idx < kNumSources); 9608ca002eedc747dd854b61cbe364b52c06869273fRobert Shih return (StreamType)(1 << idx); 9618ca002eedc747dd854b61cbe364b52c06869273fRobert Shih} 9628ca002eedc747dd854b61cbe364b52c06869273fRobert Shih 963f69c996864844e8f669308af8412cede043062a2Robert Shih// static 964f69c996864844e8f669308af8412cede043062a2Robert Shihssize_t LiveSession::typeToIndex(int32_t type) { 965f69c996864844e8f669308af8412cede043062a2Robert Shih switch (type) { 966f69c996864844e8f669308af8412cede043062a2Robert Shih case STREAMTYPE_AUDIO: 967f69c996864844e8f669308af8412cede043062a2Robert Shih return 0; 968f69c996864844e8f669308af8412cede043062a2Robert Shih case STREAMTYPE_VIDEO: 969f69c996864844e8f669308af8412cede043062a2Robert Shih return 1; 970f69c996864844e8f669308af8412cede043062a2Robert Shih case STREAMTYPE_SUBTITLES: 971f69c996864844e8f669308af8412cede043062a2Robert Shih return 2; 9720852843d304006e3ab333081fddda13b07193de8Robert Shih case STREAMTYPE_METADATA: 9730852843d304006e3ab333081fddda13b07193de8Robert Shih return 3; 974f69c996864844e8f669308af8412cede043062a2Robert Shih default: 975f69c996864844e8f669308af8412cede043062a2Robert Shih return -1; 976f69c996864844e8f669308af8412cede043062a2Robert Shih }; 977f69c996864844e8f669308af8412cede043062a2Robert Shih return -1; 978f69c996864844e8f669308af8412cede043062a2Robert Shih} 979f69c996864844e8f669308af8412cede043062a2Robert Shih 980a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onConnect(const sp<AMessage> &msg) { 9815abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang CHECK(msg->findString("url", &mMasterURL)); 9825abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 9835abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // TODO currently we don't know if we are coming here from incognito mode 9845abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang ALOGI("onConnect %s", uriDebugString(mMasterURL).c_str()); 985a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 986ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber KeyedVector<String8, String8> *headers = NULL; 987ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber if (!msg->findPointer("headers", (void **)&headers)) { 988ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber mExtraHeaders.clear(); 989ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber } else { 990ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber mExtraHeaders = *headers; 991ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber 992ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber delete headers; 993ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber headers = NULL; 994ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber } 995ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber 996964adb17885185808398507d2de88665fe193ee2Chong Zhang // create looper for fetchers 997964adb17885185808398507d2de88665fe193ee2Chong Zhang if (mFetcherLooper == NULL) { 998964adb17885185808398507d2de88665fe193ee2Chong Zhang mFetcherLooper = new ALooper(); 999964adb17885185808398507d2de88665fe193ee2Chong Zhang 1000964adb17885185808398507d2de88665fe193ee2Chong Zhang mFetcherLooper->setName("Fetcher"); 1001964adb17885185808398507d2de88665fe193ee2Chong Zhang mFetcherLooper->start(false, false); 1002964adb17885185808398507d2de88665fe193ee2Chong Zhang } 1003964adb17885185808398507d2de88665fe193ee2Chong Zhang 10045abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // create fetcher to fetch the master playlist 10055abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang addFetcher(mMasterURL.c_str())->fetchPlaylistAsync(); 10065abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang} 10075abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 10085abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhangvoid LiveSession::onMasterPlaylistFetched(const sp<AMessage> &msg) { 10095abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang AString uri; 10105abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang CHECK(msg->findString("uri", &uri)); 10115abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang ssize_t index = mFetcherInfos.indexOfKey(uri); 10125abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang if (index < 0) { 10135abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang ALOGW("fetcher for master playlist is gone."); 10145abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang return; 10155abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } 10165abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 10175abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // no longer useful, remove 10185abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang mFetcherLooper->unregisterHandler(mFetcherInfos[index].mFetcher->id()); 10195abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang mFetcherInfos.removeItemsAt(index); 10205abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 10215abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang CHECK(msg->findObject("playlist", (sp<RefBase> *)&mPlaylist)); 10225abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang if (mPlaylist == NULL) { 10235abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang ALOGE("unable to fetch master playlist %s.", 10245abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang uriDebugString(mMasterURL).c_str()); 10255abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 10265abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang postPrepared(ERROR_IO); 10275abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang return; 10285abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } 102914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // We trust the content provider to make a reasonable choice of preferred 103014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // initial bandwidth by listing it first in the variant playlist. 103114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // At startup we really don't have a good estimate on the available 103214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // network bandwidth since we haven't tranferred any data yet. Once 103314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // we have we can make a better informed choice. 103414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber size_t initialBandwidth = 0; 103514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber size_t initialBandwidthIndex = 0; 103614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 1037a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang int32_t maxWidth = 0; 1038a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang int32_t maxHeight = 0; 1039a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang 104014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (mPlaylist->isVariantPlaylist()) { 1041d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang Vector<BandwidthItem> itemsWithVideo; 104214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber for (size_t i = 0; i < mPlaylist->size(); ++i) { 1043a44153c1a57202fb538659eb50706e60454d6273Andreas Huber BandwidthItem item; 1044a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 104514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber item.mPlaylistIndex = i; 10465ef659e010e90175eb5282d9642a02f6105189bfChong Zhang item.mLastFailureUs = -1ll; 104714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 1048a44153c1a57202fb538659eb50706e60454d6273Andreas Huber sp<AMessage> meta; 104914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber AString uri; 105014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mPlaylist->itemAt(i, &uri, &meta); 1051a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1052a44153c1a57202fb538659eb50706e60454d6273Andreas Huber CHECK(meta->findInt32("bandwidth", (int32_t *)&item.mBandwidth)); 1053a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1054a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang int32_t width, height; 1055a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang if (meta->findInt32("width", &width)) { 1056a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang maxWidth = max(maxWidth, width); 1057a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang } 1058a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang if (meta->findInt32("height", &height)) { 1059a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang maxHeight = max(maxHeight, height); 1060a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang } 1061a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang 1062a44153c1a57202fb538659eb50706e60454d6273Andreas Huber mBandwidthItems.push(item); 1063d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (mPlaylist->hasType(i, "video")) { 1064d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang itemsWithVideo.push(item); 1065d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang } 1066d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang } 1067d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // remove the audio-only variants if we have at least one with video 1068d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (!itemsWithVideo.empty() 1069d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang && itemsWithVideo.size() < mBandwidthItems.size()) { 1070d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang mBandwidthItems.clear(); 1071d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang for (size_t i = 0; i < itemsWithVideo.size(); ++i) { 1072d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang mBandwidthItems.push(itemsWithVideo[i]); 1073d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang } 1074a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1075a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1076a44153c1a57202fb538659eb50706e60454d6273Andreas Huber CHECK_GT(mBandwidthItems.size(), 0u); 1077d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang initialBandwidth = mBandwidthItems[0].mBandwidth; 1078a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1079a44153c1a57202fb538659eb50706e60454d6273Andreas Huber mBandwidthItems.sort(SortByBandwidth); 108014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 108114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber for (size_t i = 0; i < mBandwidthItems.size(); ++i) { 108214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (mBandwidthItems.itemAt(i).mBandwidth == initialBandwidth) { 108314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber initialBandwidthIndex = i; 108414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 108514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 108614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 108714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else { 108814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // dummy item. 108914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber BandwidthItem item; 109014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber item.mPlaylistIndex = 0; 109114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber item.mBandwidth = 0; 109214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mBandwidthItems.push(item); 1093a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1094a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1095a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang mMaxWidth = maxWidth > 0 ? maxWidth : mMaxWidth; 1096a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang mMaxHeight = maxHeight > 0 ? maxHeight : mMaxHeight; 1097a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang 1098309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mPlaylist->pickRandomMediaItems(); 1099dcb89b3b505522efde173c105a851c412f947178Chong Zhang changeConfiguration( 1100309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 0ll /* timeUs */, initialBandwidthIndex, false /* pickTrack */); 1101a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 1102a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 110314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::finishDisconnect() { 1104a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang ALOGV("finishDisconnect"); 1105a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 110614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // No reconfiguration is currently pending, make sure none will trigger 110714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // during disconnection either. 11081543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih cancelBandwidthSwitch(); 11091543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 1110964adb17885185808398507d2de88665fe193ee2Chong Zhang // cancel buffer polling 1111964adb17885185808398507d2de88665fe193ee2Chong Zhang cancelPollBuffering(); 11120ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih 11135abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // TRICKY: don't wait for all fetcher to be stopped when disconnecting 11145abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // 11155abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // Some fetchers might be stuck in connect/getSize at this point. These 11165abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // operations will eventually timeout (as we have a timeout set in 11175abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // MediaHTTPConnection), but we don't want to block the main UI thread 11185abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // until then. Here we just need to make sure we clear all references 11195abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // to the fetchers, so that when they finally exit from the blocking 11205abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // operation, they can be destructed. 11215abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // 11225abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // There is one very tricky point though. For this scheme to work, the 11235abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // fecther must hold a reference to LiveSession, so that LiveSession is 11245abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // destroyed after fetcher. Otherwise LiveSession would get stuck in its 11255abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // own destructor when it waits for mFetcherLooper to stop, which still 11265abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // blocks main UI thread. 112714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber for (size_t i = 0; i < mFetcherInfos.size(); ++i) { 112814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mFetcherInfos.valueAt(i).mFetcher->stopAsync(); 11295abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang mFetcherLooper->unregisterHandler( 11305abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang mFetcherInfos.valueAt(i).mFetcher->id()); 113114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 11325abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang mFetcherInfos.clear(); 113314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 113414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mPacketSources.valueFor(STREAMTYPE_AUDIO)->signalEOS(ERROR_END_OF_STREAM); 113514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mPacketSources.valueFor(STREAMTYPE_VIDEO)->signalEOS(ERROR_END_OF_STREAM); 113614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 113714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mPacketSources.valueFor( 113814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber STREAMTYPE_SUBTITLES)->signalEOS(ERROR_END_OF_STREAM); 113914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 114014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AMessage> response = new AMessage; 114114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber response->setInt32("err", OK); 114214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 114314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber response->postReply(mDisconnectReplyID); 1144c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang mDisconnectReplyID.clear(); 114514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 114614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 114714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubersp<PlaylistFetcher> LiveSession::addFetcher(const char *uri) { 114814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ssize_t index = mFetcherInfos.indexOfKey(uri); 114914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 115014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (index >= 0) { 115114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return NULL; 115214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 115314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 11541d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> notify = new AMessage(kWhatFetcherNotify, this); 115514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->setString("uri", uri); 11561543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih notify->setInt32("switchGeneration", mSwitchGeneration); 115714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 115814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber FetcherInfo info; 115925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang info.mFetcher = new PlaylistFetcher( 116025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang notify, this, uri, mCurBandwidthIndex, mSubtitleGeneration); 116114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber info.mDurationUs = -1ll; 11621543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih info.mToBeRemoved = false; 1163a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang info.mToBeResumed = false; 1164964adb17885185808398507d2de88665fe193ee2Chong Zhang mFetcherLooper->registerHandler(info.mFetcher); 116514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 116614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mFetcherInfos.add(uri, info); 116714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 116814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return info.mFetcher; 1169a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 1170a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1171b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe#if 0 1172a44153c1a57202fb538659eb50706e60454d6273Andreas Huberstatic double uniformRand() { 1173a44153c1a57202fb538659eb50706e60454d6273Andreas Huber return (double)rand() / RAND_MAX; 1174a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 1175b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe#endif 1176a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 11770852843d304006e3ab333081fddda13b07193de8Robert Shihbool LiveSession::UriIsSameAsIndex(const AString &uri, int32_t i, bool newUri) { 11780852843d304006e3ab333081fddda13b07193de8Robert Shih ALOGI("[timed_id3] i %d UriIsSameAsIndex newUri %s, %s", i, 11790852843d304006e3ab333081fddda13b07193de8Robert Shih newUri ? "true" : "false", 11800852843d304006e3ab333081fddda13b07193de8Robert Shih newUri ? mStreams[i].mNewUri.c_str() : mStreams[i].mUri.c_str()); 11810852843d304006e3ab333081fddda13b07193de8Robert Shih return i >= 0 11820852843d304006e3ab333081fddda13b07193de8Robert Shih && ((!newUri && uri == mStreams[i].mUri) 11830852843d304006e3ab333081fddda13b07193de8Robert Shih || (newUri && uri == mStreams[i].mNewUri)); 11840852843d304006e3ab333081fddda13b07193de8Robert Shih} 11850852843d304006e3ab333081fddda13b07193de8Robert Shih 11860852843d304006e3ab333081fddda13b07193de8Robert Shihsp<AnotherPacketSource> LiveSession::getPacketSourceForStreamIndex( 11870852843d304006e3ab333081fddda13b07193de8Robert Shih size_t trackIndex, bool newUri) { 11880852843d304006e3ab333081fddda13b07193de8Robert Shih StreamType type = indexToType(trackIndex); 11890852843d304006e3ab333081fddda13b07193de8Robert Shih sp<AnotherPacketSource> source = NULL; 11900852843d304006e3ab333081fddda13b07193de8Robert Shih if (newUri) { 11910852843d304006e3ab333081fddda13b07193de8Robert Shih source = mPacketSources2.valueFor(type); 11920852843d304006e3ab333081fddda13b07193de8Robert Shih source->clear(); 11930852843d304006e3ab333081fddda13b07193de8Robert Shih } else { 11940852843d304006e3ab333081fddda13b07193de8Robert Shih source = mPacketSources.valueFor(type); 11950852843d304006e3ab333081fddda13b07193de8Robert Shih }; 11960852843d304006e3ab333081fddda13b07193de8Robert Shih return source; 11970852843d304006e3ab333081fddda13b07193de8Robert Shih} 11980852843d304006e3ab333081fddda13b07193de8Robert Shih 11990852843d304006e3ab333081fddda13b07193de8Robert Shihsp<AnotherPacketSource> LiveSession::getMetadataSource( 12000852843d304006e3ab333081fddda13b07193de8Robert Shih sp<AnotherPacketSource> sources[kNumSources], uint32_t streamMask, bool newUri) { 12010852843d304006e3ab333081fddda13b07193de8Robert Shih // todo: One case where the following strategy can fail is when audio and video 12020852843d304006e3ab333081fddda13b07193de8Robert Shih // are in separate playlists, both are transport streams, and the metadata 12030852843d304006e3ab333081fddda13b07193de8Robert Shih // is actually contained in the audio stream. 12040852843d304006e3ab333081fddda13b07193de8Robert Shih ALOGV("[timed_id3] getMetadataSourceForUri streamMask %x newUri %s", 12050852843d304006e3ab333081fddda13b07193de8Robert Shih streamMask, newUri ? "true" : "false"); 12060852843d304006e3ab333081fddda13b07193de8Robert Shih 12070852843d304006e3ab333081fddda13b07193de8Robert Shih if ((sources[kVideoIndex] != NULL) // video fetcher; or ... 12080852843d304006e3ab333081fddda13b07193de8Robert Shih || (!(streamMask & STREAMTYPE_VIDEO) && sources[kAudioIndex] != NULL)) { 12090852843d304006e3ab333081fddda13b07193de8Robert Shih // ... audio fetcher for audio only variant 12100852843d304006e3ab333081fddda13b07193de8Robert Shih return getPacketSourceForStreamIndex(kMetaDataIndex, newUri); 12110852843d304006e3ab333081fddda13b07193de8Robert Shih } 12120852843d304006e3ab333081fddda13b07193de8Robert Shih 12130852843d304006e3ab333081fddda13b07193de8Robert Shih return NULL; 12140852843d304006e3ab333081fddda13b07193de8Robert Shih} 12150852843d304006e3ab333081fddda13b07193de8Robert Shih 12167c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangbool LiveSession::resumeFetcher( 12177c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang const AString &uri, uint32_t streamMask, int64_t timeUs, bool newUri) { 12187c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ssize_t index = mFetcherInfos.indexOfKey(uri); 12197c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (index < 0) { 12207c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGE("did not find fetcher for uri: %s", uri.c_str()); 12217c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return false; 12227c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 12237c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 12247c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang bool resume = false; 12250852843d304006e3ab333081fddda13b07193de8Robert Shih sp<AnotherPacketSource> sources[kNumSources]; 12267c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang for (size_t i = 0; i < kMaxStreams; ++i) { 12270852843d304006e3ab333081fddda13b07193de8Robert Shih if ((streamMask & indexToType(i)) && UriIsSameAsIndex(uri, i, newUri)) { 12287c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang resume = true; 12290852843d304006e3ab333081fddda13b07193de8Robert Shih sources[i] = getPacketSourceForStreamIndex(i, newUri); 12307c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 12317c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 12327c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 12337c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (resume) { 123425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang sp<PlaylistFetcher> &fetcher = mFetcherInfos.editValueAt(index).mFetcher; 12357c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang SeekMode seekMode = newUri ? kSeekModeNextSample : kSeekModeExactPosition; 123625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 123725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("resuming fetcher-%d, timeUs=%lld, seekMode=%d", 123825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang fetcher->getFetcherID(), (long long)timeUs, seekMode); 123925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 124025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang fetcher->startAsync( 12417c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sources[kAudioIndex], 12427c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sources[kVideoIndex], 12437c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sources[kSubtitleIndex], 12440852843d304006e3ab333081fddda13b07193de8Robert Shih getMetadataSource(sources, streamMask, newUri), 12457c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang timeUs, -1, -1, seekMode); 12467c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 12477c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 12487c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return resume; 12497c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang} 12507c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 1251a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhangfloat LiveSession::getAbortThreshold( 1252a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang ssize_t currentBWIndex, ssize_t targetBWIndex) const { 1253a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang float abortThreshold = -1.0f; 1254a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (currentBWIndex > 0 && targetBWIndex < currentBWIndex) { 1255a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang /* 1256a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang If we're switching down, we need to decide whether to 1257a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1258a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1) finish last segment of high-bandwidth variant, or 1259a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 2) abort last segment of high-bandwidth variant, and fetch an 1260a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang overlapping portion from low-bandwidth variant. 1261a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1262a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang Here we try to maximize the amount of buffer left when the 1263a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang switch point is met. Given the following parameters: 1264a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1265a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang B: our current buffering level in seconds 1266a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang T: target duration in seconds 1267a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang X: sample duration in seconds remain to fetch in last segment 1268a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang bw0: bandwidth of old variant (as specified in playlist) 1269a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang bw1: bandwidth of new variant (as specified in playlist) 1270a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang bw: measured bandwidth available 1271a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1272a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang If we choose 1), when switch happens at the end of current 1273a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang segment, our buffering will be 1274a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang B + X - X * bw0 / bw 1275a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1276a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang If we choose 2), when switch happens where we aborted current 1277a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang segment, our buffering will be 1278a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang B - (T - X) * bw1 / bw 1279a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1280a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang We should only choose 1) if 1281a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang X/T < bw1 / (bw1 + bw0 - bw) 1282a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang */ 1283a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 12845ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // abort old bandwidth immediately if bandwidth is fluctuating a lot. 12855ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // our estimate could be far off, and fetching old bandwidth could 12865ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // take too long. 12875ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (!mLastBandwidthStable) { 12885ef659e010e90175eb5282d9642a02f6105189bfChong Zhang return 0.0f; 12895ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } 12905ef659e010e90175eb5282d9642a02f6105189bfChong Zhang 12917c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // Taking the measured current bandwidth at 50% face value only, 12927c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // as our bandwidth estimation is a lagging indicator. Being 12937c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // conservative on this, we prefer switching to lower bandwidth 12947c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // unless we're really confident finishing up the last segment 12957c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // of higher bandwidth will be fast. 1296a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang CHECK(mLastBandwidthBps >= 0); 1297a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang abortThreshold = 1298a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang (float)mBandwidthItems.itemAt(targetBWIndex).mBandwidth 1299a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang / ((float)mBandwidthItems.itemAt(targetBWIndex).mBandwidth 1300a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang + (float)mBandwidthItems.itemAt(currentBWIndex).mBandwidth 13017c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang - (float)mLastBandwidthBps * 0.5f); 1302a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (abortThreshold < 0.0f) { 1303a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang abortThreshold = -1.0f; // do not abort 1304a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 1305a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang ALOGV("Switching Down: bps %ld => %ld, measured %d, abort ratio %.2f", 1306a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mBandwidthItems.itemAt(currentBWIndex).mBandwidth, 1307a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mBandwidthItems.itemAt(targetBWIndex).mBandwidth, 1308a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mLastBandwidthBps, 1309a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang abortThreshold); 1310a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 1311a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang return abortThreshold; 1312a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang} 1313a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1314538b6d22a3578c0201d48f8548289aa254d81484Chong Zhangvoid LiveSession::addBandwidthMeasurement(size_t numBytes, int64_t delayUs) { 1315538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mBandwidthEstimator->addBandwidthMeasurement(numBytes, delayUs); 1316538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang} 1317538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 13185ef659e010e90175eb5282d9642a02f6105189bfChong Zhangssize_t LiveSession::getLowestValidBandwidthIndex() const { 13195ef659e010e90175eb5282d9642a02f6105189bfChong Zhang for (size_t index = 0; index < mBandwidthItems.size(); index++) { 13205ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (isBandwidthValid(mBandwidthItems[index])) { 13215ef659e010e90175eb5282d9642a02f6105189bfChong Zhang return index; 13225ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } 13235ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } 13245ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // if playlists are all blacklisted, return 0 and hope it's alive 13255ef659e010e90175eb5282d9642a02f6105189bfChong Zhang return 0; 13265ef659e010e90175eb5282d9642a02f6105189bfChong Zhang} 13275ef659e010e90175eb5282d9642a02f6105189bfChong Zhang 1328538b6d22a3578c0201d48f8548289aa254d81484Chong Zhangsize_t LiveSession::getBandwidthIndex(int32_t bandwidthBps) { 1329538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang if (mBandwidthItems.size() < 2) { 1330538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang // shouldn't be here if we only have 1 bandwidth, check 1331538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang // logic to get rid of redundant bandwidth polling 1332538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang ALOGW("getBandwidthIndex() called for single bandwidth playlist!"); 1333a44153c1a57202fb538659eb50706e60454d6273Andreas Huber return 0; 1334a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1335a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1336a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#if 1 1337a44153c1a57202fb538659eb50706e60454d6273Andreas Huber char value[PROPERTY_VALUE_MAX]; 1338673158582c9589cee1d5e4d7c79622609938b8f8Andreas Huber ssize_t index = -1; 133914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (property_get("media.httplive.bw-index", value, NULL)) { 1340a44153c1a57202fb538659eb50706e60454d6273Andreas Huber char *end; 134114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber index = strtol(value, &end, 10); 134214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(end > value && *end == '\0'); 134314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 134414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (index >= 0 && (size_t)index >= mBandwidthItems.size()) { 134514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber index = mBandwidthItems.size() - 1; 1346a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1347a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1348a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 134914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (index < 0) { 135014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber char value[PROPERTY_VALUE_MAX]; 135114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (property_get("media.httplive.max-bw", value, NULL)) { 135214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber char *end; 135314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber long maxBw = strtoul(value, &end, 10); 135414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (end > value && *end == '\0') { 135514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (maxBw > 0 && bandwidthBps > maxBw) { 135614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGV("bandwidth capped to %ld bps", maxBw); 135714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber bandwidthBps = maxBw; 135814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 135914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 136014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 1361a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 13625ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // Pick the highest bandwidth stream that's not currently blacklisted 13635ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // below or equal to estimated bandwidth. 136414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 136514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber index = mBandwidthItems.size() - 1; 13665ef659e010e90175eb5282d9642a02f6105189bfChong Zhang ssize_t lowestBandwidth = getLowestValidBandwidthIndex(); 13675ef659e010e90175eb5282d9642a02f6105189bfChong Zhang while (index > lowestBandwidth) { 1368538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang // be conservative (70%) to avoid overestimating and immediately 1369538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang // switching down again. 1370538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang size_t adjustedBandwidthBps = bandwidthBps * 7 / 10; 13715ef659e010e90175eb5282d9642a02f6105189bfChong Zhang const BandwidthItem &item = mBandwidthItems[index]; 13725ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (item.mBandwidth <= adjustedBandwidthBps 13735ef659e010e90175eb5282d9642a02f6105189bfChong Zhang && isBandwidthValid(item)) { 137400598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih break; 137500598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih } 137614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber --index; 137714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 1378a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1379a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0 1380a44153c1a57202fb538659eb50706e60454d6273Andreas Huber // Change bandwidth at random() 1381a44153c1a57202fb538659eb50706e60454d6273Andreas Huber size_t index = uniformRand() * mBandwidthItems.size(); 1382a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0 1383a44153c1a57202fb538659eb50706e60454d6273Andreas Huber // There's a 50% chance to stay on the current bandwidth and 1384a44153c1a57202fb538659eb50706e60454d6273Andreas Huber // a 50% chance to switch to the next higher bandwidth (wrapping around 1385a44153c1a57202fb538659eb50706e60454d6273Andreas Huber // to lowest) 1386a44153c1a57202fb538659eb50706e60454d6273Andreas Huber const size_t kMinIndex = 0; 1387a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1388309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih static ssize_t mCurBandwidthIndex = -1; 138914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 1390a44153c1a57202fb538659eb50706e60454d6273Andreas Huber size_t index; 1391309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (mCurBandwidthIndex < 0) { 1392a44153c1a57202fb538659eb50706e60454d6273Andreas Huber index = kMinIndex; 1393a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } else if (uniformRand() < 0.5) { 1394309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih index = (size_t)mCurBandwidthIndex; 1395a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } else { 1396309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih index = mCurBandwidthIndex + 1; 1397a44153c1a57202fb538659eb50706e60454d6273Andreas Huber if (index == mBandwidthItems.size()) { 1398a44153c1a57202fb538659eb50706e60454d6273Andreas Huber index = kMinIndex; 1399a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1400a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1401309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mCurBandwidthIndex = index; 1402a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0 1403a44153c1a57202fb538659eb50706e60454d6273Andreas Huber // Pick the highest bandwidth stream below or equal to 1.2 Mbit/sec 1404a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1405a44153c1a57202fb538659eb50706e60454d6273Andreas Huber size_t index = mBandwidthItems.size() - 1; 1406a44153c1a57202fb538659eb50706e60454d6273Andreas Huber while (index > 0 && mBandwidthItems.itemAt(index).mBandwidth > 1200000) { 1407a44153c1a57202fb538659eb50706e60454d6273Andreas Huber --index; 1408a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 140914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#elif 1 141014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber char value[PROPERTY_VALUE_MAX]; 141114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber size_t index; 141214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (property_get("media.httplive.bw-index", value, NULL)) { 141314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber char *end; 141414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber index = strtoul(value, &end, 10); 141514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(end > value && *end == '\0'); 141614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 141714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (index >= mBandwidthItems.size()) { 141814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber index = mBandwidthItems.size() - 1; 141914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 142014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else { 142114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber index = 0; 142214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 1423a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#else 1424a44153c1a57202fb538659eb50706e60454d6273Andreas Huber size_t index = mBandwidthItems.size() - 1; // Highest bandwidth stream 1425a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#endif 1426a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 142714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK_GE(index, 0); 142814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 1429a44153c1a57202fb538659eb50706e60454d6273Andreas Huber return index; 1430a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 1431a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1432d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong ZhangHLSTime LiveSession::latestMediaSegmentStartTime() const { 1433d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang HLSTime audioTime(mPacketSources.valueFor( 1434d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang STREAMTYPE_AUDIO)->getLatestDequeuedMeta()); 1435b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih 1436d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang HLSTime videoTime(mPacketSources.valueFor( 1437d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang STREAMTYPE_VIDEO)->getLatestDequeuedMeta()); 1438b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih 1439d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang return audioTime < videoTime ? videoTime : audioTime; 1440b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih} 1441b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih 1442a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnarvoid LiveSession::onSeek(const sp<AMessage> &msg) { 144314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int64_t timeUs; 144414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->findInt64("timeUs", &timeUs)); 1445a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar changeConfiguration(timeUs); 14467e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber} 14477e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber 144814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::getDuration(int64_t *durationUs) const { 1449895651b07fec30b0f9b0d2499599a179d95c9be4Wei Jia int64_t maxDurationUs = -1ll; 145014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber for (size_t i = 0; i < mFetcherInfos.size(); ++i) { 145114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int64_t fetcherDurationUs = mFetcherInfos.valueAt(i).mDurationUs; 1452b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber 1453895651b07fec30b0f9b0d2499599a179d95c9be4Wei Jia if (fetcherDurationUs > maxDurationUs) { 145414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber maxDurationUs = fetcherDurationUs; 1455a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1456a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1457a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 145814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber *durationUs = maxDurationUs; 1459a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 146014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return OK; 146114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 14620f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber 146314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberbool LiveSession::isSeekable() const { 146414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int64_t durationUs; 146514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return getDuration(&durationUs) == OK && durationUs >= 0; 146614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 14670f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber 146814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberbool LiveSession::hasDynamicDuration() const { 146914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return false; 147014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 14710f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber 1472404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhangsize_t LiveSession::getTrackCount() const { 14739d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih if (mPlaylist == NULL) { 14749d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih return 0; 14759d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih } else { 14760852843d304006e3ab333081fddda13b07193de8Robert Shih return mPlaylist->getTrackCount() + (mHasMetadata ? 1 : 0); 14779d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih } 1478404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang} 1479404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang 1480404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhangsp<AMessage> LiveSession::getTrackInfo(size_t trackIndex) const { 14819d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih if (mPlaylist == NULL) { 14829d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih return NULL; 14839d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih } else { 14840852843d304006e3ab333081fddda13b07193de8Robert Shih if (trackIndex == mPlaylist->getTrackCount() && mHasMetadata) { 14850852843d304006e3ab333081fddda13b07193de8Robert Shih sp<AMessage> format = new AMessage(); 14860852843d304006e3ab333081fddda13b07193de8Robert Shih format->setInt32("type", MEDIA_TRACK_TYPE_METADATA); 14870852843d304006e3ab333081fddda13b07193de8Robert Shih format->setString("language", "und"); 14886f9c5e26c710dbee50e57316f1c460dda4850fa5Robert Shih format->setString("mime", MEDIA_MIMETYPE_DATA_TIMED_ID3); 14890852843d304006e3ab333081fddda13b07193de8Robert Shih return format; 14900852843d304006e3ab333081fddda13b07193de8Robert Shih } 14919d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih return mPlaylist->getTrackInfo(trackIndex); 14929d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih } 1493dcb89b3b505522efde173c105a851c412f947178Chong Zhang} 1494dcb89b3b505522efde173c105a851c412f947178Chong Zhang 1495dcb89b3b505522efde173c105a851c412f947178Chong Zhangstatus_t LiveSession::selectTrack(size_t index, bool select) { 1496b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih if (mPlaylist == NULL) { 1497b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih return INVALID_OPERATION; 1498b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih } 1499b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih 150025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("selectTrack: index=%zu, select=%d, mSubtitleGen=%d++", 150125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang index, select, mSubtitleGeneration); 150225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 1503b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih ++mSubtitleGeneration; 1504dcb89b3b505522efde173c105a851c412f947178Chong Zhang status_t err = mPlaylist->selectTrack(index, select); 1505dcb89b3b505522efde173c105a851c412f947178Chong Zhang if (err == OK) { 15061d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> msg = new AMessage(kWhatChangeConfiguration, this); 1507309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih msg->setInt32("pickTrack", select); 1508309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih msg->post(); 1509dcb89b3b505522efde173c105a851c412f947178Chong Zhang } 1510dcb89b3b505522efde173c105a851c412f947178Chong Zhang return err; 1511dcb89b3b505522efde173c105a851c412f947178Chong Zhang} 1512dcb89b3b505522efde173c105a851c412f947178Chong Zhang 151389bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shihssize_t LiveSession::getSelectedTrack(media_track_type type) const { 151489bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih if (mPlaylist == NULL) { 151589bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih return -1; 151689bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih } else { 151789bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih return mPlaylist->getSelectedTrack(type); 151889bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih } 151989bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih} 152089bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih 1521dcb89b3b505522efde173c105a851c412f947178Chong Zhangvoid LiveSession::changeConfiguration( 15227c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang int64_t timeUs, ssize_t bandwidthIndex, bool pickTrack) { 152325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("changeConfiguration: timeUs=%lld us, bwIndex=%zd, pickTrack=%d", 152425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang (long long)timeUs, bandwidthIndex, pickTrack); 152525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 15261543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih cancelBandwidthSwitch(); 15271543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 152814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(!mReconfigurationInProgress); 152914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mReconfigurationInProgress = true; 15307c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (bandwidthIndex >= 0) { 15317c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mOrigBandwidthIndex = mCurBandwidthIndex; 15327c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mCurBandwidthIndex = bandwidthIndex; 15338464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang if (mOrigBandwidthIndex != mCurBandwidthIndex) { 15348464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang ALOGI("#### Starting Bandwidth Switch: %zd => %zd", 15358464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang mOrigBandwidthIndex, mCurBandwidthIndex); 15368464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang } 15377c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 15387c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang CHECK_LT(mCurBandwidthIndex, mBandwidthItems.size()); 15397c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang const BandwidthItem &item = mBandwidthItems.itemAt(mCurBandwidthIndex); 1540a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 15411543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih uint32_t streamMask = 0; // streams that should be fetched by the new fetcher 15421543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih uint32_t resumeMask = 0; // streams that should be fetched by the original fetcher 1543a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 15448ca002eedc747dd854b61cbe364b52c06869273fRobert Shih AString URIs[kMaxStreams]; 15458ca002eedc747dd854b61cbe364b52c06869273fRobert Shih for (size_t i = 0; i < kMaxStreams; ++i) { 15468ca002eedc747dd854b61cbe364b52c06869273fRobert Shih if (mPlaylist->getTypeURI(item.mPlaylistIndex, mStreams[i].mType, &URIs[i])) { 15478ca002eedc747dd854b61cbe364b52c06869273fRobert Shih streamMask |= indexToType(i); 15488ca002eedc747dd854b61cbe364b52c06869273fRobert Shih } 154914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 1550aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber 155114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // Step 1, stop and discard fetchers that are no longer needed. 155214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // Pause those that we'll reuse. 155314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber for (size_t i = 0; i < mFetcherInfos.size(); ++i) { 15547c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // skip fetchers that are marked mToBeRemoved, 15557c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // these are done and can't be reused 15567c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (mFetcherInfos[i].mToBeRemoved) { 15577c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang continue; 15587c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 15597c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 156014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber const AString &uri = mFetcherInfos.keyAt(i); 1561d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang sp<PlaylistFetcher> &fetcher = mFetcherInfos.editValueAt(i).mFetcher; 1562aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber 1563d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang bool discardFetcher = true, delayRemoval = false; 1564c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang for (size_t j = 0; j < kMaxStreams; ++j) { 1565c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang StreamType type = indexToType(j); 1566c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang if ((streamMask & type) && uri == URIs[j]) { 1567c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang resumeMask |= type; 1568c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang streamMask &= ~type; 1569c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang discardFetcher = false; 15706801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber } 157114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 1572d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // Delay fetcher removal if not picking tracks, AND old fetcher 1573d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // has stream mask that overlaps new variant. (Okay to discard 1574d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // old fetcher now, if completely no overlap.) 1575d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (discardFetcher && timeUs < 0ll && !pickTrack 1576d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang && (fetcher->getStreamTypeMask() & streamMask)) { 1577d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang discardFetcher = false; 1578d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang delayRemoval = true; 1579d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang } 1580a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 158114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (discardFetcher) { 158225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("discarding fetcher-%d", fetcher->getFetcherID()); 1583d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang fetcher->stopAsync(); 15846801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber } else { 15858a048338d9291b2db1b3a325fff58cb1aa69f04dChong Zhang float threshold = 0.0f; // default to pause after current block (47Kbytes) 15865abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang bool disconnect = false; 1587a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (timeUs >= 0ll) { 1588a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // seeking, no need to finish fetching 15895abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang disconnect = true; 1590d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang } else if (delayRemoval) { 1591a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // adapting, abort if remaining of current segment is over threshold 1592a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang threshold = getAbortThreshold( 15937c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mOrigBandwidthIndex, mCurBandwidthIndex); 1594a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 1595a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 159625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("pausing fetcher-%d, threshold=%.2f", 159725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang fetcher->getFetcherID(), threshold); 15985abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang fetcher->pauseAsync(threshold, disconnect); 15996801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber } 1600a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1601a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 16021543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih sp<AMessage> msg; 16031543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih if (timeUs < 0ll) { 1604309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih // skip onChangeConfiguration2 (decoder destruction) if not seeking. 16051d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar msg = new AMessage(kWhatChangeConfiguration3, this); 16061543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } else { 16071d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar msg = new AMessage(kWhatChangeConfiguration2, this); 16081543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 160914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber msg->setInt32("streamMask", streamMask); 16101543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih msg->setInt32("resumeMask", resumeMask); 1611309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih msg->setInt32("pickTrack", pickTrack); 161214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber msg->setInt64("timeUs", timeUs); 16138ca002eedc747dd854b61cbe364b52c06869273fRobert Shih for (size_t i = 0; i < kMaxStreams; ++i) { 1614309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if ((streamMask | resumeMask) & indexToType(i)) { 16158ca002eedc747dd854b61cbe364b52c06869273fRobert Shih msg->setString(mStreams[i].uriKey().c_str(), URIs[i].c_str()); 16168ca002eedc747dd854b61cbe364b52c06869273fRobert Shih } 16176e6b1cae2bac1b78205cefab8e4e9e9538982965Andreas Huber } 1618a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 161914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // Every time a fetcher acknowledges the stopAsync or pauseAsync request 162014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // we'll decrement mContinuationCounter, once it reaches zero, i.e. all 162114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // fetchers have completed their asynchronous operation, we'll post 162214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // mContinuation, which then is handled below in onChangeConfiguration2. 162314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mContinuationCounter = mFetcherInfos.size(); 162414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mContinuation = msg; 162588b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber 162614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (mContinuationCounter == 0) { 162714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber msg->post(); 162888b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber } 162914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 1630a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1631dcb89b3b505522efde173c105a851c412f947178Chong Zhangvoid LiveSession::onChangeConfiguration(const sp<AMessage> &msg) { 163225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("onChangeConfiguration"); 163325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 1634dcb89b3b505522efde173c105a851c412f947178Chong Zhang if (!mReconfigurationInProgress) { 16357c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang int32_t pickTrack = 0; 1636309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih msg->findInt32("pickTrack", &pickTrack); 16377c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang changeConfiguration(-1ll /* timeUs */, -1, pickTrack); 1638dcb89b3b505522efde173c105a851c412f947178Chong Zhang } else { 1639dcb89b3b505522efde173c105a851c412f947178Chong Zhang msg->post(1000000ll); // retry in 1 sec 1640dcb89b3b505522efde173c105a851c412f947178Chong Zhang } 1641dcb89b3b505522efde173c105a851c412f947178Chong Zhang} 1642dcb89b3b505522efde173c105a851c412f947178Chong Zhang 164314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::onChangeConfiguration2(const sp<AMessage> &msg) { 164425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("onChangeConfiguration2"); 164525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 164614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mContinuation.clear(); 1647bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber 164814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // All fetchers are either suspended or have been removed now. 1649bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber 1650964adb17885185808398507d2de88665fe193ee2Chong Zhang // If we're seeking, clear all packet sources before we report 1651964adb17885185808398507d2de88665fe193ee2Chong Zhang // seek complete, to prevent decoder from pulling stale data. 1652964adb17885185808398507d2de88665fe193ee2Chong Zhang int64_t timeUs; 1653964adb17885185808398507d2de88665fe193ee2Chong Zhang CHECK(msg->findInt64("timeUs", &timeUs)); 1654964adb17885185808398507d2de88665fe193ee2Chong Zhang 1655964adb17885185808398507d2de88665fe193ee2Chong Zhang if (timeUs >= 0) { 1656964adb17885185808398507d2de88665fe193ee2Chong Zhang mLastSeekTimeUs = timeUs; 16578464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang mLastDequeuedTimeUs = timeUs; 1658964adb17885185808398507d2de88665fe193ee2Chong Zhang 1659964adb17885185808398507d2de88665fe193ee2Chong Zhang for (size_t i = 0; i < mPacketSources.size(); i++) { 16607f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih sp<AnotherPacketSource> packetSource = mPacketSources.editValueAt(i); 16617f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih sp<MetaData> format = packetSource->getFormat(); 16627f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih packetSource->clear(); 16637f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih // Set a tentative format here such that HTTPLiveSource will always have 16647f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih // a format available when NuPlayer queries. Without an available video 16657f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih // format when setting a surface NuPlayer might disable video decoding 16667f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih // altogether. The tentative format will be overwritten by the 16677f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih // authoritative (and possibly same) format once content from the new 16687f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih // position is dequeued. 16697f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih packetSource->setFormat(format); 1670964adb17885185808398507d2de88665fe193ee2Chong Zhang } 1671964adb17885185808398507d2de88665fe193ee2Chong Zhang 16727c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang for (size_t i = 0; i < kMaxStreams; ++i) { 167381636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang mStreams[i].reset(); 16747c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 16757c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 1676964adb17885185808398507d2de88665fe193ee2Chong Zhang mDiscontinuityOffsetTimesUs.clear(); 1677964adb17885185808398507d2de88665fe193ee2Chong Zhang mDiscontinuityAbsStartTimesUs.clear(); 1678964adb17885185808398507d2de88665fe193ee2Chong Zhang 1679c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang if (mSeekReplyID != NULL) { 1680964adb17885185808398507d2de88665fe193ee2Chong Zhang CHECK(mSeekReply != NULL); 1681964adb17885185808398507d2de88665fe193ee2Chong Zhang mSeekReply->setInt32("err", OK); 1682964adb17885185808398507d2de88665fe193ee2Chong Zhang mSeekReply->postReply(mSeekReplyID); 1683c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang mSeekReplyID.clear(); 1684964adb17885185808398507d2de88665fe193ee2Chong Zhang mSeekReply.clear(); 1685964adb17885185808398507d2de88665fe193ee2Chong Zhang } 16867c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 16877c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // restart buffer polling after seek becauese previous 16887c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // buffering position is no longer valid. 16897c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang restartPollBuffering(); 1690964adb17885185808398507d2de88665fe193ee2Chong Zhang } 1691964adb17885185808398507d2de88665fe193ee2Chong Zhang 1692309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih uint32_t streamMask, resumeMask; 169314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->findInt32("streamMask", (int32_t *)&streamMask)); 1694309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih CHECK(msg->findInt32("resumeMask", (int32_t *)&resumeMask)); 1695309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 1696309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih streamMask |= resumeMask; 1697bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber 16988ca002eedc747dd854b61cbe364b52c06869273fRobert Shih AString URIs[kMaxStreams]; 16998ca002eedc747dd854b61cbe364b52c06869273fRobert Shih for (size_t i = 0; i < kMaxStreams; ++i) { 17008ca002eedc747dd854b61cbe364b52c06869273fRobert Shih if (streamMask & indexToType(i)) { 17018ca002eedc747dd854b61cbe364b52c06869273fRobert Shih const AString &uriKey = mStreams[i].uriKey(); 17028ca002eedc747dd854b61cbe364b52c06869273fRobert Shih CHECK(msg->findString(uriKey.c_str(), &URIs[i])); 17038ca002eedc747dd854b61cbe364b52c06869273fRobert Shih ALOGV("%s = '%s'", uriKey.c_str(), URIs[i].c_str()); 17048ca002eedc747dd854b61cbe364b52c06869273fRobert Shih } 170522fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber } 17063831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber 170714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber uint32_t changedMask = 0; 17088ca002eedc747dd854b61cbe364b52c06869273fRobert Shih for (size_t i = 0; i < kMaxStreams && i != kSubtitleIndex; ++i) { 1709c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // stream URI could change even if onChangeConfiguration2 is only 1710c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // used for seek. Seek could happen during a bw switch, in this 1711c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // case bw switch will be cancelled, but the seekTo position will 1712c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // fetch from the new URI. 1713c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang if ((mStreamMask & streamMask & indexToType(i)) 1714c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang && !mStreams[i].mUri.empty() 1715c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang && !(URIs[i] == mStreams[i].mUri)) { 17164604458dfe57b0e91a464aefafea50ae7b9876c1Chong Zhang ALOGV("stream %zu changed: oldURI %s, newURI %s", i, 1717c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang mStreams[i].mUri.c_str(), URIs[i].c_str()); 1718c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang sp<AnotherPacketSource> source = mPacketSources.valueFor(indexToType(i)); 17198464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang if (source->getLatestDequeuedMeta() != NULL) { 17208464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang source->queueDiscontinuity( 17218464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang ATSParser::DISCONTINUITY_FORMATCHANGE, NULL, true); 17228464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang } 1723c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang } 1724c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // Determine which decoders to shutdown on the player side, 1725c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // a decoder has to be shutdown if its streamtype was active 1726c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // before but now longer isn't. 1727c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang if ((mStreamMask & ~streamMask & indexToType(i))) { 17288ca002eedc747dd854b61cbe364b52c06869273fRobert Shih changedMask |= indexToType(i); 17298ca002eedc747dd854b61cbe364b52c06869273fRobert Shih } 1730b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber } 1731b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber 173214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (changedMask == 0) { 173314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // If nothing changed as far as the audio/video decoders 173414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // are concerned we can proceed. 173514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber onChangeConfiguration3(msg); 173614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return; 173714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 173843c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber 173914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // Something changed, inform the player which will shutdown the 174014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // corresponding decoders and will post the reply once that's done. 174114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // Handling the reply will continue executing below in 174214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // onChangeConfiguration3. 174314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AMessage> notify = mNotify->dup(); 174414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->setInt32("what", kWhatStreamsChanged); 174514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->setInt32("changedMask", changedMask); 174620f725ebcef13ded1b4b85c61c8a4b37cd030656Andreas Huber 174714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber msg->setWhat(kWhatChangeConfiguration3); 17481d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar msg->setTarget(this); 1749b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber 175014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->setMessage("reply", msg); 175114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->post(); 175214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 1753b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber 175414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::onChangeConfiguration3(const sp<AMessage> &msg) { 17551543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih mContinuation.clear(); 175614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // All remaining fetchers are still suspended, the player has shutdown 175714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // any decoders that needed it. 1758b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber 17591543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih uint32_t streamMask, resumeMask; 176014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->findInt32("streamMask", (int32_t *)&streamMask)); 17611543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih CHECK(msg->findInt32("resumeMask", (int32_t *)&resumeMask)); 1762a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1763d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang mNewStreamMask = streamMask | resumeMask; 1764d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang 176514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int64_t timeUs; 1766309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih int32_t pickTrack; 17671543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih bool switching = false; 176814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->findInt64("timeUs", &timeUs)); 1769309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih CHECK(msg->findInt32("pickTrack", &pickTrack)); 1770a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 177114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (timeUs < 0ll) { 1772309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (!pickTrack) { 1773d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // mSwapMask contains streams that are in both old and new variant, 1774d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // (in mNewStreamMask & mStreamMask) but with different URIs 1775d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // (not in resumeMask). 1776d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // For example, old variant has video and audio in two separate 1777d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // URIs, and new variant has only audio with unchanged URI. mSwapMask 1778d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // should be 0 as there is nothing to swap. We only need to stop video, 1779d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // and resume audio. 1780d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang mSwapMask = mNewStreamMask & mStreamMask & ~resumeMask; 1781d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang switching = (mSwapMask != 0); 1782309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 1783309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mRealTimeBaseUs = ALooper::GetNowUs() - mLastDequeuedTimeUs; 1784309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } else { 1785309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mRealTimeBaseUs = ALooper::GetNowUs() - timeUs; 178614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 1787a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 178825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("onChangeConfiguration3: timeUs=%lld, switching=%d, pickTrack=%d, " 178925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang "mStreamMask=0x%x, mNewStreamMask=0x%x, mSwapMask=0x%x", 179025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang (long long)timeUs, switching, pickTrack, 179125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang mStreamMask, mNewStreamMask, mSwapMask); 179225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 1793f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih for (size_t i = 0; i < kMaxStreams; ++i) { 1794f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih if (streamMask & indexToType(i)) { 1795f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih if (switching) { 1796f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih CHECK(msg->findString(mStreams[i].uriKey().c_str(), &mStreams[i].mNewUri)); 1797f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } else { 1798f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih CHECK(msg->findString(mStreams[i].uriKey().c_str(), &mStreams[i].mUri)); 1799f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 1800f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 1801f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 1802f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih 18031543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih // Of all existing fetchers: 18041543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih // * Resume fetchers that are still needed and assign them original packet sources. 18051543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih // * Mark otherwise unneeded fetchers for removal. 18061543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih ALOGV("resuming fetchers for mask 0x%08x", resumeMask); 180714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber for (size_t i = 0; i < mFetcherInfos.size(); ++i) { 180814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber const AString &uri = mFetcherInfos.keyAt(i); 18097c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (!resumeFetcher(uri, resumeMask, timeUs)) { 181025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("marking fetcher-%d to be removed", 181125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang mFetcherInfos[i].mFetcher->getFetcherID()); 181225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 18137c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mFetcherInfos.editValueAt(i).mToBeRemoved = true; 18141543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 1815a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1816a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 181714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // streamMask now only contains the types that need a new fetcher created. 181814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (streamMask != 0) { 181914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGV("creating new fetchers for mask 0x%08x", streamMask); 1820a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1821a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 18221543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih // Find out when the original fetchers have buffered up to and start the new fetchers 18231543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih // at a later timestamp. 18248ca002eedc747dd854b61cbe364b52c06869273fRobert Shih for (size_t i = 0; i < kMaxStreams; i++) { 18258ca002eedc747dd854b61cbe364b52c06869273fRobert Shih if (!(indexToType(i) & streamMask)) { 18268ca002eedc747dd854b61cbe364b52c06869273fRobert Shih continue; 18278ca002eedc747dd854b61cbe364b52c06869273fRobert Shih } 18281156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 182914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber AString uri; 1830f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih uri = switching ? mStreams[i].mNewUri : mStreams[i].mUri; 18319b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber 183214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<PlaylistFetcher> fetcher = addFetcher(uri.c_str()); 183314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(fetcher != NULL); 1834a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1835d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang HLSTime startTime; 1836a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang SeekMode seekMode = kSeekModeExactPosition; 18370852843d304006e3ab333081fddda13b07193de8Robert Shih sp<AnotherPacketSource> sources[kNumSources]; 18381543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 1839d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (i == kSubtitleIndex || (!pickTrack && !switching)) { 1840d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang startTime = latestMediaSegmentStartTime(); 1841b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih } 1842b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih 18438ca002eedc747dd854b61cbe364b52c06869273fRobert Shih // TRICKY: looping from i as earlier streams are already removed from streamMask 18448ca002eedc747dd854b61cbe364b52c06869273fRobert Shih for (size_t j = i; j < kMaxStreams; ++j) { 1845f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih const AString &streamUri = switching ? mStreams[j].mNewUri : mStreams[j].mUri; 1846f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih if ((streamMask & indexToType(j)) && uri == streamUri) { 18478ca002eedc747dd854b61cbe364b52c06869273fRobert Shih sources[j] = mPacketSources.valueFor(indexToType(j)); 18481543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 1849309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (timeUs >= 0) { 1850d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang startTime.mTimeUs = timeUs; 18511543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } else { 1852309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih int32_t type; 1853309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih sp<AMessage> meta; 1854d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (!switching) { 1855d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // selecting, or adapting but no swap required 1856309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih meta = sources[j]->getLatestDequeuedMeta(); 1857309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } else { 1858d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // adapting and swap required 1859309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih meta = sources[j]->getLatestEnqueuedMeta(); 18607c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (meta != NULL && mCurBandwidthIndex > mOrigBandwidthIndex) { 18617c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // switching up 18627c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang meta = sources[j]->getMetaAfterLastDequeued(mUpSwitchMargin); 18637c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 1864309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 18651543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 18660852843d304006e3ab333081fddda13b07193de8Robert Shih if ((j == kAudioIndex || j == kVideoIndex) 18670852843d304006e3ab333081fddda13b07193de8Robert Shih && meta != NULL && !meta->findInt32("discontinuity", &type)) { 1868d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang HLSTime tmpTime(meta); 1869d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (startTime < tmpTime) { 1870d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang startTime = tmpTime; 18711543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 18721543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 18731543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 1874d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (!switching) { 1875d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // selecting, or adapting but no swap required 1876309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih sources[j]->clear(); 1877309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (j == kSubtitleIndex) { 1878309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih break; 1879309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 1880964adb17885185808398507d2de88665fe193ee2Chong Zhang 18814604458dfe57b0e91a464aefafea50ae7b9876c1Chong Zhang ALOGV("stream[%zu]: queue format change", j); 1882964adb17885185808398507d2de88665fe193ee2Chong Zhang sources[j]->queueDiscontinuity( 1883a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang ATSParser::DISCONTINUITY_FORMAT_ONLY, NULL, true); 1884309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } else { 1885d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // switching, queue discontinuities after resume 1886309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih sources[j] = mPacketSources2.valueFor(indexToType(j)); 1887309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih sources[j]->clear(); 1888a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // the new fetcher might be providing streams that used to be 1889a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // provided by two different fetchers, if one of the fetcher 1890a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // paused in the middle while the other somehow paused in next 1891a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // seg, we have to start from next seg. 1892a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (seekMode < mStreams[j].mSeekMode) { 1893a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang seekMode = mStreams[j].mSeekMode; 1894309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 18951543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 18961543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 1897a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 18988ca002eedc747dd854b61cbe364b52c06869273fRobert Shih streamMask &= ~indexToType(j); 18998ca002eedc747dd854b61cbe364b52c06869273fRobert Shih } 1900a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 190114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 190225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("[fetcher-%d] startAsync: startTimeUs %lld mLastSeekTimeUs %lld " 190325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang "segmentStartTimeUs %lld seekMode %d", 190425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang fetcher->getFetcherID(), 190525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang (long long)startTime.mTimeUs, 190625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang (long long)mLastSeekTimeUs, 1907978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang (long long)startTime.getSegmentTimeUs(), 190825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang seekMode); 190925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 1910d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // Set the target segment start time to the middle point of the 1911d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // segment where the last sample was. 1912d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // This gives a better guess if segments of the two variants are not 1913d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // perfectly aligned. (If the corresponding segment in new variant 1914d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // starts slightly later than that in the old variant, we still want 1915d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // to pick that segment, not the one before) 19168ca002eedc747dd854b61cbe364b52c06869273fRobert Shih fetcher->startAsync( 19178ca002eedc747dd854b61cbe364b52c06869273fRobert Shih sources[kAudioIndex], 19188ca002eedc747dd854b61cbe364b52c06869273fRobert Shih sources[kVideoIndex], 19198ca002eedc747dd854b61cbe364b52c06869273fRobert Shih sources[kSubtitleIndex], 19200852843d304006e3ab333081fddda13b07193de8Robert Shih getMetadataSource(sources, mNewStreamMask, switching), 1921d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang startTime.mTimeUs < 0 ? mLastSeekTimeUs : startTime.mTimeUs, 1922978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang startTime.getSegmentTimeUs(), 1923d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang startTime.mSeq, 1924a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang seekMode); 1925a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1926a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 192714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // All fetchers have now been started, the configuration change 192814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // has completed. 1929a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 193014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mReconfigurationInProgress = false; 19311543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih if (switching) { 19321543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih mSwitchInProgress = true; 19331543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } else { 19341543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih mStreamMask = mNewStreamMask; 19358464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang if (mOrigBandwidthIndex != mCurBandwidthIndex) { 19368464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang ALOGV("#### Finished Bandwidth Switch Early: %zd => %zd", 19378464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang mOrigBandwidthIndex, mCurBandwidthIndex); 19388464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang mOrigBandwidthIndex = mCurBandwidthIndex; 19398464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang } 19401543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 1941a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 194225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("onChangeConfiguration3: mSwitchInProgress %d, mStreamMask 0x%x", 194325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang mSwitchInProgress, mStreamMask); 194425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 1945c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang if (mDisconnectReplyID != NULL) { 194614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber finishDisconnect(); 1947a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 194814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 1949a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1950a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhangvoid LiveSession::swapPacketSource(StreamType stream) { 195125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("[%s] swapPacketSource", getNameForStream(stream)); 1952a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1953a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // transfer packets from source2 to source 1954a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang sp<AnotherPacketSource> &aps = mPacketSources.editValueFor(stream); 1955a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang sp<AnotherPacketSource> &aps2 = mPacketSources2.editValueFor(stream); 1956a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1957a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // queue discontinuity in mPacketSource 1958a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang aps->queueDiscontinuity(ATSParser::DISCONTINUITY_FORMAT_ONLY, NULL, false); 1959a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1960a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // queue packets in mPacketSource2 to mPacketSource 1961a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang status_t finalResult = OK; 1962a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang sp<ABuffer> accessUnit; 1963a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang while (aps2->hasBufferAvailable(&finalResult) && finalResult == OK && 1964a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang OK == aps2->dequeueAccessUnit(&accessUnit)) { 1965a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang aps->queueAccessUnit(accessUnit); 1966a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 1967a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang aps2->clear(); 1968a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang} 1969a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 19707c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::tryToFinishBandwidthSwitch(const AString &oldUri) { 1971a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (!mSwitchInProgress) { 1972a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang return; 1973a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 1974a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 19757c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ssize_t index = mFetcherInfos.indexOfKey(oldUri); 1976a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (index < 0 || !mFetcherInfos[index].mToBeRemoved) { 19771543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih return; 19781543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 19791543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 1980a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // Swap packet source of streams provided by old variant 1981a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang for (size_t idx = 0; idx < kMaxStreams; idx++) { 19827c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang StreamType stream = indexToType(idx); 19837c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if ((mSwapMask & stream) && (oldUri == mStreams[idx].mUri)) { 1984a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang swapPacketSource(stream); 1985a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1986a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if ((mNewStreamMask & stream) && mStreams[idx].mNewUri.empty()) { 1987a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang ALOGW("swapping stream type %d %s to empty stream", 1988a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang stream, mStreams[idx].mUri.c_str()); 1989a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 1990a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mStreams[idx].mUri = mStreams[idx].mNewUri; 1991a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mStreams[idx].mNewUri.clear(); 1992a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1993a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mSwapMask &= ~stream; 1994a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 1995f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 1996f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih 19977c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mFetcherInfos.editValueAt(index).mFetcher->stopAsync(false /* clear */); 1998a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 199925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("tryToFinishBandwidthSwitch: mSwapMask=0x%x", mSwapMask); 2000309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (mSwapMask != 0) { 20011543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih return; 20021543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 20031543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 20041543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih // Check if new variant contains extra streams. 20051543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih uint32_t extraStreams = mNewStreamMask & (~mStreamMask); 20061543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih while (extraStreams) { 2007a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang StreamType stream = (StreamType) (extraStreams & ~(extraStreams - 1)); 2008a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang extraStreams &= ~stream; 2009a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 2010a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang swapPacketSource(stream); 2011f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih 2012a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang ssize_t idx = typeToIndex(stream); 2013f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih CHECK(idx >= 0); 2014f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih if (mStreams[idx].mNewUri.empty()) { 2015f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih ALOGW("swapping extra stream type %d %s to empty stream", 2016a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang stream, mStreams[idx].mUri.c_str()); 2017f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 2018f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih mStreams[idx].mUri = mStreams[idx].mNewUri; 2019f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih mStreams[idx].mNewUri.clear(); 20201543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 20211543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 2022a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // Restart new fetcher (it was paused after the first 47k block) 2023a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // and let it fetch into mPacketSources (not mPacketSources2) 2024a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang for (size_t i = 0; i < mFetcherInfos.size(); ++i) { 2025a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang FetcherInfo &info = mFetcherInfos.editValueAt(i); 2026a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (info.mToBeResumed) { 20277c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang resumeFetcher(mFetcherInfos.keyAt(i), mNewStreamMask); 2028a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang info.mToBeResumed = false; 2029a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 2030a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 2031a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 20327c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGI("#### Finished Bandwidth Switch: %zd => %zd", 20337c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mOrigBandwidthIndex, mCurBandwidthIndex); 20347c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 2035a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mStreamMask = mNewStreamMask; 2036a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mSwitchInProgress = false; 20377c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mOrigBandwidthIndex = mCurBandwidthIndex; 2038a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 20397c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang restartPollBuffering(); 20401543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih} 20411543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 2042964adb17885185808398507d2de88665fe193ee2Chong Zhangvoid LiveSession::schedulePollBuffering() { 2043964adb17885185808398507d2de88665fe193ee2Chong Zhang sp<AMessage> msg = new AMessage(kWhatPollBuffering, this); 2044964adb17885185808398507d2de88665fe193ee2Chong Zhang msg->setInt32("generation", mPollBufferingGeneration); 2045964adb17885185808398507d2de88665fe193ee2Chong Zhang msg->post(1000000ll); 2046964adb17885185808398507d2de88665fe193ee2Chong Zhang} 2047678bcdc852dd8f801f5c46fdc85db587b721d83dApurupa Pattapu 2048964adb17885185808398507d2de88665fe193ee2Chong Zhangvoid LiveSession::cancelPollBuffering() { 2049964adb17885185808398507d2de88665fe193ee2Chong Zhang ++mPollBufferingGeneration; 20507c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mPrevBufferPercentage = -1; 20517c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang} 20527c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 20537c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::restartPollBuffering() { 20547c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang cancelPollBuffering(); 20557c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang onPollBuffering(); 2056964adb17885185808398507d2de88665fe193ee2Chong Zhang} 20570ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih 2058964adb17885185808398507d2de88665fe193ee2Chong Zhangvoid LiveSession::onPollBuffering() { 2059964adb17885185808398507d2de88665fe193ee2Chong Zhang ALOGV("onPollBuffering: mSwitchInProgress %d, mReconfigurationInProgress %d, " 2060a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang "mInPreparationPhase %d, mCurBandwidthIndex %zd, mStreamMask 0x%x", 2061964adb17885185808398507d2de88665fe193ee2Chong Zhang mSwitchInProgress, mReconfigurationInProgress, 2062538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mInPreparationPhase, mCurBandwidthIndex, mStreamMask); 20630ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih 20647c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang bool underflow, ready, down, up; 20657c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (checkBuffering(underflow, ready, down, up)) { 20668464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang if (mInPreparationPhase) { 20678464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang // Allow down switch even if we're still preparing. 20688464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang // 20698464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang // Some streams have a high bandwidth index as default, 20708464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang // when bandwidth is low, it takes a long time to buffer 20718464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang // to ready mark, then it immediately pauses after start 20728464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang // as we have to do a down switch. It's better experience 20738464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang // to restart from a lower index, if we detect low bw. 20748464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang if (!switchBandwidthIfNeeded(false /* up */, down) && ready) { 20758464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang postPrepared(OK); 20768464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang } 20770ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih } 20780ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih 2079538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang if (!mInPreparationPhase) { 20807c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (ready) { 20817c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang stopBufferingIfNecessary(); 20827c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } else if (underflow) { 20837c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang startBufferingIfNecessary(); 20847c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 20857c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang switchBandwidthIfNeeded(up, down); 20868464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang } 20870ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih } 20880ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih 2089964adb17885185808398507d2de88665fe193ee2Chong Zhang schedulePollBuffering(); 20900ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih} 20910ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih 20927c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::cancelBandwidthSwitch(bool resume) { 20937c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGV("cancelBandwidthSwitch: mSwitchGen(%d)++, orig %zd, cur %zd", 20947c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mSwitchGeneration, mOrigBandwidthIndex, mCurBandwidthIndex); 20957c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (!mSwitchInProgress) { 20967c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return; 20977c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 2098f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih 2099f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih for (size_t i = 0; i < mFetcherInfos.size(); ++i) { 2100f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih FetcherInfo& info = mFetcherInfos.editValueAt(i); 2101f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih if (info.mToBeRemoved) { 2102f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih info.mToBeRemoved = false; 21037c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (resume) { 21047c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang resumeFetcher(mFetcherInfos.keyAt(i), mSwapMask); 21057c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 2106f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 2107f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 2108f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih 2109f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih for (size_t i = 0; i < kMaxStreams; ++i) { 21107c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang AString newUri = mStreams[i].mNewUri; 21117c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (!newUri.empty()) { 21127c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // clear all mNewUri matching this newUri 21137c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang for (size_t j = i; j < kMaxStreams; ++j) { 21147c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (mStreams[j].mNewUri == newUri) { 21157c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mStreams[j].mNewUri.clear(); 21167c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 21177c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 21187c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGV("stopping newUri = %s", newUri.c_str()); 21197c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ssize_t index = mFetcherInfos.indexOfKey(newUri); 21207c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (index < 0) { 21217c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGE("did not find fetcher for newUri: %s", newUri.c_str()); 2122f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih continue; 2123f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 21247c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang FetcherInfo &info = mFetcherInfos.editValueAt(index); 21257c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang info.mToBeRemoved = true; 2126f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih info.mFetcher->stopAsync(); 2127f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 2128f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 21297c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 21307c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGI("#### Canceled Bandwidth Switch: %zd => %zd", 213125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang mOrigBandwidthIndex, mCurBandwidthIndex); 21327c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 21337c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mSwitchGeneration++; 21347c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mSwitchInProgress = false; 21357c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mCurBandwidthIndex = mOrigBandwidthIndex; 21367c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mSwapMask = 0; 21371543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih} 21381543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 21397c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangbool LiveSession::checkBuffering( 21407c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang bool &underflow, bool &ready, bool &down, bool &up) { 21417c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang underflow = ready = down = up = false; 2142964adb17885185808398507d2de88665fe193ee2Chong Zhang 21437c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (mReconfigurationInProgress) { 2144964adb17885185808398507d2de88665fe193ee2Chong Zhang ALOGV("Switch/Reconfig in progress, defer buffer polling"); 21451543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih return false; 21461543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 21471543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 21487c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang size_t activeCount, underflowCount, readyCount, downCount, upCount; 21497c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang activeCount = underflowCount = readyCount = downCount = upCount =0; 21507c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang int32_t minBufferPercent = -1; 21517c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang int64_t durationUs; 21527c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (getDuration(&durationUs) != OK) { 21537c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang durationUs = -1; 21547c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 2155964adb17885185808398507d2de88665fe193ee2Chong Zhang for (size_t i = 0; i < mPacketSources.size(); ++i) { 2156964adb17885185808398507d2de88665fe193ee2Chong Zhang // we don't check subtitles for buffering level 2157964adb17885185808398507d2de88665fe193ee2Chong Zhang if (!(mStreamMask & mPacketSources.keyAt(i) 2158964adb17885185808398507d2de88665fe193ee2Chong Zhang & (STREAMTYPE_AUDIO | STREAMTYPE_VIDEO))) { 2159964adb17885185808398507d2de88665fe193ee2Chong Zhang continue; 2160964adb17885185808398507d2de88665fe193ee2Chong Zhang } 2161964adb17885185808398507d2de88665fe193ee2Chong Zhang // ignore streams that never had any packet queued. 2162964adb17885185808398507d2de88665fe193ee2Chong Zhang // (it's possible that the variant only has audio or video) 2163964adb17885185808398507d2de88665fe193ee2Chong Zhang sp<AMessage> meta = mPacketSources[i]->getLatestEnqueuedMeta(); 2164964adb17885185808398507d2de88665fe193ee2Chong Zhang if (meta == NULL) { 2165964adb17885185808398507d2de88665fe193ee2Chong Zhang continue; 2166964adb17885185808398507d2de88665fe193ee2Chong Zhang } 2167964adb17885185808398507d2de88665fe193ee2Chong Zhang 21680dd229bb306df68b88e7419b3cc11fc6175be1daRobert Shih status_t finalResult; 2169964adb17885185808398507d2de88665fe193ee2Chong Zhang int64_t bufferedDurationUs = 21700dd229bb306df68b88e7419b3cc11fc6175be1daRobert Shih mPacketSources[i]->getBufferedDurationUs(&finalResult); 217125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("[%s] buffered %lld us", 217225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang getNameForStream(mPacketSources.keyAt(i)), 217325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang (long long)bufferedDurationUs); 21747c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (durationUs >= 0) { 21757c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang int32_t percent; 21767c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (mPacketSources[i]->isFinished(0 /* duration */)) { 21777c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang percent = 100; 21787c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } else { 21798464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang percent = (int32_t)(100.0 * 21808464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang (mLastDequeuedTimeUs + bufferedDurationUs) / durationUs); 21817c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 21827c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (minBufferPercent < 0 || percent < minBufferPercent) { 21837c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang minBufferPercent = percent; 21847c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 2185964adb17885185808398507d2de88665fe193ee2Chong Zhang } 21867c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 21877c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ++activeCount; 2188765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang int64_t readyMark = mInPreparationPhase ? kPrepareMarkUs : kReadyMarkUs; 21897c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (bufferedDurationUs > readyMark 21907c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang || mPacketSources[i]->isFinished(0)) { 21917c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ++readyCount; 21927c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 21937c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (!mPacketSources[i]->isFinished(0)) { 2194765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang if (bufferedDurationUs < kUnderflowMarkUs) { 21957c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ++underflowCount; 21967c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 21977c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (bufferedDurationUs > mUpSwitchMark) { 21987c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ++upCount; 2199d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang } 2200d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (bufferedDurationUs < mDownSwitchMark) { 22017c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ++downCount; 22027c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 22037c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 22047c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 22057c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 22067c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (minBufferPercent >= 0) { 22077c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notifyBufferingUpdate(minBufferPercent); 220814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 220914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 2210964adb17885185808398507d2de88665fe193ee2Chong Zhang if (activeCount > 0) { 22117c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang up = (upCount == activeCount); 22127c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang down = (downCount > 0); 22137c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ready = (readyCount == activeCount); 22147c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang underflow = (underflowCount > 0); 22151543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih return true; 22161543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 2217964adb17885185808398507d2de88665fe193ee2Chong Zhang 2218964adb17885185808398507d2de88665fe193ee2Chong Zhang return false; 22191543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih} 22201543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 22217c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::startBufferingIfNecessary() { 22227c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGV("startBufferingIfNecessary: mInPreparationPhase=%d, mBuffering=%d", 22237c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mInPreparationPhase, mBuffering); 22247c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (!mBuffering) { 22257c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mBuffering = true; 22267c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 22277c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AMessage> notify = mNotify->dup(); 22287c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->setInt32("what", kWhatBufferingStart); 22297c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->post(); 22307c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 22317c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang} 22327c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 22337c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::stopBufferingIfNecessary() { 22347c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGV("stopBufferingIfNecessary: mInPreparationPhase=%d, mBuffering=%d", 22357c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mInPreparationPhase, mBuffering); 22367c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 22377c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (mBuffering) { 22387c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mBuffering = false; 22397c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 22407c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AMessage> notify = mNotify->dup(); 22417c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->setInt32("what", kWhatBufferingEnd); 22427c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->post(); 22437c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 22447c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang} 22457c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 22467c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::notifyBufferingUpdate(int32_t percentage) { 22477c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (percentage < mPrevBufferPercentage) { 22487c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang percentage = mPrevBufferPercentage; 22497c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } else if (percentage > 100) { 22507c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang percentage = 100; 22517c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 22527c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 22537c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mPrevBufferPercentage = percentage; 22547c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 22557c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGV("notifyBufferingUpdate: percentage=%d%%", percentage); 22567c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 22577c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AMessage> notify = mNotify->dup(); 22587c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->setInt32("what", kWhatBufferingUpdate); 22597c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->setInt32("percentage", percentage); 22607c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->post(); 22617c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang} 22627c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 22635ef659e010e90175eb5282d9642a02f6105189bfChong Zhangbool LiveSession::tryBandwidthFallback() { 22645ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (mInPreparationPhase || mReconfigurationInProgress) { 22655ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // Don't try fallback during prepare or reconfig. 22665ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // If error happens there, it's likely unrecoverable. 22675ef659e010e90175eb5282d9642a02f6105189bfChong Zhang return false; 22685ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } 22695ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (mCurBandwidthIndex > mOrigBandwidthIndex) { 22705ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // if we're switching up, simply cancel and resume old variant 22715ef659e010e90175eb5282d9642a02f6105189bfChong Zhang cancelBandwidthSwitch(true /* resume */); 22725ef659e010e90175eb5282d9642a02f6105189bfChong Zhang return true; 22735ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } else { 22745ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // if we're switching down, we're likely about to underflow (if 22755ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // not already underflowing). try the lowest viable bandwidth if 22765ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // not on that variant already. 22775ef659e010e90175eb5282d9642a02f6105189bfChong Zhang ssize_t lowestValid = getLowestValidBandwidthIndex(); 22785ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (mCurBandwidthIndex > lowestValid) { 22795ef659e010e90175eb5282d9642a02f6105189bfChong Zhang cancelBandwidthSwitch(); 22805ef659e010e90175eb5282d9642a02f6105189bfChong Zhang changeConfiguration(-1ll, lowestValid); 22815ef659e010e90175eb5282d9642a02f6105189bfChong Zhang return true; 22825ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } 22835ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } 22845ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // return false if we couldn't find any fallback 22855ef659e010e90175eb5282d9642a02f6105189bfChong Zhang return false; 22865ef659e010e90175eb5282d9642a02f6105189bfChong Zhang} 22875ef659e010e90175eb5282d9642a02f6105189bfChong Zhang 22888464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang/* 22898464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang * returns true if a bandwidth switch is actually needed (and started), 22908464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang * returns false otherwise 22918464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang */ 22928464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhangbool LiveSession::switchBandwidthIfNeeded(bool bufferHigh, bool bufferLow) { 2293538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang // no need to check bandwidth if we only have 1 bandwidth settings 22945ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (mBandwidthItems.size() < 2) { 22955ef659e010e90175eb5282d9642a02f6105189bfChong Zhang return false; 22965ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } 22975ef659e010e90175eb5282d9642a02f6105189bfChong Zhang 22985ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (mSwitchInProgress) { 22995ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (mBuffering) { 23005ef659e010e90175eb5282d9642a02f6105189bfChong Zhang tryBandwidthFallback(); 23015ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } 23028464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang return false; 2303538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang } 2304538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 23055ef659e010e90175eb5282d9642a02f6105189bfChong Zhang int32_t bandwidthBps, shortTermBps; 2306978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang bool isStable; 23075ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (mBandwidthEstimator->estimateBandwidth( 23085ef659e010e90175eb5282d9642a02f6105189bfChong Zhang &bandwidthBps, &isStable, &shortTermBps)) { 23095ef659e010e90175eb5282d9642a02f6105189bfChong Zhang ALOGV("bandwidth estimated at %.2f kbps, " 23105ef659e010e90175eb5282d9642a02f6105189bfChong Zhang "stable %d, shortTermBps %.2f kbps", 23115ef659e010e90175eb5282d9642a02f6105189bfChong Zhang bandwidthBps / 1024.0f, isStable, shortTermBps / 1024.0f); 2312a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mLastBandwidthBps = bandwidthBps; 23135ef659e010e90175eb5282d9642a02f6105189bfChong Zhang mLastBandwidthStable = isStable; 2314538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang } else { 2315538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang ALOGV("no bandwidth estimate."); 23168464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang return false; 2317538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang } 2318538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 2319538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang int32_t curBandwidth = mBandwidthItems.itemAt(mCurBandwidthIndex).mBandwidth; 2320d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // canSwithDown and canSwitchUp can't both be true. 2321d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // we only want to switch up when measured bw is 120% higher than current variant, 2322d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // and we only want to switch down when measured bw is below current variant. 2323978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang bool canSwitchDown = bufferLow 2324d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang && (bandwidthBps < (int32_t)curBandwidth); 2325d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang bool canSwitchUp = bufferHigh 2326d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang && (bandwidthBps > (int32_t)curBandwidth * 12 / 10); 2327d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang 2328978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (canSwitchDown || canSwitchUp) { 2329978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang // bandwidth estimating has some delay, if we have to downswitch when 23305ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // it hasn't stabilized, use the short term to guess real bandwidth, 23315ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // since it may be dropping too fast. 23325ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // (note this doesn't apply to upswitch, always use longer average there) 2333978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (!isStable && canSwitchDown) { 23345ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (shortTermBps < bandwidthBps) { 23355ef659e010e90175eb5282d9642a02f6105189bfChong Zhang bandwidthBps = shortTermBps; 23365ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } 2337978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 2338978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang 2339538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang ssize_t bandwidthIndex = getBandwidthIndex(bandwidthBps); 2340538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 2341d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // it's possible that we're checking for canSwitchUp case, but the returned 2342d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // bandwidthIndex is < mCurBandwidthIndex, as getBandwidthIndex() only uses 70% 2343d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // of measured bw. In that case we don't want to do anything, since we have 2344d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // both enough buffer and enough bw. 23458464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang if ((canSwitchUp && bandwidthIndex > mCurBandwidthIndex) 2346978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang || (canSwitchDown && bandwidthIndex < mCurBandwidthIndex)) { 23478464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang // if not yet prepared, just restart again with new bw index. 23488464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang // this is faster and playback experience is cleaner. 23498464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang changeConfiguration( 23508464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang mInPreparationPhase ? 0 : -1ll, bandwidthIndex); 23518464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang return true; 2352538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang } 235314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 23548464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang return false; 2355a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 2356a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 23577c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::postError(status_t err) { 23587c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // if we reached EOS, notify buffering of 100% 23597c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (err == ERROR_END_OF_STREAM) { 23607c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notifyBufferingUpdate(100); 23617c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 23627c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // we'll stop buffer polling now, before that notify 23637c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // stop buffering to stop the spinning icon 23647c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang stopBufferingIfNecessary(); 23657c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang cancelPollBuffering(); 23667c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 23677c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AMessage> notify = mNotify->dup(); 23687c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->setInt32("what", kWhatError); 23697c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->setInt32("err", err); 23707c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->post(); 23717c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang} 23727c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 237314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::postPrepared(status_t err) { 237414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(mInPreparationPhase); 2375a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 237614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AMessage> notify = mNotify->dup(); 237714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (err == OK || err == ERROR_END_OF_STREAM) { 237814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->setInt32("what", kWhatPrepared); 237914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else { 23807c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang cancelPollBuffering(); 23817c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 238214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->setInt32("what", kWhatPreparationFailed); 238314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->setInt32("err", err); 238414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 2385a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 238614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->post(); 2387a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 238814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mInPreparationPhase = false; 2389b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber} 2390b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber 2391964adb17885185808398507d2de88665fe193ee2Chong Zhang 2392a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} // namespace android 2393a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 2394