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> 2973feb8cda587e02f1ff68095b17d47e1d6e37c70Wei Jia#include <media/MediaHTTPService.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 529bb3803a80a680ea7a3bc11e07b8a89ccddee003Wei Jia//TODO: redefine this mark to a fair value 539bb3803a80a680ea7a3bc11e07b8a89ccddee003Wei Jia// default buffer underflow mark 549bb3803a80a680ea7a3bc11e07b8a89ccddee003Wei Jiastatic const int kUnderflowMarkMs = 1000; // 1 second 559bb3803a80a680ea7a3bc11e07b8a89ccddee003Wei Jia 56538b6d22a3578c0201d48f8548289aa254d81484Chong Zhangstruct LiveSession::BandwidthEstimator : public RefBase { 57538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang BandwidthEstimator(); 58538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 59538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang void addBandwidthMeasurement(size_t numBytes, int64_t delayUs); 605ef659e010e90175eb5282d9642a02f6105189bfChong Zhang bool estimateBandwidth( 615ef659e010e90175eb5282d9642a02f6105189bfChong Zhang int32_t *bandwidth, 625ef659e010e90175eb5282d9642a02f6105189bfChong Zhang bool *isStable = NULL, 635ef659e010e90175eb5282d9642a02f6105189bfChong Zhang int32_t *shortTermBps = NULL); 64538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 65538b6d22a3578c0201d48f8548289aa254d81484Chong Zhangprivate: 66538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang // Bandwidth estimation parameters 675ef659e010e90175eb5282d9642a02f6105189bfChong Zhang static const int32_t kShortTermBandwidthItems = 3; 6881636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang static const int32_t kMinBandwidthHistoryItems = 20; 6981636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang static const int64_t kMinBandwidthHistoryWindowUs = 5000000ll; // 5 sec 7081636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang static const int64_t kMaxBandwidthHistoryWindowUs = 30000000ll; // 30 sec 715ef659e010e90175eb5282d9642a02f6105189bfChong Zhang static const int64_t kMaxBandwidthHistoryAgeUs = 60000000ll; // 60 sec 72538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 73538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang struct BandwidthEntry { 745ef659e010e90175eb5282d9642a02f6105189bfChong Zhang int64_t mTimestampUs; 75538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang int64_t mDelayUs; 76538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang size_t mNumBytes; 77538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang }; 78538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 79538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang Mutex mLock; 80538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang List<BandwidthEntry> mBandwidthHistory; 81978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang List<int32_t> mPrevEstimates; 825ef659e010e90175eb5282d9642a02f6105189bfChong Zhang int32_t mShortTermEstimate; 83978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang bool mHasNewSample; 84978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang bool mIsStable; 85538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang int64_t mTotalTransferTimeUs; 86538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang size_t mTotalTransferBytes; 87538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 88538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang DISALLOW_EVIL_CONSTRUCTORS(BandwidthEstimator); 89538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang}; 90538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 91538b6d22a3578c0201d48f8548289aa254d81484Chong ZhangLiveSession::BandwidthEstimator::BandwidthEstimator() : 925ef659e010e90175eb5282d9642a02f6105189bfChong Zhang mShortTermEstimate(0), 93978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mHasNewSample(false), 94978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mIsStable(true), 95538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mTotalTransferTimeUs(0), 96538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mTotalTransferBytes(0) { 97538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang} 98538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 99538b6d22a3578c0201d48f8548289aa254d81484Chong Zhangvoid LiveSession::BandwidthEstimator::addBandwidthMeasurement( 100538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang size_t numBytes, int64_t delayUs) { 101538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang AutoMutex autoLock(mLock); 102538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 1035ef659e010e90175eb5282d9642a02f6105189bfChong Zhang int64_t nowUs = ALooper::GetNowUs(); 104538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang BandwidthEntry entry; 1055ef659e010e90175eb5282d9642a02f6105189bfChong Zhang entry.mTimestampUs = nowUs; 106538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang entry.mDelayUs = delayUs; 107538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang entry.mNumBytes = numBytes; 108538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mTotalTransferTimeUs += delayUs; 109538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mTotalTransferBytes += numBytes; 110538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mBandwidthHistory.push_back(entry); 111978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mHasNewSample = true; 112538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 11381636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang // Remove no more than 10% of total transfer time at a time 11481636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang // to avoid sudden jump on bandwidth estimation. There might 11581636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang // be long blocking reads that takes up signification time, 11681636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang // we have to keep a longer window in that case. 11781636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang int64_t bandwidthHistoryWindowUs = mTotalTransferTimeUs * 9 / 10; 11881636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang if (bandwidthHistoryWindowUs < kMinBandwidthHistoryWindowUs) { 11981636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang bandwidthHistoryWindowUs = kMinBandwidthHistoryWindowUs; 12081636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang } else if (bandwidthHistoryWindowUs > kMaxBandwidthHistoryWindowUs) { 12181636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang bandwidthHistoryWindowUs = kMaxBandwidthHistoryWindowUs; 12281636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang } 123538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang // trim old samples, keeping at least kMaxBandwidthHistoryItems samples, 124538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang // and total transfer time at least kMaxBandwidthHistoryWindowUs. 12581636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang while (mBandwidthHistory.size() > kMinBandwidthHistoryItems) { 126538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang List<BandwidthEntry>::iterator it = mBandwidthHistory.begin(); 1275ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // remove sample if either absolute age or total transfer time is 1285ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // over kMaxBandwidthHistoryWindowUs 1295ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (nowUs - it->mTimestampUs < kMaxBandwidthHistoryAgeUs && 1305ef659e010e90175eb5282d9642a02f6105189bfChong Zhang mTotalTransferTimeUs - it->mDelayUs < bandwidthHistoryWindowUs) { 131538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang break; 132538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang } 133538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mTotalTransferTimeUs -= it->mDelayUs; 134538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mTotalTransferBytes -= it->mNumBytes; 135538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mBandwidthHistory.erase(mBandwidthHistory.begin()); 136538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang } 137538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang} 138538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 13981636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhangbool LiveSession::BandwidthEstimator::estimateBandwidth( 1405ef659e010e90175eb5282d9642a02f6105189bfChong Zhang int32_t *bandwidthBps, bool *isStable, int32_t *shortTermBps) { 141538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang AutoMutex autoLock(mLock); 142538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 143538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang if (mBandwidthHistory.size() < 2) { 144538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang return false; 145538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang } 146538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 147978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (!mHasNewSample) { 148978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang *bandwidthBps = *(--mPrevEstimates.end()); 149978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (isStable) { 150978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang *isStable = mIsStable; 151978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 1525ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (shortTermBps) { 1535ef659e010e90175eb5282d9642a02f6105189bfChong Zhang *shortTermBps = mShortTermEstimate; 1545ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } 155978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang return true; 156978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 157978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang 158538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang *bandwidthBps = ((double)mTotalTransferBytes * 8E6 / mTotalTransferTimeUs); 159978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mPrevEstimates.push_back(*bandwidthBps); 160978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang while (mPrevEstimates.size() > 3) { 161978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mPrevEstimates.erase(mPrevEstimates.begin()); 162978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 163978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mHasNewSample = false; 164978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang 1655ef659e010e90175eb5282d9642a02f6105189bfChong Zhang int64_t totalTimeUs = 0; 1665ef659e010e90175eb5282d9642a02f6105189bfChong Zhang size_t totalBytes = 0; 1675ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (mBandwidthHistory.size() >= kShortTermBandwidthItems) { 1685ef659e010e90175eb5282d9642a02f6105189bfChong Zhang List<BandwidthEntry>::iterator it = --mBandwidthHistory.end(); 1695ef659e010e90175eb5282d9642a02f6105189bfChong Zhang for (size_t i = 0; i < kShortTermBandwidthItems; i++, it--) { 1705ef659e010e90175eb5282d9642a02f6105189bfChong Zhang totalTimeUs += it->mDelayUs; 1715ef659e010e90175eb5282d9642a02f6105189bfChong Zhang totalBytes += it->mNumBytes; 1725ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } 1735ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } 1745ef659e010e90175eb5282d9642a02f6105189bfChong Zhang mShortTermEstimate = totalTimeUs > 0 ? 1755ef659e010e90175eb5282d9642a02f6105189bfChong Zhang (totalBytes * 8E6 / totalTimeUs) : *bandwidthBps; 1765ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (shortTermBps) { 1775ef659e010e90175eb5282d9642a02f6105189bfChong Zhang *shortTermBps = mShortTermEstimate; 1785ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } 1795ef659e010e90175eb5282d9642a02f6105189bfChong Zhang 180a6ff3a8a9bd17e8a5a421b409b58b8497842ebefRobert Shih int64_t minEstimate = -1, maxEstimate = -1; 181978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang List<int32_t>::iterator it; 182978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang for (it = mPrevEstimates.begin(); it != mPrevEstimates.end(); it++) { 183978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang int32_t estimate = *it; 184978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (minEstimate < 0 || minEstimate > estimate) { 185978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang minEstimate = estimate; 186978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 187978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (maxEstimate < 0 || maxEstimate < estimate) { 188978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang maxEstimate = estimate; 189978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 190978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 1915ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // consider it stable if long-term average is not jumping a lot 1925ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // and short-term average is not much lower than long-term average 1935ef659e010e90175eb5282d9642a02f6105189bfChong Zhang mIsStable = (maxEstimate <= minEstimate * 4 / 3) 1945ef659e010e90175eb5282d9642a02f6105189bfChong Zhang && mShortTermEstimate > minEstimate * 7 / 10; 195978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (isStable) { 1965ef659e010e90175eb5282d9642a02f6105189bfChong Zhang *isStable = mIsStable; 197978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 1985ef659e010e90175eb5282d9642a02f6105189bfChong Zhang 19981636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang#if 0 20081636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang { 20181636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang char dumpStr[1024] = {0}; 20281636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang size_t itemIdx = 0; 20381636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang size_t histSize = mBandwidthHistory.size(); 20481636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang sprintf(dumpStr, "estimate bps=%d stable=%d history (n=%d): {", 20581636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang *bandwidthBps, mIsStable, histSize); 20681636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang List<BandwidthEntry>::iterator it = mBandwidthHistory.begin(); 20781636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang for (; it != mBandwidthHistory.end(); ++it) { 20881636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang if (itemIdx > 50) { 20981636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang sprintf(dumpStr + strlen(dumpStr), 21081636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang "...(%zd more items)... }", histSize - itemIdx); 21181636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang break; 21281636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang } 21381636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang sprintf(dumpStr + strlen(dumpStr), "%dk/%.3fs%s", 21481636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang it->mNumBytes / 1024, 21581636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang (double)it->mDelayUs * 1.0e-6, 21681636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang (it == (--mBandwidthHistory.end())) ? "}" : ", "); 21781636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang itemIdx++; 21881636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang } 21981636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang ALOGE(dumpStr); 22081636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang } 22181636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang#endif 222538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang return true; 223538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang} 224538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 2257c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang//static 2267c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangconst char *LiveSession::getKeyForStream(StreamType type) { 2277c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang switch (type) { 2287c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang case STREAMTYPE_VIDEO: 2297c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return "timeUsVideo"; 2307c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang case STREAMTYPE_AUDIO: 2317c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return "timeUsAudio"; 2327c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang case STREAMTYPE_SUBTITLES: 2337c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return "timeUsSubtitle"; 2340852843d304006e3ab333081fddda13b07193de8Robert Shih case STREAMTYPE_METADATA: 2350852843d304006e3ab333081fddda13b07193de8Robert Shih return "timeUsMetadata"; // unused 2367c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang default: 2377c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang TRESPASS(); 2387c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 2397c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return NULL; 2407c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang} 2417c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 24225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang//static 24325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhangconst char *LiveSession::getNameForStream(StreamType type) { 24425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang switch (type) { 24525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang case STREAMTYPE_VIDEO: 24625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang return "video"; 24725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang case STREAMTYPE_AUDIO: 24825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang return "audio"; 24925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang case STREAMTYPE_SUBTITLES: 25025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang return "subs"; 2510852843d304006e3ab333081fddda13b07193de8Robert Shih case STREAMTYPE_METADATA: 2520852843d304006e3ab333081fddda13b07193de8Robert Shih return "metadata"; 25325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang default: 25425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang break; 25525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang } 25625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang return "unknown"; 25725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang} 25825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 2590852843d304006e3ab333081fddda13b07193de8Robert Shih//static 2600852843d304006e3ab333081fddda13b07193de8Robert ShihATSParser::SourceType LiveSession::getSourceTypeForStream(StreamType type) { 2610852843d304006e3ab333081fddda13b07193de8Robert Shih switch (type) { 2620852843d304006e3ab333081fddda13b07193de8Robert Shih case STREAMTYPE_VIDEO: 2630852843d304006e3ab333081fddda13b07193de8Robert Shih return ATSParser::VIDEO; 2640852843d304006e3ab333081fddda13b07193de8Robert Shih case STREAMTYPE_AUDIO: 2650852843d304006e3ab333081fddda13b07193de8Robert Shih return ATSParser::AUDIO; 2660852843d304006e3ab333081fddda13b07193de8Robert Shih case STREAMTYPE_METADATA: 2670852843d304006e3ab333081fddda13b07193de8Robert Shih return ATSParser::META; 2680852843d304006e3ab333081fddda13b07193de8Robert Shih case STREAMTYPE_SUBTITLES: 2690852843d304006e3ab333081fddda13b07193de8Robert Shih default: 2700852843d304006e3ab333081fddda13b07193de8Robert Shih TRESPASS(); 2710852843d304006e3ab333081fddda13b07193de8Robert Shih } 2720852843d304006e3ab333081fddda13b07193de8Robert Shih return ATSParser::NUM_SOURCE_TYPES; // should not reach here 2730852843d304006e3ab333081fddda13b07193de8Robert Shih} 2740852843d304006e3ab333081fddda13b07193de8Robert Shih 2750df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas HuberLiveSession::LiveSession( 2761b86fe063badb5f28c467ade39be0f4008688947Andreas Huber const sp<AMessage> ¬ify, uint32_t flags, 27773feb8cda587e02f1ff68095b17d47e1d6e37c70Wei Jia const sp<MediaHTTPService> &httpService) 2780df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas Huber : mNotify(notify), 2790df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas Huber mFlags(flags), 2801b86fe063badb5f28c467ade39be0f4008688947Andreas Huber mHTTPService(httpService), 2817c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mBuffering(false), 2820df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas Huber mInPreparationPhase(true), 2837c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mPollBufferingGeneration(0), 2847c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mPrevBufferPercentage(-1), 285309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mCurBandwidthIndex(-1), 2867c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mOrigBandwidthIndex(-1), 287a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mLastBandwidthBps(-1ll), 2885ef659e010e90175eb5282d9642a02f6105189bfChong Zhang mLastBandwidthStable(false), 289538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mBandwidthEstimator(new BandwidthEstimator()), 290a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang mMaxWidth(720), 291a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang mMaxHeight(480), 29214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mStreamMask(0), 2931543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih mNewStreamMask(0), 2941543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih mSwapMask(0), 2951543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih mSwitchGeneration(0), 296b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih mSubtitleGeneration(0), 29714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mLastDequeuedTimeUs(0ll), 298dcb89b3b505522efde173c105a851c412f947178Chong Zhang mRealTimeBaseUs(0ll), 29914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mReconfigurationInProgress(false), 3001543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih mSwitchInProgress(false), 301765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang mUpSwitchMark(kUpSwitchMarkUs), 302765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang mDownSwitchMark(kDownSwitchMarkUs), 303765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang mUpSwitchMargin(kUpSwitchMarginUs), 304309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mFirstTimeUsValid(false), 305309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mFirstTimeUs(0), 3060852843d304006e3ab333081fddda13b07193de8Robert Shih mLastSeekTimeUs(0), 3070852843d304006e3ab333081fddda13b07193de8Robert Shih mHasMetadata(false) { 3088ca002eedc747dd854b61cbe364b52c06869273fRobert Shih mStreams[kAudioIndex] = StreamItem("audio"); 3098ca002eedc747dd854b61cbe364b52c06869273fRobert Shih mStreams[kVideoIndex] = StreamItem("video"); 310e4f25c280a8f1655c31a745978e0fcbc61f91deeRobert Shih mStreams[kSubtitleIndex] = StreamItem("subtitles"); 31114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 3120852843d304006e3ab333081fddda13b07193de8Robert Shih for (size_t i = 0; i < kNumSources; ++i) { 3138ca002eedc747dd854b61cbe364b52c06869273fRobert Shih mPacketSources.add(indexToType(i), new AnotherPacketSource(NULL /* meta */)); 3141543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih mPacketSources2.add(indexToType(i), new AnotherPacketSource(NULL /* meta */)); 3158ca002eedc747dd854b61cbe364b52c06869273fRobert Shih } 316a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 317a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 318a44153c1a57202fb538659eb50706e60454d6273Andreas HuberLiveSession::~LiveSession() { 319964adb17885185808398507d2de88665fe193ee2Chong Zhang if (mFetcherLooper != NULL) { 320964adb17885185808398507d2de88665fe193ee2Chong Zhang mFetcherLooper->stop(); 321964adb17885185808398507d2de88665fe193ee2Chong Zhang } 322a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 323a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 3240852843d304006e3ab333081fddda13b07193de8Robert Shihint64_t LiveSession::calculateMediaTimeUs( 3250852843d304006e3ab333081fddda13b07193de8Robert Shih int64_t firstTimeUs, int64_t timeUs, int32_t discontinuitySeq) { 3260852843d304006e3ab333081fddda13b07193de8Robert Shih if (timeUs >= firstTimeUs) { 3270852843d304006e3ab333081fddda13b07193de8Robert Shih timeUs -= firstTimeUs; 3280852843d304006e3ab333081fddda13b07193de8Robert Shih } else { 3290852843d304006e3ab333081fddda13b07193de8Robert Shih timeUs = 0; 3300852843d304006e3ab333081fddda13b07193de8Robert Shih } 3310852843d304006e3ab333081fddda13b07193de8Robert Shih timeUs += mLastSeekTimeUs; 3320852843d304006e3ab333081fddda13b07193de8Robert Shih if (mDiscontinuityOffsetTimesUs.indexOfKey(discontinuitySeq) >= 0) { 3330852843d304006e3ab333081fddda13b07193de8Robert Shih timeUs += mDiscontinuityOffsetTimesUs.valueFor(discontinuitySeq); 3340852843d304006e3ab333081fddda13b07193de8Robert Shih } 3350852843d304006e3ab333081fddda13b07193de8Robert Shih return timeUs; 3360852843d304006e3ab333081fddda13b07193de8Robert Shih} 3370852843d304006e3ab333081fddda13b07193de8Robert Shih 33814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::dequeueAccessUnit( 33914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber StreamType stream, sp<ABuffer> *accessUnit) { 340964adb17885185808398507d2de88665fe193ee2Chong Zhang status_t finalResult = OK; 34114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AnotherPacketSource> packetSource = mPacketSources.valueFor(stream); 34214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 34325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ssize_t streamIdx = typeToIndex(stream); 34425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang if (streamIdx < 0) { 3455abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang return BAD_VALUE; 34625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang } 34725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang const char *streamStr = getNameForStream(stream); 348a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // Do not let client pull data if we don't have data packets yet. 349a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // We might only have a format discontinuity queued without data. 350a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // When NuPlayerDecoder dequeues the format discontinuity, it will 351a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // immediately try to getFormat. If we return NULL, NuPlayerDecoder 352a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // thinks it can do seamless change, so will not shutdown decoder. 353a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // When the actual format arrives, it can't handle it and get stuck. 354a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (!packetSource->hasDataBufferAvailable(&finalResult)) { 35525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("[%s] dequeueAccessUnit: no buffer available (finalResult=%d)", 35625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang streamStr, finalResult); 35725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 358f69c996864844e8f669308af8412cede043062a2Robert Shih if (finalResult == OK) { 359f69c996864844e8f669308af8412cede043062a2Robert Shih return -EAGAIN; 360f69c996864844e8f669308af8412cede043062a2Robert Shih } else { 361f69c996864844e8f669308af8412cede043062a2Robert Shih return finalResult; 362f69c996864844e8f669308af8412cede043062a2Robert Shih } 363f69c996864844e8f669308af8412cede043062a2Robert Shih } 364f69c996864844e8f669308af8412cede043062a2Robert Shih 365a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // Let the client dequeue as long as we have buffers available 366a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // Do not make pause/resume decisions here. 367309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 36814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber status_t err = packetSource->dequeueAccessUnit(accessUnit); 36914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 37014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (err == INFO_DISCONTINUITY) { 371309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih // adaptive streaming, discontinuities in the playlist 37214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int32_t type; 37314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK((*accessUnit)->meta()->findInt32("discontinuity", &type)); 37414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 37514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AMessage> extra; 37614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (!(*accessUnit)->meta()->findMessage("extra", &extra)) { 37714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber extra.clear(); 37814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 37914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 38014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGI("[%s] read discontinuity of type %d, extra = %s", 38114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber streamStr, 38214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber type, 38314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber extra == NULL ? "NULL" : extra->debugString().c_str()); 38414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else if (err == OK) { 385309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 386dcb89b3b505522efde173c105a851c412f947178Chong Zhang if (stream == STREAMTYPE_AUDIO || stream == STREAMTYPE_VIDEO) { 38725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang int64_t timeUs, originalTimeUs; 388309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih int32_t discontinuitySeq = 0; 3890852843d304006e3ab333081fddda13b07193de8Robert Shih StreamItem& strm = mStreams[streamIdx]; 390dcb89b3b505522efde173c105a851c412f947178Chong Zhang CHECK((*accessUnit)->meta()->findInt64("timeUs", &timeUs)); 39125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang originalTimeUs = timeUs; 392309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih (*accessUnit)->meta()->findInt32("discontinuitySeq", &discontinuitySeq); 3937c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (discontinuitySeq > (int32_t) strm.mCurDiscontinuitySeq) { 3947c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang int64_t offsetTimeUs; 3957c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (mDiscontinuityOffsetTimesUs.indexOfKey(strm.mCurDiscontinuitySeq) >= 0) { 3967c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang offsetTimeUs = mDiscontinuityOffsetTimesUs.valueFor(strm.mCurDiscontinuitySeq); 3977c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } else { 3987c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang offsetTimeUs = 0; 3997c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 4007c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 40181636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang if (mDiscontinuityAbsStartTimesUs.indexOfKey(strm.mCurDiscontinuitySeq) >= 0 40281636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang && strm.mLastDequeuedTimeUs >= 0) { 4037c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang int64_t firstTimeUs; 4047c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang firstTimeUs = mDiscontinuityAbsStartTimesUs.valueFor(strm.mCurDiscontinuitySeq); 4057c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang offsetTimeUs += strm.mLastDequeuedTimeUs - firstTimeUs; 4067c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang offsetTimeUs += strm.mLastSampleDurationUs; 4077c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } else { 4087c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang offsetTimeUs += strm.mLastSampleDurationUs; 4097c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 4107c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 4117c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mDiscontinuityOffsetTimesUs.add(discontinuitySeq, offsetTimeUs); 4127c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang strm.mCurDiscontinuitySeq = discontinuitySeq; 4137c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 414309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 415309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih int32_t discard = 0; 416309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih int64_t firstTimeUs; 417309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (mDiscontinuityAbsStartTimesUs.indexOfKey(strm.mCurDiscontinuitySeq) >= 0) { 418309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih int64_t durUs; // approximate sample duration 419309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (timeUs > strm.mLastDequeuedTimeUs) { 420309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih durUs = timeUs - strm.mLastDequeuedTimeUs; 421309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } else { 422309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih durUs = strm.mLastDequeuedTimeUs - timeUs; 423309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 424309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih strm.mLastSampleDurationUs = durUs; 425309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih firstTimeUs = mDiscontinuityAbsStartTimesUs.valueFor(strm.mCurDiscontinuitySeq); 426309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } else if ((*accessUnit)->meta()->findInt32("discard", &discard) && discard) { 427309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih firstTimeUs = timeUs; 428309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } else { 429309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mDiscontinuityAbsStartTimesUs.add(strm.mCurDiscontinuitySeq, timeUs); 430309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih firstTimeUs = timeUs; 431309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 432309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 433309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih strm.mLastDequeuedTimeUs = timeUs; 4340852843d304006e3ab333081fddda13b07193de8Robert Shih timeUs = calculateMediaTimeUs(firstTimeUs, timeUs, discontinuitySeq); 435dcb89b3b505522efde173c105a851c412f947178Chong Zhang 43625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("[%s] dequeueAccessUnit: time %lld us, original %lld us", 43725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang streamStr, (long long)timeUs, (long long)originalTimeUs); 438309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih (*accessUnit)->meta()->setInt64("timeUs", timeUs); 439dcb89b3b505522efde173c105a851c412f947178Chong Zhang mLastDequeuedTimeUs = timeUs; 440dcb89b3b505522efde173c105a851c412f947178Chong Zhang mRealTimeBaseUs = ALooper::GetNowUs() - timeUs; 441dcb89b3b505522efde173c105a851c412f947178Chong Zhang } else if (stream == STREAMTYPE_SUBTITLES) { 442b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih int32_t subtitleGeneration; 443b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih if ((*accessUnit)->meta()->findInt32("subtitleGeneration", &subtitleGeneration) 444b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih && subtitleGeneration != mSubtitleGeneration) { 445b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih return -EAGAIN; 446b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih }; 447dcb89b3b505522efde173c105a851c412f947178Chong Zhang (*accessUnit)->meta()->setInt32( 448dcb89b3b505522efde173c105a851c412f947178Chong Zhang "trackIndex", mPlaylist->getSelectedIndex()); 449dcb89b3b505522efde173c105a851c412f947178Chong Zhang (*accessUnit)->meta()->setInt64("baseUs", mRealTimeBaseUs); 4500852843d304006e3ab333081fddda13b07193de8Robert Shih } else if (stream == STREAMTYPE_METADATA) { 4510852843d304006e3ab333081fddda13b07193de8Robert Shih HLSTime mdTime((*accessUnit)->meta()); 4520852843d304006e3ab333081fddda13b07193de8Robert Shih if (mDiscontinuityAbsStartTimesUs.indexOfKey(mdTime.mSeq) < 0) { 4530852843d304006e3ab333081fddda13b07193de8Robert Shih packetSource->requeueAccessUnit((*accessUnit)); 4540852843d304006e3ab333081fddda13b07193de8Robert Shih return -EAGAIN; 4550852843d304006e3ab333081fddda13b07193de8Robert Shih } else { 4560852843d304006e3ab333081fddda13b07193de8Robert Shih int64_t firstTimeUs = mDiscontinuityAbsStartTimesUs.valueFor(mdTime.mSeq); 4570852843d304006e3ab333081fddda13b07193de8Robert Shih int64_t timeUs = calculateMediaTimeUs(firstTimeUs, mdTime.mTimeUs, mdTime.mSeq); 4580852843d304006e3ab333081fddda13b07193de8Robert Shih (*accessUnit)->meta()->setInt64("timeUs", timeUs); 4590852843d304006e3ab333081fddda13b07193de8Robert Shih (*accessUnit)->meta()->setInt64("baseUs", mRealTimeBaseUs); 4600852843d304006e3ab333081fddda13b07193de8Robert Shih } 461dcb89b3b505522efde173c105a851c412f947178Chong Zhang } 46214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else { 46314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGI("[%s] encountered error %d", streamStr, err); 46414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 46514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 46614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return err; 46714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 46814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 469a83eebb78c3a7d57a769dac965b17a8aad7c7b8fRobert Shihstatus_t LiveSession::getStreamFormatMeta(StreamType stream, sp<MetaData> *meta) { 47014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (!(mStreamMask & stream)) { 47114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return UNKNOWN_ERROR; 47214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 47314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 47414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AnotherPacketSource> packetSource = mPacketSources.valueFor(stream); 47514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 476a83eebb78c3a7d57a769dac965b17a8aad7c7b8fRobert Shih *meta = packetSource->getFormat(); 47714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 478a83eebb78c3a7d57a769dac965b17a8aad7c7b8fRobert Shih if (*meta == NULL) { 4797350b057ca864f5dc9e53d48e34710a8e81133f8Robert Shih return -EWOULDBLOCK; 48014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 48114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 4827c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (stream == STREAMTYPE_AUDIO) { 4837c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // set AAC input buffer size to 32K bytes (256kbps x 1sec) 484a83eebb78c3a7d57a769dac965b17a8aad7c7b8fRobert Shih (*meta)->setInt32(kKeyMaxInputSize, 32 * 1024); 485a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang } else if (stream == STREAMTYPE_VIDEO) { 486a83eebb78c3a7d57a769dac965b17a8aad7c7b8fRobert Shih (*meta)->setInt32(kKeyMaxWidth, mMaxWidth); 487a83eebb78c3a7d57a769dac965b17a8aad7c7b8fRobert Shih (*meta)->setInt32(kKeyMaxHeight, mMaxHeight); 4887c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 4897c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 490a83eebb78c3a7d57a769dac965b17a8aad7c7b8fRobert Shih return OK; 491a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 492a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 4935abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhangsp<HTTPDownloader> LiveSession::getHTTPDownloader() { 4945abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang return new HTTPDownloader(mHTTPService, mExtraHeaders); 495a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang} 496a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 49748fa06d1e80a872c7495804979256e021e566ae0Wei Jiavoid LiveSession::setBufferingSettings( 49848fa06d1e80a872c7495804979256e021e566ae0Wei Jia const BufferingSettings &buffering) { 49948fa06d1e80a872c7495804979256e021e566ae0Wei Jia sp<AMessage> msg = new AMessage(kWhatSetBufferingSettings, this); 50048fa06d1e80a872c7495804979256e021e566ae0Wei Jia writeToAMessage(msg, buffering); 50148fa06d1e80a872c7495804979256e021e566ae0Wei Jia msg->post(); 50248fa06d1e80a872c7495804979256e021e566ae0Wei Jia} 50348fa06d1e80a872c7495804979256e021e566ae0Wei Jia 50414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::connectAsync( 505ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber const char *url, const KeyedVector<String8, String8> *headers) { 5061d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> msg = new AMessage(kWhatConnect, this); 507a44153c1a57202fb538659eb50706e60454d6273Andreas Huber msg->setString("url", url); 508ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber 509ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber if (headers != NULL) { 510ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber msg->setPointer( 511ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber "headers", 512ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber new KeyedVector<String8, String8>(*headers)); 513ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber } 514ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber 515a44153c1a57202fb538659eb50706e60454d6273Andreas Huber msg->post(); 516a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 517a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 51814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::disconnect() { 5191d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> msg = new AMessage(kWhatDisconnect, this); 520ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber 52114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AMessage> response; 52214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber status_t err = msg->postAndAwaitResponse(&response); 523ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber 52414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return err; 525a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 526a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 527c5de09127e9e0d5df7aa587be317e1487d793245Wei Jiastatus_t LiveSession::seekTo(int64_t timeUs, MediaPlayerSeekMode mode) { 5281d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> msg = new AMessage(kWhatSeek, this); 529a44153c1a57202fb538659eb50706e60454d6273Andreas Huber msg->setInt64("timeUs", timeUs); 530c5de09127e9e0d5df7aa587be317e1487d793245Wei Jia msg->setInt32("mode", mode); 531a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 53214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AMessage> response; 53314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber status_t err = msg->postAndAwaitResponse(&response); 53414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 53514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return err; 536a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 537a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 5387c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangbool LiveSession::checkSwitchProgress( 5397c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AMessage> &stopParams, int64_t delayUs, bool *needResumeUntil) { 5407c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang AString newUri; 5417c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang CHECK(stopParams->findString("uri", &newUri)); 5427c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 5437c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang *needResumeUntil = false; 5447c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AMessage> firstNewMeta[kMaxStreams]; 5457c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang for (size_t i = 0; i < kMaxStreams; ++i) { 5467c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang StreamType stream = indexToType(i); 5477c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (!(mSwapMask & mNewStreamMask & stream) 5487c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang || (mStreams[i].mNewUri != newUri)) { 5497c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang continue; 5507c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 5517c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (stream == STREAMTYPE_SUBTITLES) { 5527c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang continue; 5537c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 5547c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AnotherPacketSource> &source = mPacketSources.editValueAt(i); 5557c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 5567c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // First, get latest dequeued meta, which is where the decoder is at. 5577c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // (when upswitching, we take the meta after a certain delay, so that 5587c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // the decoder is left with some cushion) 5597c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AMessage> lastDequeueMeta, lastEnqueueMeta; 5607c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (delayUs > 0) { 5617c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang lastDequeueMeta = source->getMetaAfterLastDequeued(delayUs); 562d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (lastDequeueMeta == NULL) { 563d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // this means we don't have enough cushion, try again later 564d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang ALOGV("[%s] up switching failed due to insufficient buffer", 56525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang getNameForStream(stream)); 566d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang return false; 567d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang } 5687c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } else { 569d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // It's okay for lastDequeueMeta to be NULL here, it means the 570d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // decoder hasn't even started dequeueing 5717c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang lastDequeueMeta = source->getLatestDequeuedMeta(); 5727c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 5737c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // Then, trim off packets at beginning of mPacketSources2 that's before 5747c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // the latest dequeued time. These samples are definitely too late. 575d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang firstNewMeta[i] = mPacketSources2.editValueAt(i) 576d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang ->trimBuffersBeforeMeta(lastDequeueMeta); 577d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang 5787c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // Now firstNewMeta[i] is the first sample after the trim. 5797c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // If it's NULL, we failed because dequeue already past all samples 5807c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // in mPacketSource2, we have to try again. 5817c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (firstNewMeta[i] == NULL) { 582d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang HLSTime dequeueTime(lastDequeueMeta); 5837c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGV("[%s] dequeue time (%d, %lld) past start time", 58425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang getNameForStream(stream), 585d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang dequeueTime.mSeq, (long long) dequeueTime.mTimeUs); 5867c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return false; 5877c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 5887c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 5897c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // Otherwise, we check if mPacketSources2 overlaps with what old fetcher 5907c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // already fetched, and see if we need to resumeUntil 5917c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang lastEnqueueMeta = source->getLatestEnqueuedMeta(); 5927c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // lastEnqueueMeta == NULL means old fetcher stopped at a discontinuity 5937c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // boundary, no need to resume as the content will look different anyways 5947c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (lastEnqueueMeta != NULL) { 595d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang HLSTime lastTime(lastEnqueueMeta), startTime(firstNewMeta[i]); 5967c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 5977c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // no need to resume old fetcher if new fetcher started in different 5987c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // discontinuity sequence, as the content will look different. 599d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang *needResumeUntil |= (startTime.mSeq == lastTime.mSeq 600d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang && startTime.mTimeUs - lastTime.mTimeUs > kResumeThresholdUs); 6017c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 602d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // update the stopTime for resumeUntil 603d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang stopParams->setInt32("discontinuitySeq", startTime.mSeq); 604d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang stopParams->setInt64(getKeyForStream(stream), startTime.mTimeUs); 6057c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 6067c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 6077c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 6087c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // if we're here, it means dequeue progress hasn't passed some samples in 6097c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // mPacketSource2, we can trim off the excess in mPacketSource. 6107c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // (old fetcher might still need to resumeUntil the start time of new fetcher) 6117c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang for (size_t i = 0; i < kMaxStreams; ++i) { 6127c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang StreamType stream = indexToType(i); 6137c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (!(mSwapMask & mNewStreamMask & stream) 614d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang || (newUri != mStreams[i].mNewUri) 615d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang || stream == STREAMTYPE_SUBTITLES) { 6167c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang continue; 6177c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 618d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang mPacketSources.valueFor(stream)->trimBuffersAfterMeta(firstNewMeta[i]); 6197c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 6207c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 6217c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // no resumeUntil if already underflow 6227c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang *needResumeUntil &= !mBuffering; 6237c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 6247c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return true; 6257c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang} 6267c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 627a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onMessageReceived(const sp<AMessage> &msg) { 628a44153c1a57202fb538659eb50706e60454d6273Andreas Huber switch (msg->what()) { 62948fa06d1e80a872c7495804979256e021e566ae0Wei Jia case kWhatSetBufferingSettings: 63048fa06d1e80a872c7495804979256e021e566ae0Wei Jia { 63148fa06d1e80a872c7495804979256e021e566ae0Wei Jia readFromAMessage(msg, &mBufferingSettings); 63248fa06d1e80a872c7495804979256e021e566ae0Wei Jia break; 63348fa06d1e80a872c7495804979256e021e566ae0Wei Jia } 63448fa06d1e80a872c7495804979256e021e566ae0Wei Jia 635a44153c1a57202fb538659eb50706e60454d6273Andreas Huber case kWhatConnect: 63614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 637a44153c1a57202fb538659eb50706e60454d6273Andreas Huber onConnect(msg); 638a44153c1a57202fb538659eb50706e60454d6273Andreas Huber break; 63914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 640a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 641a44153c1a57202fb538659eb50706e60454d6273Andreas Huber case kWhatDisconnect: 64214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 64314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->senderAwaitsResponse(&mDisconnectReplyID)); 64414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 64514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (mReconfigurationInProgress) { 64614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 64714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 64814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 64914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber finishDisconnect(); 650a44153c1a57202fb538659eb50706e60454d6273Andreas Huber break; 65114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 652a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 65314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case kWhatSeek: 65414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 655a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar if (mReconfigurationInProgress) { 656800599cdd50737de1cde483a34b39923750b0658Robert Shih msg->post(50000); 657a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar break; 658800599cdd50737de1cde483a34b39923750b0658Robert Shih } 659a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar 660a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar CHECK(msg->senderAwaitsResponse(&mSeekReplyID)); 661a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar mSeekReply = new AMessage; 662a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar 663a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar onSeek(msg); 66414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 66514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 66614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 66714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case kWhatFetcherNotify: 66814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 66914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int32_t what; 67014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->findInt32("what", &what)); 67114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 67214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber switch (what) { 67314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case PlaylistFetcher::kWhatStarted: 67414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 67514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case PlaylistFetcher::kWhatPaused: 67614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case PlaylistFetcher::kWhatStopped: 67714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 678a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang AString uri; 679a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang CHECK(msg->findString("uri", &uri)); 680a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang ssize_t index = mFetcherInfos.indexOfKey(uri); 681a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (index < 0) { 682a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // ignore msgs from fetchers that's already gone 683a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang break; 684a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 685a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 68625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("fetcher-%d %s", 68725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang mFetcherInfos[index].mFetcher->getFetcherID(), 68825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang what == PlaylistFetcher::kWhatPaused ? 68925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang "paused" : "stopped"); 69025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 69114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (what == PlaylistFetcher::kWhatStopped) { 692964adb17885185808398507d2de88665fe193ee2Chong Zhang mFetcherLooper->unregisterHandler( 693964adb17885185808398507d2de88665fe193ee2Chong Zhang mFetcherInfos[index].mFetcher->id()); 694964adb17885185808398507d2de88665fe193ee2Chong Zhang mFetcherInfos.removeItemsAt(index); 695a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } else if (what == PlaylistFetcher::kWhatPaused) { 696a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang int32_t seekMode; 697a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang CHECK(msg->findInt32("seekMode", &seekMode)); 698a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang for (size_t i = 0; i < kMaxStreams; ++i) { 699a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (mStreams[i].mUri == uri) { 700a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mStreams[i].mSeekMode = (SeekMode) seekMode; 701a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 702309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 70314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 70414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 70514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (mContinuation != NULL) { 706b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross CHECK_GT(mContinuationCounter, 0u); 70714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (--mContinuationCounter == 0) { 70814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mContinuation->post(); 70914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 71025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("%zu fetcher(s) left", mContinuationCounter); 71114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 71214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 71314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 71414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 71514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case PlaylistFetcher::kWhatDurationUpdate: 71614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 71714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber AString uri; 71814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->findString("uri", &uri)); 71914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 72014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int64_t durationUs; 72114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->findInt64("durationUs", &durationUs)); 72214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 723964adb17885185808398507d2de88665fe193ee2Chong Zhang ssize_t index = mFetcherInfos.indexOfKey(uri); 724964adb17885185808398507d2de88665fe193ee2Chong Zhang if (index >= 0) { 725964adb17885185808398507d2de88665fe193ee2Chong Zhang FetcherInfo *info = &mFetcherInfos.editValueFor(uri); 726964adb17885185808398507d2de88665fe193ee2Chong Zhang info->mDurationUs = durationUs; 727964adb17885185808398507d2de88665fe193ee2Chong Zhang } 72814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 72914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 73014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 7317c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang case PlaylistFetcher::kWhatTargetDurationUpdate: 7327c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang { 7337c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang int64_t targetDurationUs; 7347c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang CHECK(msg->findInt64("targetDurationUs", &targetDurationUs)); 735d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang mUpSwitchMark = min(kUpSwitchMarkUs, targetDurationUs * 7 / 4); 736765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang mDownSwitchMark = min(kDownSwitchMarkUs, targetDurationUs * 9 / 4); 737765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang mUpSwitchMargin = min(kUpSwitchMarginUs, targetDurationUs); 7387c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang break; 7397c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 7407c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 74114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case PlaylistFetcher::kWhatError: 74214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 74314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber status_t err; 74414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->findInt32("err", &err)); 74514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 74614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGE("XXX Received error %d from PlaylistFetcher.", err); 74714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 74815f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih // handle EOS on subtitle tracks independently 74915f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih AString uri; 75015f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih if (err == ERROR_END_OF_STREAM && msg->findString("uri", &uri)) { 75115f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih ssize_t i = mFetcherInfos.indexOfKey(uri); 75215f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih if (i >= 0) { 75315f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih const sp<PlaylistFetcher> &fetcher = mFetcherInfos.valueAt(i).mFetcher; 75415f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih if (fetcher != NULL) { 75515f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih uint32_t type = fetcher->getStreamTypeMask(); 75615f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih if (type == STREAMTYPE_SUBTITLES) { 75715f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih mPacketSources.valueFor( 75815f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih STREAMTYPE_SUBTITLES)->signalEOS(err);; 75915f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih break; 76015f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih } 76115f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih } 76215f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih } 76315f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih } 76415f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih 7655ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // remember the failure index (as mCurBandwidthIndex will be restored 7665ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // after cancelBandwidthSwitch()), and record last fail time 7675ef659e010e90175eb5282d9642a02f6105189bfChong Zhang size_t failureIndex = mCurBandwidthIndex; 7685ef659e010e90175eb5282d9642a02f6105189bfChong Zhang mBandwidthItems.editItemAt( 7695ef659e010e90175eb5282d9642a02f6105189bfChong Zhang failureIndex).mLastFailureUs = ALooper::GetNowUs(); 7705ef659e010e90175eb5282d9642a02f6105189bfChong Zhang 7715ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (mSwitchInProgress) { 7725ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // if error happened when we switch to a variant, try fallback 7735ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // to other variant to save the session 7745ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (tryBandwidthFallback()) { 7755ef659e010e90175eb5282d9642a02f6105189bfChong Zhang break; 7765ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } 7775ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } 7785ef659e010e90175eb5282d9642a02f6105189bfChong Zhang 77914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (mInPreparationPhase) { 78014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber postPrepared(err); 78114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 78214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 7831543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih cancelBandwidthSwitch(); 7841543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 78514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mPacketSources.valueFor(STREAMTYPE_AUDIO)->signalEOS(err); 78614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 78714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mPacketSources.valueFor(STREAMTYPE_VIDEO)->signalEOS(err); 78814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 78914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mPacketSources.valueFor( 79014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber STREAMTYPE_SUBTITLES)->signalEOS(err); 79114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 7927c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang postError(err); 7937c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang break; 7947c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 7957c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 7967c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang case PlaylistFetcher::kWhatStopReached: 7977c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang { 7987c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGV("kWhatStopReached"); 7997c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 800d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang AString oldUri; 801d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang CHECK(msg->findString("uri", &oldUri)); 8027c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 803d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang ssize_t index = mFetcherInfos.indexOfKey(oldUri); 8047c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (index < 0) { 8057c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang break; 8067c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 8077c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 808d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang tryToFinishBandwidthSwitch(oldUri); 80914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 81014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 81114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 8121543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih case PlaylistFetcher::kWhatStartedAt: 8131543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih { 8141543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih int32_t switchGeneration; 8151543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih CHECK(msg->findInt32("switchGeneration", &switchGeneration)); 8161543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 81725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("kWhatStartedAt: switchGen=%d, mSwitchGen=%d", 81825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang switchGeneration, mSwitchGeneration); 81925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 8201543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih if (switchGeneration != mSwitchGeneration) { 8211543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih break; 8221543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 8231543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 824a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang AString uri; 825a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang CHECK(msg->findString("uri", &uri)); 8267c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 8277c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // mark new fetcher mToBeResumed 828a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang ssize_t index = mFetcherInfos.indexOfKey(uri); 829a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (index >= 0) { 830a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mFetcherInfos.editValueAt(index).mToBeResumed = true; 831a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 832a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 8337c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // temporarily disable packet sources to be swapped to prevent 8347c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // NuPlayerDecoder from dequeuing while we check progress 8357c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang for (size_t i = 0; i < mPacketSources.size(); ++i) { 8367c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if ((mSwapMask & mPacketSources.keyAt(i)) 8377c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang && uri == mStreams[i].mNewUri) { 8387c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mPacketSources.editValueAt(i)->enable(false); 8391543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 8401543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 8417c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang bool switchUp = (mCurBandwidthIndex > mOrigBandwidthIndex); 8427c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // If switching up, require a cushion bigger than kUnderflowMark 8437c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // to avoid buffering immediately after the switch. 8447c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // (If we don't have that cushion we'd rather cancel and try again.) 84548fa06d1e80a872c7495804979256e021e566ae0Wei Jia int64_t delayUs = 84648fa06d1e80a872c7495804979256e021e566ae0Wei Jia switchUp ? 8479bb3803a80a680ea7a3bc11e07b8a89ccddee003Wei Jia (kUnderflowMarkMs * 1000ll + 1000000ll) 84848fa06d1e80a872c7495804979256e021e566ae0Wei Jia : 0; 8497c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang bool needResumeUntil = false; 8507c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AMessage> stopParams = msg; 8517c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (checkSwitchProgress(stopParams, delayUs, &needResumeUntil)) { 8527c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // playback time hasn't passed startAt time 8537c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (!needResumeUntil) { 85425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("finish switch"); 8557c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang for (size_t i = 0; i < kMaxStreams; ++i) { 8567c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if ((mSwapMask & indexToType(i)) 8577c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang && uri == mStreams[i].mNewUri) { 8587c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // have to make a copy of mStreams[i].mUri because 8597c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // tryToFinishBandwidthSwitch is modifying mStreams[] 8607c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang AString oldURI = mStreams[i].mUri; 8617c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang tryToFinishBandwidthSwitch(oldURI); 8627c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang break; 8637c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 8647c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 8657c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } else { 8667c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // startAt time is after last enqueue time 8677c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // Resume fetcher for the original variant; the resumed fetcher should 8687c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // continue until the timestamps found in msg, which is stored by the 8697c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // new fetcher to indicate where the new variant has started buffering. 87025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("finish switch with resumeUntilAsync"); 8717c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang for (size_t i = 0; i < mFetcherInfos.size(); i++) { 8727c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang const FetcherInfo &info = mFetcherInfos.valueAt(i); 8737c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (info.mToBeRemoved) { 8747c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang info.mFetcher->resumeUntilAsync(stopParams); 8757c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 8767c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 8777c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 8787c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } else { 8797c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // playback time passed startAt time 8807c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (switchUp) { 8817c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // if switching up, cancel and retry if condition satisfies again 88225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("cancel up switch because we're too late"); 8837c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang cancelBandwidthSwitch(true /* resume */); 8847c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } else { 88525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("retry down switch at next sample"); 8867c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang resumeFetcher(uri, mSwapMask, -1, true /* newUri */); 8877c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 8887c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 8897c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // re-enable all packet sources 8907c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang for (size_t i = 0; i < mPacketSources.size(); ++i) { 8917c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mPacketSources.editValueAt(i)->enable(true); 8927c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 8937c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 8941543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih break; 8951543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 8961543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 8975abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang case PlaylistFetcher::kWhatPlaylistFetched: 8985abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang { 8995abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang onMasterPlaylistFetched(msg); 9005abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang break; 9015abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } 9025abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 9030852843d304006e3ab333081fddda13b07193de8Robert Shih case PlaylistFetcher::kWhatMetadataDetected: 9040852843d304006e3ab333081fddda13b07193de8Robert Shih { 9050852843d304006e3ab333081fddda13b07193de8Robert Shih if (!mHasMetadata) { 9060852843d304006e3ab333081fddda13b07193de8Robert Shih mHasMetadata = true; 9070852843d304006e3ab333081fddda13b07193de8Robert Shih sp<AMessage> notify = mNotify->dup(); 9080852843d304006e3ab333081fddda13b07193de8Robert Shih notify->setInt32("what", kWhatMetadataDetected); 9090852843d304006e3ab333081fddda13b07193de8Robert Shih notify->post(); 9100852843d304006e3ab333081fddda13b07193de8Robert Shih } 9110852843d304006e3ab333081fddda13b07193de8Robert Shih break; 9120852843d304006e3ab333081fddda13b07193de8Robert Shih } 9130852843d304006e3ab333081fddda13b07193de8Robert Shih 91414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber default: 91514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber TRESPASS(); 91614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 91714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 91814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 91914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 92014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 921dcb89b3b505522efde173c105a851c412f947178Chong Zhang case kWhatChangeConfiguration: 922dcb89b3b505522efde173c105a851c412f947178Chong Zhang { 923dcb89b3b505522efde173c105a851c412f947178Chong Zhang onChangeConfiguration(msg); 924dcb89b3b505522efde173c105a851c412f947178Chong Zhang break; 925dcb89b3b505522efde173c105a851c412f947178Chong Zhang } 926dcb89b3b505522efde173c105a851c412f947178Chong Zhang 92714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case kWhatChangeConfiguration2: 92814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 92914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber onChangeConfiguration2(msg); 93014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 93114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 93214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 93314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case kWhatChangeConfiguration3: 93414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 93514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber onChangeConfiguration3(msg); 93614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 93714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 93814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 939964adb17885185808398507d2de88665fe193ee2Chong Zhang case kWhatPollBuffering: 9400ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih { 941964adb17885185808398507d2de88665fe193ee2Chong Zhang int32_t generation; 942964adb17885185808398507d2de88665fe193ee2Chong Zhang CHECK(msg->findInt32("generation", &generation)); 943964adb17885185808398507d2de88665fe193ee2Chong Zhang if (generation == mPollBufferingGeneration) { 944964adb17885185808398507d2de88665fe193ee2Chong Zhang onPollBuffering(); 945964adb17885185808398507d2de88665fe193ee2Chong Zhang } 9460ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih break; 9470ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih } 9480ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih 949a44153c1a57202fb538659eb50706e60454d6273Andreas Huber default: 950a44153c1a57202fb538659eb50706e60454d6273Andreas Huber TRESPASS(); 951a44153c1a57202fb538659eb50706e60454d6273Andreas Huber break; 952a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 953a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 954a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 955a44153c1a57202fb538659eb50706e60454d6273Andreas Huber// static 9565ef659e010e90175eb5282d9642a02f6105189bfChong Zhangbool LiveSession::isBandwidthValid(const BandwidthItem &item) { 9575ef659e010e90175eb5282d9642a02f6105189bfChong Zhang static const int64_t kBlacklistWindowUs = 300 * 1000000ll; 9585ef659e010e90175eb5282d9642a02f6105189bfChong Zhang return item.mLastFailureUs < 0 9595ef659e010e90175eb5282d9642a02f6105189bfChong Zhang || ALooper::GetNowUs() - item.mLastFailureUs > kBlacklistWindowUs; 9605ef659e010e90175eb5282d9642a02f6105189bfChong Zhang} 9615ef659e010e90175eb5282d9642a02f6105189bfChong Zhang 9625ef659e010e90175eb5282d9642a02f6105189bfChong Zhang// static 963a44153c1a57202fb538659eb50706e60454d6273Andreas Huberint LiveSession::SortByBandwidth(const BandwidthItem *a, const BandwidthItem *b) { 964a44153c1a57202fb538659eb50706e60454d6273Andreas Huber if (a->mBandwidth < b->mBandwidth) { 965a44153c1a57202fb538659eb50706e60454d6273Andreas Huber return -1; 966a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } else if (a->mBandwidth == b->mBandwidth) { 967a44153c1a57202fb538659eb50706e60454d6273Andreas Huber return 0; 968a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 969a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 970a44153c1a57202fb538659eb50706e60454d6273Andreas Huber return 1; 971a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 972a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 9738ca002eedc747dd854b61cbe364b52c06869273fRobert Shih// static 9748ca002eedc747dd854b61cbe364b52c06869273fRobert ShihLiveSession::StreamType LiveSession::indexToType(int idx) { 9750852843d304006e3ab333081fddda13b07193de8Robert Shih CHECK(idx >= 0 && idx < kNumSources); 9768ca002eedc747dd854b61cbe364b52c06869273fRobert Shih return (StreamType)(1 << idx); 9778ca002eedc747dd854b61cbe364b52c06869273fRobert Shih} 9788ca002eedc747dd854b61cbe364b52c06869273fRobert Shih 979f69c996864844e8f669308af8412cede043062a2Robert Shih// static 980f69c996864844e8f669308af8412cede043062a2Robert Shihssize_t LiveSession::typeToIndex(int32_t type) { 981f69c996864844e8f669308af8412cede043062a2Robert Shih switch (type) { 982f69c996864844e8f669308af8412cede043062a2Robert Shih case STREAMTYPE_AUDIO: 983f69c996864844e8f669308af8412cede043062a2Robert Shih return 0; 984f69c996864844e8f669308af8412cede043062a2Robert Shih case STREAMTYPE_VIDEO: 985f69c996864844e8f669308af8412cede043062a2Robert Shih return 1; 986f69c996864844e8f669308af8412cede043062a2Robert Shih case STREAMTYPE_SUBTITLES: 987f69c996864844e8f669308af8412cede043062a2Robert Shih return 2; 9880852843d304006e3ab333081fddda13b07193de8Robert Shih case STREAMTYPE_METADATA: 9890852843d304006e3ab333081fddda13b07193de8Robert Shih return 3; 990f69c996864844e8f669308af8412cede043062a2Robert Shih default: 991f69c996864844e8f669308af8412cede043062a2Robert Shih return -1; 992f69c996864844e8f669308af8412cede043062a2Robert Shih }; 993f69c996864844e8f669308af8412cede043062a2Robert Shih return -1; 994f69c996864844e8f669308af8412cede043062a2Robert Shih} 995f69c996864844e8f669308af8412cede043062a2Robert Shih 996a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onConnect(const sp<AMessage> &msg) { 9975abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang CHECK(msg->findString("url", &mMasterURL)); 9985abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 9995abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // TODO currently we don't know if we are coming here from incognito mode 10005abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang ALOGI("onConnect %s", uriDebugString(mMasterURL).c_str()); 1001a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1002ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber KeyedVector<String8, String8> *headers = NULL; 1003ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber if (!msg->findPointer("headers", (void **)&headers)) { 1004ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber mExtraHeaders.clear(); 1005ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber } else { 1006ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber mExtraHeaders = *headers; 1007ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber 1008ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber delete headers; 1009ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber headers = NULL; 1010ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber } 1011ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber 1012964adb17885185808398507d2de88665fe193ee2Chong Zhang // create looper for fetchers 1013964adb17885185808398507d2de88665fe193ee2Chong Zhang if (mFetcherLooper == NULL) { 1014964adb17885185808398507d2de88665fe193ee2Chong Zhang mFetcherLooper = new ALooper(); 1015964adb17885185808398507d2de88665fe193ee2Chong Zhang 1016964adb17885185808398507d2de88665fe193ee2Chong Zhang mFetcherLooper->setName("Fetcher"); 10174e69ad15e481883b53ddd37e371ab5f3560dca7aWei Jia mFetcherLooper->start(false, /* runOnCallingThread */ 10184e69ad15e481883b53ddd37e371ab5f3560dca7aWei Jia true /* canCallJava */); 1019964adb17885185808398507d2de88665fe193ee2Chong Zhang } 1020964adb17885185808398507d2de88665fe193ee2Chong Zhang 10215abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // create fetcher to fetch the master playlist 10225abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang addFetcher(mMasterURL.c_str())->fetchPlaylistAsync(); 10235abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang} 10245abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 10255abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhangvoid LiveSession::onMasterPlaylistFetched(const sp<AMessage> &msg) { 10265abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang AString uri; 10275abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang CHECK(msg->findString("uri", &uri)); 10285abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang ssize_t index = mFetcherInfos.indexOfKey(uri); 10295abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang if (index < 0) { 10305abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang ALOGW("fetcher for master playlist is gone."); 10315abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang return; 10325abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } 10335abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 10345abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // no longer useful, remove 10355abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang mFetcherLooper->unregisterHandler(mFetcherInfos[index].mFetcher->id()); 10365abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang mFetcherInfos.removeItemsAt(index); 10375abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 10385abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang CHECK(msg->findObject("playlist", (sp<RefBase> *)&mPlaylist)); 10395abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang if (mPlaylist == NULL) { 10405abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang ALOGE("unable to fetch master playlist %s.", 10415abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang uriDebugString(mMasterURL).c_str()); 10425abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 10435abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang postPrepared(ERROR_IO); 10445abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang return; 10455abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } 104614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // We trust the content provider to make a reasonable choice of preferred 104714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // initial bandwidth by listing it first in the variant playlist. 104814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // At startup we really don't have a good estimate on the available 104914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // network bandwidth since we haven't tranferred any data yet. Once 105014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // we have we can make a better informed choice. 105114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber size_t initialBandwidth = 0; 105214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber size_t initialBandwidthIndex = 0; 105314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 1054a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang int32_t maxWidth = 0; 1055a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang int32_t maxHeight = 0; 1056a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang 105714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (mPlaylist->isVariantPlaylist()) { 1058d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang Vector<BandwidthItem> itemsWithVideo; 105914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber for (size_t i = 0; i < mPlaylist->size(); ++i) { 1060a44153c1a57202fb538659eb50706e60454d6273Andreas Huber BandwidthItem item; 1061a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 106214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber item.mPlaylistIndex = i; 10635ef659e010e90175eb5282d9642a02f6105189bfChong Zhang item.mLastFailureUs = -1ll; 106414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 1065a44153c1a57202fb538659eb50706e60454d6273Andreas Huber sp<AMessage> meta; 106614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber AString uri; 106714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mPlaylist->itemAt(i, &uri, &meta); 1068a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1069a44153c1a57202fb538659eb50706e60454d6273Andreas Huber CHECK(meta->findInt32("bandwidth", (int32_t *)&item.mBandwidth)); 1070a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1071a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang int32_t width, height; 1072a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang if (meta->findInt32("width", &width)) { 1073a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang maxWidth = max(maxWidth, width); 1074a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang } 1075a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang if (meta->findInt32("height", &height)) { 1076a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang maxHeight = max(maxHeight, height); 1077a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang } 1078a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang 1079a44153c1a57202fb538659eb50706e60454d6273Andreas Huber mBandwidthItems.push(item); 1080d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (mPlaylist->hasType(i, "video")) { 1081d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang itemsWithVideo.push(item); 1082d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang } 1083d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang } 1084d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // remove the audio-only variants if we have at least one with video 1085d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (!itemsWithVideo.empty() 1086d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang && itemsWithVideo.size() < mBandwidthItems.size()) { 1087d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang mBandwidthItems.clear(); 1088d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang for (size_t i = 0; i < itemsWithVideo.size(); ++i) { 1089d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang mBandwidthItems.push(itemsWithVideo[i]); 1090d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang } 1091a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1092a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1093a44153c1a57202fb538659eb50706e60454d6273Andreas Huber CHECK_GT(mBandwidthItems.size(), 0u); 1094d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang initialBandwidth = mBandwidthItems[0].mBandwidth; 1095a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1096a44153c1a57202fb538659eb50706e60454d6273Andreas Huber mBandwidthItems.sort(SortByBandwidth); 109714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 109814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber for (size_t i = 0; i < mBandwidthItems.size(); ++i) { 109914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (mBandwidthItems.itemAt(i).mBandwidth == initialBandwidth) { 110014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber initialBandwidthIndex = i; 110114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 110214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 110314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 110414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else { 110514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // dummy item. 110614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber BandwidthItem item; 110714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber item.mPlaylistIndex = 0; 110814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber item.mBandwidth = 0; 110914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mBandwidthItems.push(item); 1110a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1111a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1112a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang mMaxWidth = maxWidth > 0 ? maxWidth : mMaxWidth; 1113a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang mMaxHeight = maxHeight > 0 ? maxHeight : mMaxHeight; 1114a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang 1115309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mPlaylist->pickRandomMediaItems(); 1116dcb89b3b505522efde173c105a851c412f947178Chong Zhang changeConfiguration( 1117309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 0ll /* timeUs */, initialBandwidthIndex, false /* pickTrack */); 1118a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 1119a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 112014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::finishDisconnect() { 1121a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang ALOGV("finishDisconnect"); 1122a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 112314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // No reconfiguration is currently pending, make sure none will trigger 112414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // during disconnection either. 11251543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih cancelBandwidthSwitch(); 11261543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 1127964adb17885185808398507d2de88665fe193ee2Chong Zhang // cancel buffer polling 1128964adb17885185808398507d2de88665fe193ee2Chong Zhang cancelPollBuffering(); 11290ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih 11305abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // TRICKY: don't wait for all fetcher to be stopped when disconnecting 11315abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // 11325abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // Some fetchers might be stuck in connect/getSize at this point. These 11335abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // operations will eventually timeout (as we have a timeout set in 11345abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // MediaHTTPConnection), but we don't want to block the main UI thread 11355abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // until then. Here we just need to make sure we clear all references 11365abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // to the fetchers, so that when they finally exit from the blocking 11375abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // operation, they can be destructed. 11385abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // 11395abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // There is one very tricky point though. For this scheme to work, the 11405abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // fecther must hold a reference to LiveSession, so that LiveSession is 11415abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // destroyed after fetcher. Otherwise LiveSession would get stuck in its 11425abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // own destructor when it waits for mFetcherLooper to stop, which still 11435abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // blocks main UI thread. 114414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber for (size_t i = 0; i < mFetcherInfos.size(); ++i) { 114514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mFetcherInfos.valueAt(i).mFetcher->stopAsync(); 11465abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang mFetcherLooper->unregisterHandler( 11475abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang mFetcherInfos.valueAt(i).mFetcher->id()); 114814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 11495abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang mFetcherInfos.clear(); 115014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 115114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mPacketSources.valueFor(STREAMTYPE_AUDIO)->signalEOS(ERROR_END_OF_STREAM); 115214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mPacketSources.valueFor(STREAMTYPE_VIDEO)->signalEOS(ERROR_END_OF_STREAM); 115314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 115414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mPacketSources.valueFor( 115514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber STREAMTYPE_SUBTITLES)->signalEOS(ERROR_END_OF_STREAM); 115614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 115714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AMessage> response = new AMessage; 115814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber response->setInt32("err", OK); 115914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 116014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber response->postReply(mDisconnectReplyID); 1161c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang mDisconnectReplyID.clear(); 116214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 116314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 116414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubersp<PlaylistFetcher> LiveSession::addFetcher(const char *uri) { 116514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ssize_t index = mFetcherInfos.indexOfKey(uri); 116614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 116714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (index >= 0) { 116814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return NULL; 116914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 117014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 11711d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> notify = new AMessage(kWhatFetcherNotify, this); 117214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->setString("uri", uri); 11731543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih notify->setInt32("switchGeneration", mSwitchGeneration); 117414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 117514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber FetcherInfo info; 117625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang info.mFetcher = new PlaylistFetcher( 117725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang notify, this, uri, mCurBandwidthIndex, mSubtitleGeneration); 117814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber info.mDurationUs = -1ll; 11791543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih info.mToBeRemoved = false; 1180a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang info.mToBeResumed = false; 1181964adb17885185808398507d2de88665fe193ee2Chong Zhang mFetcherLooper->registerHandler(info.mFetcher); 118214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 118314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mFetcherInfos.add(uri, info); 118414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 118514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return info.mFetcher; 1186a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 1187a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1188b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe#if 0 1189a44153c1a57202fb538659eb50706e60454d6273Andreas Huberstatic double uniformRand() { 1190a44153c1a57202fb538659eb50706e60454d6273Andreas Huber return (double)rand() / RAND_MAX; 1191a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 1192b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe#endif 1193a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 11940852843d304006e3ab333081fddda13b07193de8Robert Shihbool LiveSession::UriIsSameAsIndex(const AString &uri, int32_t i, bool newUri) { 119594e2db71cf1ce90f8a74632895e2766b24a80d7fMichal Piechowski ALOGV("[timed_id3] i %d UriIsSameAsIndex newUri %s, %s", i, 11960852843d304006e3ab333081fddda13b07193de8Robert Shih newUri ? "true" : "false", 11970852843d304006e3ab333081fddda13b07193de8Robert Shih newUri ? mStreams[i].mNewUri.c_str() : mStreams[i].mUri.c_str()); 11980852843d304006e3ab333081fddda13b07193de8Robert Shih return i >= 0 11990852843d304006e3ab333081fddda13b07193de8Robert Shih && ((!newUri && uri == mStreams[i].mUri) 12000852843d304006e3ab333081fddda13b07193de8Robert Shih || (newUri && uri == mStreams[i].mNewUri)); 12010852843d304006e3ab333081fddda13b07193de8Robert Shih} 12020852843d304006e3ab333081fddda13b07193de8Robert Shih 12030852843d304006e3ab333081fddda13b07193de8Robert Shihsp<AnotherPacketSource> LiveSession::getPacketSourceForStreamIndex( 12040852843d304006e3ab333081fddda13b07193de8Robert Shih size_t trackIndex, bool newUri) { 12050852843d304006e3ab333081fddda13b07193de8Robert Shih StreamType type = indexToType(trackIndex); 12060852843d304006e3ab333081fddda13b07193de8Robert Shih sp<AnotherPacketSource> source = NULL; 12070852843d304006e3ab333081fddda13b07193de8Robert Shih if (newUri) { 12080852843d304006e3ab333081fddda13b07193de8Robert Shih source = mPacketSources2.valueFor(type); 12090852843d304006e3ab333081fddda13b07193de8Robert Shih source->clear(); 12100852843d304006e3ab333081fddda13b07193de8Robert Shih } else { 12110852843d304006e3ab333081fddda13b07193de8Robert Shih source = mPacketSources.valueFor(type); 12120852843d304006e3ab333081fddda13b07193de8Robert Shih }; 12130852843d304006e3ab333081fddda13b07193de8Robert Shih return source; 12140852843d304006e3ab333081fddda13b07193de8Robert Shih} 12150852843d304006e3ab333081fddda13b07193de8Robert Shih 12160852843d304006e3ab333081fddda13b07193de8Robert Shihsp<AnotherPacketSource> LiveSession::getMetadataSource( 12170852843d304006e3ab333081fddda13b07193de8Robert Shih sp<AnotherPacketSource> sources[kNumSources], uint32_t streamMask, bool newUri) { 12180852843d304006e3ab333081fddda13b07193de8Robert Shih // todo: One case where the following strategy can fail is when audio and video 12190852843d304006e3ab333081fddda13b07193de8Robert Shih // are in separate playlists, both are transport streams, and the metadata 12200852843d304006e3ab333081fddda13b07193de8Robert Shih // is actually contained in the audio stream. 12210852843d304006e3ab333081fddda13b07193de8Robert Shih ALOGV("[timed_id3] getMetadataSourceForUri streamMask %x newUri %s", 12220852843d304006e3ab333081fddda13b07193de8Robert Shih streamMask, newUri ? "true" : "false"); 12230852843d304006e3ab333081fddda13b07193de8Robert Shih 12240852843d304006e3ab333081fddda13b07193de8Robert Shih if ((sources[kVideoIndex] != NULL) // video fetcher; or ... 12250852843d304006e3ab333081fddda13b07193de8Robert Shih || (!(streamMask & STREAMTYPE_VIDEO) && sources[kAudioIndex] != NULL)) { 12260852843d304006e3ab333081fddda13b07193de8Robert Shih // ... audio fetcher for audio only variant 12270852843d304006e3ab333081fddda13b07193de8Robert Shih return getPacketSourceForStreamIndex(kMetaDataIndex, newUri); 12280852843d304006e3ab333081fddda13b07193de8Robert Shih } 12290852843d304006e3ab333081fddda13b07193de8Robert Shih 12300852843d304006e3ab333081fddda13b07193de8Robert Shih return NULL; 12310852843d304006e3ab333081fddda13b07193de8Robert Shih} 12320852843d304006e3ab333081fddda13b07193de8Robert Shih 12337c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangbool LiveSession::resumeFetcher( 12347c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang const AString &uri, uint32_t streamMask, int64_t timeUs, bool newUri) { 12357c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ssize_t index = mFetcherInfos.indexOfKey(uri); 12367c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (index < 0) { 12377c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGE("did not find fetcher for uri: %s", uri.c_str()); 12387c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return false; 12397c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 12407c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 12417c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang bool resume = false; 12420852843d304006e3ab333081fddda13b07193de8Robert Shih sp<AnotherPacketSource> sources[kNumSources]; 12437c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang for (size_t i = 0; i < kMaxStreams; ++i) { 12440852843d304006e3ab333081fddda13b07193de8Robert Shih if ((streamMask & indexToType(i)) && UriIsSameAsIndex(uri, i, newUri)) { 12457c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang resume = true; 12460852843d304006e3ab333081fddda13b07193de8Robert Shih sources[i] = getPacketSourceForStreamIndex(i, newUri); 12477c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 12487c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 12497c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 12507c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (resume) { 125125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang sp<PlaylistFetcher> &fetcher = mFetcherInfos.editValueAt(index).mFetcher; 12527c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang SeekMode seekMode = newUri ? kSeekModeNextSample : kSeekModeExactPosition; 125325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 125425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("resuming fetcher-%d, timeUs=%lld, seekMode=%d", 125525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang fetcher->getFetcherID(), (long long)timeUs, seekMode); 125625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 125725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang fetcher->startAsync( 12587c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sources[kAudioIndex], 12597c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sources[kVideoIndex], 12607c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sources[kSubtitleIndex], 12610852843d304006e3ab333081fddda13b07193de8Robert Shih getMetadataSource(sources, streamMask, newUri), 12627c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang timeUs, -1, -1, seekMode); 12637c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 12647c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 12657c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return resume; 12667c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang} 12677c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 1268a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhangfloat LiveSession::getAbortThreshold( 1269a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang ssize_t currentBWIndex, ssize_t targetBWIndex) const { 1270a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang float abortThreshold = -1.0f; 1271a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (currentBWIndex > 0 && targetBWIndex < currentBWIndex) { 1272a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang /* 1273a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang If we're switching down, we need to decide whether to 1274a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1275a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1) finish last segment of high-bandwidth variant, or 1276a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 2) abort last segment of high-bandwidth variant, and fetch an 1277a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang overlapping portion from low-bandwidth variant. 1278a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1279a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang Here we try to maximize the amount of buffer left when the 1280a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang switch point is met. Given the following parameters: 1281a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1282a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang B: our current buffering level in seconds 1283a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang T: target duration in seconds 1284a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang X: sample duration in seconds remain to fetch in last segment 1285a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang bw0: bandwidth of old variant (as specified in playlist) 1286a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang bw1: bandwidth of new variant (as specified in playlist) 1287a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang bw: measured bandwidth available 1288a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1289a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang If we choose 1), when switch happens at the end of current 1290a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang segment, our buffering will be 1291a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang B + X - X * bw0 / bw 1292a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1293a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang If we choose 2), when switch happens where we aborted current 1294a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang segment, our buffering will be 1295a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang B - (T - X) * bw1 / bw 1296a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1297a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang We should only choose 1) if 1298a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang X/T < bw1 / (bw1 + bw0 - bw) 1299a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang */ 1300a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 13015ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // abort old bandwidth immediately if bandwidth is fluctuating a lot. 13025ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // our estimate could be far off, and fetching old bandwidth could 13035ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // take too long. 13045ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (!mLastBandwidthStable) { 13055ef659e010e90175eb5282d9642a02f6105189bfChong Zhang return 0.0f; 13065ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } 13075ef659e010e90175eb5282d9642a02f6105189bfChong Zhang 13087c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // Taking the measured current bandwidth at 50% face value only, 13097c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // as our bandwidth estimation is a lagging indicator. Being 13107c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // conservative on this, we prefer switching to lower bandwidth 13117c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // unless we're really confident finishing up the last segment 13127c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // of higher bandwidth will be fast. 1313a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang CHECK(mLastBandwidthBps >= 0); 1314a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang abortThreshold = 1315a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang (float)mBandwidthItems.itemAt(targetBWIndex).mBandwidth 1316a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang / ((float)mBandwidthItems.itemAt(targetBWIndex).mBandwidth 1317a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang + (float)mBandwidthItems.itemAt(currentBWIndex).mBandwidth 13187c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang - (float)mLastBandwidthBps * 0.5f); 1319a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (abortThreshold < 0.0f) { 1320a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang abortThreshold = -1.0f; // do not abort 1321a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 1322a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang ALOGV("Switching Down: bps %ld => %ld, measured %d, abort ratio %.2f", 1323a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mBandwidthItems.itemAt(currentBWIndex).mBandwidth, 1324a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mBandwidthItems.itemAt(targetBWIndex).mBandwidth, 1325a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mLastBandwidthBps, 1326a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang abortThreshold); 1327a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 1328a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang return abortThreshold; 1329a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang} 1330a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1331538b6d22a3578c0201d48f8548289aa254d81484Chong Zhangvoid LiveSession::addBandwidthMeasurement(size_t numBytes, int64_t delayUs) { 1332538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mBandwidthEstimator->addBandwidthMeasurement(numBytes, delayUs); 1333538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang} 1334538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 13355ef659e010e90175eb5282d9642a02f6105189bfChong Zhangssize_t LiveSession::getLowestValidBandwidthIndex() const { 13365ef659e010e90175eb5282d9642a02f6105189bfChong Zhang for (size_t index = 0; index < mBandwidthItems.size(); index++) { 13375ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (isBandwidthValid(mBandwidthItems[index])) { 13385ef659e010e90175eb5282d9642a02f6105189bfChong Zhang return index; 13395ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } 13405ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } 13415ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // if playlists are all blacklisted, return 0 and hope it's alive 13425ef659e010e90175eb5282d9642a02f6105189bfChong Zhang return 0; 13435ef659e010e90175eb5282d9642a02f6105189bfChong Zhang} 13445ef659e010e90175eb5282d9642a02f6105189bfChong Zhang 1345538b6d22a3578c0201d48f8548289aa254d81484Chong Zhangsize_t LiveSession::getBandwidthIndex(int32_t bandwidthBps) { 1346538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang if (mBandwidthItems.size() < 2) { 1347538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang // shouldn't be here if we only have 1 bandwidth, check 1348538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang // logic to get rid of redundant bandwidth polling 1349538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang ALOGW("getBandwidthIndex() called for single bandwidth playlist!"); 1350a44153c1a57202fb538659eb50706e60454d6273Andreas Huber return 0; 1351a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1352a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1353a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#if 1 1354a44153c1a57202fb538659eb50706e60454d6273Andreas Huber char value[PROPERTY_VALUE_MAX]; 1355673158582c9589cee1d5e4d7c79622609938b8f8Andreas Huber ssize_t index = -1; 135614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (property_get("media.httplive.bw-index", value, NULL)) { 1357a44153c1a57202fb538659eb50706e60454d6273Andreas Huber char *end; 135814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber index = strtol(value, &end, 10); 135914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(end > value && *end == '\0'); 136014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 136114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (index >= 0 && (size_t)index >= mBandwidthItems.size()) { 136214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber index = mBandwidthItems.size() - 1; 1363a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1364a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1365a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 136614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (index < 0) { 136714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber char value[PROPERTY_VALUE_MAX]; 136814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (property_get("media.httplive.max-bw", value, NULL)) { 136914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber char *end; 137014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber long maxBw = strtoul(value, &end, 10); 137114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (end > value && *end == '\0') { 137214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (maxBw > 0 && bandwidthBps > maxBw) { 137314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGV("bandwidth capped to %ld bps", maxBw); 137414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber bandwidthBps = maxBw; 137514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 137614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 137714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 1378a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 13795ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // Pick the highest bandwidth stream that's not currently blacklisted 13805ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // below or equal to estimated bandwidth. 138114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 138214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber index = mBandwidthItems.size() - 1; 13835ef659e010e90175eb5282d9642a02f6105189bfChong Zhang ssize_t lowestBandwidth = getLowestValidBandwidthIndex(); 13845ef659e010e90175eb5282d9642a02f6105189bfChong Zhang while (index > lowestBandwidth) { 1385538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang // be conservative (70%) to avoid overestimating and immediately 1386538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang // switching down again. 1387538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang size_t adjustedBandwidthBps = bandwidthBps * 7 / 10; 13885ef659e010e90175eb5282d9642a02f6105189bfChong Zhang const BandwidthItem &item = mBandwidthItems[index]; 13895ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (item.mBandwidth <= adjustedBandwidthBps 13905ef659e010e90175eb5282d9642a02f6105189bfChong Zhang && isBandwidthValid(item)) { 139100598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih break; 139200598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih } 139314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber --index; 139414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 1395a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1396a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0 1397a44153c1a57202fb538659eb50706e60454d6273Andreas Huber // Change bandwidth at random() 1398a44153c1a57202fb538659eb50706e60454d6273Andreas Huber size_t index = uniformRand() * mBandwidthItems.size(); 1399a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0 1400a44153c1a57202fb538659eb50706e60454d6273Andreas Huber // There's a 50% chance to stay on the current bandwidth and 1401a44153c1a57202fb538659eb50706e60454d6273Andreas Huber // a 50% chance to switch to the next higher bandwidth (wrapping around 1402a44153c1a57202fb538659eb50706e60454d6273Andreas Huber // to lowest) 1403a44153c1a57202fb538659eb50706e60454d6273Andreas Huber const size_t kMinIndex = 0; 1404a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1405309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih static ssize_t mCurBandwidthIndex = -1; 140614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 1407a44153c1a57202fb538659eb50706e60454d6273Andreas Huber size_t index; 1408309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (mCurBandwidthIndex < 0) { 1409a44153c1a57202fb538659eb50706e60454d6273Andreas Huber index = kMinIndex; 1410a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } else if (uniformRand() < 0.5) { 1411309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih index = (size_t)mCurBandwidthIndex; 1412a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } else { 1413309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih index = mCurBandwidthIndex + 1; 1414a44153c1a57202fb538659eb50706e60454d6273Andreas Huber if (index == mBandwidthItems.size()) { 1415a44153c1a57202fb538659eb50706e60454d6273Andreas Huber index = kMinIndex; 1416a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1417a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1418309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mCurBandwidthIndex = index; 1419a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0 1420a44153c1a57202fb538659eb50706e60454d6273Andreas Huber // Pick the highest bandwidth stream below or equal to 1.2 Mbit/sec 1421a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1422a44153c1a57202fb538659eb50706e60454d6273Andreas Huber size_t index = mBandwidthItems.size() - 1; 1423a44153c1a57202fb538659eb50706e60454d6273Andreas Huber while (index > 0 && mBandwidthItems.itemAt(index).mBandwidth > 1200000) { 1424a44153c1a57202fb538659eb50706e60454d6273Andreas Huber --index; 1425a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 142614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#elif 1 142714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber char value[PROPERTY_VALUE_MAX]; 142814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber size_t index; 142914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (property_get("media.httplive.bw-index", value, NULL)) { 143014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber char *end; 143114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber index = strtoul(value, &end, 10); 143214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(end > value && *end == '\0'); 143314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 143414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (index >= mBandwidthItems.size()) { 143514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber index = mBandwidthItems.size() - 1; 143614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 143714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else { 143814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber index = 0; 143914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 1440a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#else 1441a44153c1a57202fb538659eb50706e60454d6273Andreas Huber size_t index = mBandwidthItems.size() - 1; // Highest bandwidth stream 1442a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#endif 1443a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 144414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK_GE(index, 0); 144514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 1446a44153c1a57202fb538659eb50706e60454d6273Andreas Huber return index; 1447a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 1448a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1449d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong ZhangHLSTime LiveSession::latestMediaSegmentStartTime() const { 1450d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang HLSTime audioTime(mPacketSources.valueFor( 1451d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang STREAMTYPE_AUDIO)->getLatestDequeuedMeta()); 1452b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih 1453d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang HLSTime videoTime(mPacketSources.valueFor( 1454d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang STREAMTYPE_VIDEO)->getLatestDequeuedMeta()); 1455b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih 1456d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang return audioTime < videoTime ? videoTime : audioTime; 1457b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih} 1458b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih 1459a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnarvoid LiveSession::onSeek(const sp<AMessage> &msg) { 146014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int64_t timeUs; 1461c5de09127e9e0d5df7aa587be317e1487d793245Wei Jia int32_t mode; 146214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->findInt64("timeUs", &timeUs)); 1463c5de09127e9e0d5df7aa587be317e1487d793245Wei Jia CHECK(msg->findInt32("mode", &mode)); 1464c5de09127e9e0d5df7aa587be317e1487d793245Wei Jia // TODO: add "mode" to changeConfiguration. 1465c5de09127e9e0d5df7aa587be317e1487d793245Wei Jia changeConfiguration(timeUs/* , (MediaPlayerSeekMode)mode */); 14667e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber} 14677e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber 146814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::getDuration(int64_t *durationUs) const { 1469895651b07fec30b0f9b0d2499599a179d95c9be4Wei Jia int64_t maxDurationUs = -1ll; 147014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber for (size_t i = 0; i < mFetcherInfos.size(); ++i) { 147114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int64_t fetcherDurationUs = mFetcherInfos.valueAt(i).mDurationUs; 1472b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber 1473895651b07fec30b0f9b0d2499599a179d95c9be4Wei Jia if (fetcherDurationUs > maxDurationUs) { 147414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber maxDurationUs = fetcherDurationUs; 1475a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1476a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1477a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 147814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber *durationUs = maxDurationUs; 1479a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 148014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return OK; 148114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 14820f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber 148314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberbool LiveSession::isSeekable() const { 148414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int64_t durationUs; 148514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return getDuration(&durationUs) == OK && durationUs >= 0; 148614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 14870f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber 148814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberbool LiveSession::hasDynamicDuration() const { 148914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return false; 149014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 14910f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber 1492404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhangsize_t LiveSession::getTrackCount() const { 14939d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih if (mPlaylist == NULL) { 14949d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih return 0; 14959d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih } else { 14960852843d304006e3ab333081fddda13b07193de8Robert Shih return mPlaylist->getTrackCount() + (mHasMetadata ? 1 : 0); 14979d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih } 1498404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang} 1499404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang 1500404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhangsp<AMessage> LiveSession::getTrackInfo(size_t trackIndex) const { 15019d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih if (mPlaylist == NULL) { 15029d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih return NULL; 15039d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih } else { 15040852843d304006e3ab333081fddda13b07193de8Robert Shih if (trackIndex == mPlaylist->getTrackCount() && mHasMetadata) { 15050852843d304006e3ab333081fddda13b07193de8Robert Shih sp<AMessage> format = new AMessage(); 15060852843d304006e3ab333081fddda13b07193de8Robert Shih format->setInt32("type", MEDIA_TRACK_TYPE_METADATA); 15070852843d304006e3ab333081fddda13b07193de8Robert Shih format->setString("language", "und"); 15086f9c5e26c710dbee50e57316f1c460dda4850fa5Robert Shih format->setString("mime", MEDIA_MIMETYPE_DATA_TIMED_ID3); 15090852843d304006e3ab333081fddda13b07193de8Robert Shih return format; 15100852843d304006e3ab333081fddda13b07193de8Robert Shih } 15119d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih return mPlaylist->getTrackInfo(trackIndex); 15129d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih } 1513dcb89b3b505522efde173c105a851c412f947178Chong Zhang} 1514dcb89b3b505522efde173c105a851c412f947178Chong Zhang 1515dcb89b3b505522efde173c105a851c412f947178Chong Zhangstatus_t LiveSession::selectTrack(size_t index, bool select) { 1516b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih if (mPlaylist == NULL) { 1517b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih return INVALID_OPERATION; 1518b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih } 1519b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih 152025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("selectTrack: index=%zu, select=%d, mSubtitleGen=%d++", 152125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang index, select, mSubtitleGeneration); 152225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 1523b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih ++mSubtitleGeneration; 1524dcb89b3b505522efde173c105a851c412f947178Chong Zhang status_t err = mPlaylist->selectTrack(index, select); 1525dcb89b3b505522efde173c105a851c412f947178Chong Zhang if (err == OK) { 15261d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> msg = new AMessage(kWhatChangeConfiguration, this); 1527309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih msg->setInt32("pickTrack", select); 1528309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih msg->post(); 1529dcb89b3b505522efde173c105a851c412f947178Chong Zhang } 1530dcb89b3b505522efde173c105a851c412f947178Chong Zhang return err; 1531dcb89b3b505522efde173c105a851c412f947178Chong Zhang} 1532dcb89b3b505522efde173c105a851c412f947178Chong Zhang 153389bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shihssize_t LiveSession::getSelectedTrack(media_track_type type) const { 153489bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih if (mPlaylist == NULL) { 153589bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih return -1; 153689bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih } else { 153789bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih return mPlaylist->getSelectedTrack(type); 153889bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih } 153989bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih} 154089bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih 1541dcb89b3b505522efde173c105a851c412f947178Chong Zhangvoid LiveSession::changeConfiguration( 15427c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang int64_t timeUs, ssize_t bandwidthIndex, bool pickTrack) { 154325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("changeConfiguration: timeUs=%lld us, bwIndex=%zd, pickTrack=%d", 154425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang (long long)timeUs, bandwidthIndex, pickTrack); 154525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 15461543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih cancelBandwidthSwitch(); 15471543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 154814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(!mReconfigurationInProgress); 154914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mReconfigurationInProgress = true; 15507c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (bandwidthIndex >= 0) { 15517c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mOrigBandwidthIndex = mCurBandwidthIndex; 15527c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mCurBandwidthIndex = bandwidthIndex; 15538464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang if (mOrigBandwidthIndex != mCurBandwidthIndex) { 15548464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang ALOGI("#### Starting Bandwidth Switch: %zd => %zd", 15558464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang mOrigBandwidthIndex, mCurBandwidthIndex); 15568464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang } 15577c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 15586f51c153ea5e4187a313e47ac8bad9a1a999d4e1Colin Cross CHECK_LT((size_t)mCurBandwidthIndex, mBandwidthItems.size()); 15597c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang const BandwidthItem &item = mBandwidthItems.itemAt(mCurBandwidthIndex); 1560a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 15611543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih uint32_t streamMask = 0; // streams that should be fetched by the new fetcher 15621543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih uint32_t resumeMask = 0; // streams that should be fetched by the original fetcher 1563a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 15648ca002eedc747dd854b61cbe364b52c06869273fRobert Shih AString URIs[kMaxStreams]; 15658ca002eedc747dd854b61cbe364b52c06869273fRobert Shih for (size_t i = 0; i < kMaxStreams; ++i) { 15668ca002eedc747dd854b61cbe364b52c06869273fRobert Shih if (mPlaylist->getTypeURI(item.mPlaylistIndex, mStreams[i].mType, &URIs[i])) { 15678ca002eedc747dd854b61cbe364b52c06869273fRobert Shih streamMask |= indexToType(i); 15688ca002eedc747dd854b61cbe364b52c06869273fRobert Shih } 156914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 1570aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber 157114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // Step 1, stop and discard fetchers that are no longer needed. 157214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // Pause those that we'll reuse. 157314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber for (size_t i = 0; i < mFetcherInfos.size(); ++i) { 15747c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // skip fetchers that are marked mToBeRemoved, 15757c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // these are done and can't be reused 15767c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (mFetcherInfos[i].mToBeRemoved) { 15777c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang continue; 15787c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 15797c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 158014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber const AString &uri = mFetcherInfos.keyAt(i); 1581d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang sp<PlaylistFetcher> &fetcher = mFetcherInfos.editValueAt(i).mFetcher; 1582aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber 1583d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang bool discardFetcher = true, delayRemoval = false; 1584c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang for (size_t j = 0; j < kMaxStreams; ++j) { 1585c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang StreamType type = indexToType(j); 1586c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang if ((streamMask & type) && uri == URIs[j]) { 1587c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang resumeMask |= type; 1588c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang streamMask &= ~type; 1589c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang discardFetcher = false; 15906801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber } 159114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 1592d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // Delay fetcher removal if not picking tracks, AND old fetcher 1593d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // has stream mask that overlaps new variant. (Okay to discard 1594d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // old fetcher now, if completely no overlap.) 1595d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (discardFetcher && timeUs < 0ll && !pickTrack 1596d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang && (fetcher->getStreamTypeMask() & streamMask)) { 1597d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang discardFetcher = false; 1598d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang delayRemoval = true; 1599d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang } 1600a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 160114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (discardFetcher) { 160225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("discarding fetcher-%d", fetcher->getFetcherID()); 1603d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang fetcher->stopAsync(); 16046801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber } else { 16058a048338d9291b2db1b3a325fff58cb1aa69f04dChong Zhang float threshold = 0.0f; // default to pause after current block (47Kbytes) 16065abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang bool disconnect = false; 1607a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (timeUs >= 0ll) { 1608a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // seeking, no need to finish fetching 16095abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang disconnect = true; 1610d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang } else if (delayRemoval) { 1611a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // adapting, abort if remaining of current segment is over threshold 1612a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang threshold = getAbortThreshold( 16137c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mOrigBandwidthIndex, mCurBandwidthIndex); 1614a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 1615a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 161625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("pausing fetcher-%d, threshold=%.2f", 161725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang fetcher->getFetcherID(), threshold); 16185abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang fetcher->pauseAsync(threshold, disconnect); 16196801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber } 1620a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1621a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 16221543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih sp<AMessage> msg; 16231543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih if (timeUs < 0ll) { 1624309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih // skip onChangeConfiguration2 (decoder destruction) if not seeking. 16251d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar msg = new AMessage(kWhatChangeConfiguration3, this); 16261543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } else { 16271d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar msg = new AMessage(kWhatChangeConfiguration2, this); 16281543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 162914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber msg->setInt32("streamMask", streamMask); 16301543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih msg->setInt32("resumeMask", resumeMask); 1631309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih msg->setInt32("pickTrack", pickTrack); 163214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber msg->setInt64("timeUs", timeUs); 16338ca002eedc747dd854b61cbe364b52c06869273fRobert Shih for (size_t i = 0; i < kMaxStreams; ++i) { 1634309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if ((streamMask | resumeMask) & indexToType(i)) { 16358ca002eedc747dd854b61cbe364b52c06869273fRobert Shih msg->setString(mStreams[i].uriKey().c_str(), URIs[i].c_str()); 16368ca002eedc747dd854b61cbe364b52c06869273fRobert Shih } 16376e6b1cae2bac1b78205cefab8e4e9e9538982965Andreas Huber } 1638a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 163914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // Every time a fetcher acknowledges the stopAsync or pauseAsync request 164014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // we'll decrement mContinuationCounter, once it reaches zero, i.e. all 164114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // fetchers have completed their asynchronous operation, we'll post 164214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // mContinuation, which then is handled below in onChangeConfiguration2. 164314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mContinuationCounter = mFetcherInfos.size(); 164414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mContinuation = msg; 164588b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber 164614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (mContinuationCounter == 0) { 164714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber msg->post(); 164888b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber } 164914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 1650a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1651dcb89b3b505522efde173c105a851c412f947178Chong Zhangvoid LiveSession::onChangeConfiguration(const sp<AMessage> &msg) { 165225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("onChangeConfiguration"); 165325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 1654dcb89b3b505522efde173c105a851c412f947178Chong Zhang if (!mReconfigurationInProgress) { 16557c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang int32_t pickTrack = 0; 1656309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih msg->findInt32("pickTrack", &pickTrack); 16577c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang changeConfiguration(-1ll /* timeUs */, -1, pickTrack); 1658dcb89b3b505522efde173c105a851c412f947178Chong Zhang } else { 1659dcb89b3b505522efde173c105a851c412f947178Chong Zhang msg->post(1000000ll); // retry in 1 sec 1660dcb89b3b505522efde173c105a851c412f947178Chong Zhang } 1661dcb89b3b505522efde173c105a851c412f947178Chong Zhang} 1662dcb89b3b505522efde173c105a851c412f947178Chong Zhang 166314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::onChangeConfiguration2(const sp<AMessage> &msg) { 166425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("onChangeConfiguration2"); 166525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 166614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mContinuation.clear(); 1667bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber 166814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // All fetchers are either suspended or have been removed now. 1669bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber 1670964adb17885185808398507d2de88665fe193ee2Chong Zhang // If we're seeking, clear all packet sources before we report 1671964adb17885185808398507d2de88665fe193ee2Chong Zhang // seek complete, to prevent decoder from pulling stale data. 1672964adb17885185808398507d2de88665fe193ee2Chong Zhang int64_t timeUs; 1673964adb17885185808398507d2de88665fe193ee2Chong Zhang CHECK(msg->findInt64("timeUs", &timeUs)); 1674964adb17885185808398507d2de88665fe193ee2Chong Zhang 1675964adb17885185808398507d2de88665fe193ee2Chong Zhang if (timeUs >= 0) { 1676964adb17885185808398507d2de88665fe193ee2Chong Zhang mLastSeekTimeUs = timeUs; 16778464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang mLastDequeuedTimeUs = timeUs; 1678964adb17885185808398507d2de88665fe193ee2Chong Zhang 1679964adb17885185808398507d2de88665fe193ee2Chong Zhang for (size_t i = 0; i < mPacketSources.size(); i++) { 16807f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih sp<AnotherPacketSource> packetSource = mPacketSources.editValueAt(i); 16817f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih sp<MetaData> format = packetSource->getFormat(); 16827f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih packetSource->clear(); 16837f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih // Set a tentative format here such that HTTPLiveSource will always have 16847f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih // a format available when NuPlayer queries. Without an available video 16857f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih // format when setting a surface NuPlayer might disable video decoding 16867f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih // altogether. The tentative format will be overwritten by the 16877f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih // authoritative (and possibly same) format once content from the new 16887f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih // position is dequeued. 16897f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih packetSource->setFormat(format); 1690964adb17885185808398507d2de88665fe193ee2Chong Zhang } 1691964adb17885185808398507d2de88665fe193ee2Chong Zhang 16927c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang for (size_t i = 0; i < kMaxStreams; ++i) { 169381636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang mStreams[i].reset(); 16947c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 16957c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 1696964adb17885185808398507d2de88665fe193ee2Chong Zhang mDiscontinuityOffsetTimesUs.clear(); 1697964adb17885185808398507d2de88665fe193ee2Chong Zhang mDiscontinuityAbsStartTimesUs.clear(); 1698964adb17885185808398507d2de88665fe193ee2Chong Zhang 1699c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang if (mSeekReplyID != NULL) { 1700964adb17885185808398507d2de88665fe193ee2Chong Zhang CHECK(mSeekReply != NULL); 1701964adb17885185808398507d2de88665fe193ee2Chong Zhang mSeekReply->setInt32("err", OK); 1702964adb17885185808398507d2de88665fe193ee2Chong Zhang mSeekReply->postReply(mSeekReplyID); 1703c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang mSeekReplyID.clear(); 1704964adb17885185808398507d2de88665fe193ee2Chong Zhang mSeekReply.clear(); 1705964adb17885185808398507d2de88665fe193ee2Chong Zhang } 17067c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 17077c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // restart buffer polling after seek becauese previous 17087c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // buffering position is no longer valid. 17097c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang restartPollBuffering(); 1710964adb17885185808398507d2de88665fe193ee2Chong Zhang } 1711964adb17885185808398507d2de88665fe193ee2Chong Zhang 1712309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih uint32_t streamMask, resumeMask; 171314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->findInt32("streamMask", (int32_t *)&streamMask)); 1714309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih CHECK(msg->findInt32("resumeMask", (int32_t *)&resumeMask)); 1715309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 1716309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih streamMask |= resumeMask; 1717bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber 17188ca002eedc747dd854b61cbe364b52c06869273fRobert Shih AString URIs[kMaxStreams]; 17198ca002eedc747dd854b61cbe364b52c06869273fRobert Shih for (size_t i = 0; i < kMaxStreams; ++i) { 17208ca002eedc747dd854b61cbe364b52c06869273fRobert Shih if (streamMask & indexToType(i)) { 17218ca002eedc747dd854b61cbe364b52c06869273fRobert Shih const AString &uriKey = mStreams[i].uriKey(); 17228ca002eedc747dd854b61cbe364b52c06869273fRobert Shih CHECK(msg->findString(uriKey.c_str(), &URIs[i])); 17238ca002eedc747dd854b61cbe364b52c06869273fRobert Shih ALOGV("%s = '%s'", uriKey.c_str(), URIs[i].c_str()); 17248ca002eedc747dd854b61cbe364b52c06869273fRobert Shih } 172522fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber } 17263831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber 172714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber uint32_t changedMask = 0; 17288ca002eedc747dd854b61cbe364b52c06869273fRobert Shih for (size_t i = 0; i < kMaxStreams && i != kSubtitleIndex; ++i) { 1729c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // stream URI could change even if onChangeConfiguration2 is only 1730c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // used for seek. Seek could happen during a bw switch, in this 1731c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // case bw switch will be cancelled, but the seekTo position will 1732c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // fetch from the new URI. 1733c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang if ((mStreamMask & streamMask & indexToType(i)) 1734c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang && !mStreams[i].mUri.empty() 1735c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang && !(URIs[i] == mStreams[i].mUri)) { 17364604458dfe57b0e91a464aefafea50ae7b9876c1Chong Zhang ALOGV("stream %zu changed: oldURI %s, newURI %s", i, 1737c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang mStreams[i].mUri.c_str(), URIs[i].c_str()); 1738c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang sp<AnotherPacketSource> source = mPacketSources.valueFor(indexToType(i)); 17398464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang if (source->getLatestDequeuedMeta() != NULL) { 17408464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang source->queueDiscontinuity( 17418464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang ATSParser::DISCONTINUITY_FORMATCHANGE, NULL, true); 17428464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang } 1743c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang } 1744c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // Determine which decoders to shutdown on the player side, 1745c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // a decoder has to be shutdown if its streamtype was active 1746c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // before but now longer isn't. 1747c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang if ((mStreamMask & ~streamMask & indexToType(i))) { 17488ca002eedc747dd854b61cbe364b52c06869273fRobert Shih changedMask |= indexToType(i); 17498ca002eedc747dd854b61cbe364b52c06869273fRobert Shih } 1750b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber } 1751b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber 175214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (changedMask == 0) { 175314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // If nothing changed as far as the audio/video decoders 175414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // are concerned we can proceed. 175514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber onChangeConfiguration3(msg); 175614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return; 175714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 175843c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber 175914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // Something changed, inform the player which will shutdown the 176014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // corresponding decoders and will post the reply once that's done. 176114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // Handling the reply will continue executing below in 176214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // onChangeConfiguration3. 176314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AMessage> notify = mNotify->dup(); 176414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->setInt32("what", kWhatStreamsChanged); 176514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->setInt32("changedMask", changedMask); 176620f725ebcef13ded1b4b85c61c8a4b37cd030656Andreas Huber 176714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber msg->setWhat(kWhatChangeConfiguration3); 17681d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar msg->setTarget(this); 1769b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber 177014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->setMessage("reply", msg); 177114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->post(); 177214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 1773b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber 177414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::onChangeConfiguration3(const sp<AMessage> &msg) { 17751543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih mContinuation.clear(); 177614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // All remaining fetchers are still suspended, the player has shutdown 177714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // any decoders that needed it. 1778b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber 17791543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih uint32_t streamMask, resumeMask; 178014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->findInt32("streamMask", (int32_t *)&streamMask)); 17811543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih CHECK(msg->findInt32("resumeMask", (int32_t *)&resumeMask)); 1782a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1783d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang mNewStreamMask = streamMask | resumeMask; 1784d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang 178514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int64_t timeUs; 1786309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih int32_t pickTrack; 17871543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih bool switching = false; 178814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->findInt64("timeUs", &timeUs)); 1789309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih CHECK(msg->findInt32("pickTrack", &pickTrack)); 1790a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 179114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (timeUs < 0ll) { 1792309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (!pickTrack) { 1793d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // mSwapMask contains streams that are in both old and new variant, 1794d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // (in mNewStreamMask & mStreamMask) but with different URIs 1795d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // (not in resumeMask). 1796d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // For example, old variant has video and audio in two separate 1797d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // URIs, and new variant has only audio with unchanged URI. mSwapMask 1798d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // should be 0 as there is nothing to swap. We only need to stop video, 1799d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // and resume audio. 1800d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang mSwapMask = mNewStreamMask & mStreamMask & ~resumeMask; 1801d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang switching = (mSwapMask != 0); 1802309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 1803309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mRealTimeBaseUs = ALooper::GetNowUs() - mLastDequeuedTimeUs; 1804309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } else { 1805309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mRealTimeBaseUs = ALooper::GetNowUs() - timeUs; 180614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 1807a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 180825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("onChangeConfiguration3: timeUs=%lld, switching=%d, pickTrack=%d, " 180925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang "mStreamMask=0x%x, mNewStreamMask=0x%x, mSwapMask=0x%x", 181025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang (long long)timeUs, switching, pickTrack, 181125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang mStreamMask, mNewStreamMask, mSwapMask); 181225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 1813f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih for (size_t i = 0; i < kMaxStreams; ++i) { 1814f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih if (streamMask & indexToType(i)) { 1815f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih if (switching) { 1816f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih CHECK(msg->findString(mStreams[i].uriKey().c_str(), &mStreams[i].mNewUri)); 1817f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } else { 1818f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih CHECK(msg->findString(mStreams[i].uriKey().c_str(), &mStreams[i].mUri)); 1819f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 1820f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 1821f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 1822f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih 18231543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih // Of all existing fetchers: 18241543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih // * Resume fetchers that are still needed and assign them original packet sources. 18251543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih // * Mark otherwise unneeded fetchers for removal. 18261543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih ALOGV("resuming fetchers for mask 0x%08x", resumeMask); 182714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber for (size_t i = 0; i < mFetcherInfos.size(); ++i) { 182814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber const AString &uri = mFetcherInfos.keyAt(i); 18297c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (!resumeFetcher(uri, resumeMask, timeUs)) { 183025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("marking fetcher-%d to be removed", 183125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang mFetcherInfos[i].mFetcher->getFetcherID()); 183225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 18337c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mFetcherInfos.editValueAt(i).mToBeRemoved = true; 18341543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 1835a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1836a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 183714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // streamMask now only contains the types that need a new fetcher created. 183814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (streamMask != 0) { 183914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGV("creating new fetchers for mask 0x%08x", streamMask); 1840a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1841a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 18421543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih // Find out when the original fetchers have buffered up to and start the new fetchers 18431543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih // at a later timestamp. 18448ca002eedc747dd854b61cbe364b52c06869273fRobert Shih for (size_t i = 0; i < kMaxStreams; i++) { 18458ca002eedc747dd854b61cbe364b52c06869273fRobert Shih if (!(indexToType(i) & streamMask)) { 18468ca002eedc747dd854b61cbe364b52c06869273fRobert Shih continue; 18478ca002eedc747dd854b61cbe364b52c06869273fRobert Shih } 18481156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 184914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber AString uri; 1850f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih uri = switching ? mStreams[i].mNewUri : mStreams[i].mUri; 18519b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber 185214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<PlaylistFetcher> fetcher = addFetcher(uri.c_str()); 185314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(fetcher != NULL); 1854a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1855d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang HLSTime startTime; 1856a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang SeekMode seekMode = kSeekModeExactPosition; 18570852843d304006e3ab333081fddda13b07193de8Robert Shih sp<AnotherPacketSource> sources[kNumSources]; 18581543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 1859d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (i == kSubtitleIndex || (!pickTrack && !switching)) { 1860d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang startTime = latestMediaSegmentStartTime(); 1861b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih } 1862b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih 18638ca002eedc747dd854b61cbe364b52c06869273fRobert Shih // TRICKY: looping from i as earlier streams are already removed from streamMask 18648ca002eedc747dd854b61cbe364b52c06869273fRobert Shih for (size_t j = i; j < kMaxStreams; ++j) { 1865f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih const AString &streamUri = switching ? mStreams[j].mNewUri : mStreams[j].mUri; 1866f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih if ((streamMask & indexToType(j)) && uri == streamUri) { 18678ca002eedc747dd854b61cbe364b52c06869273fRobert Shih sources[j] = mPacketSources.valueFor(indexToType(j)); 18681543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 1869309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (timeUs >= 0) { 1870d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang startTime.mTimeUs = timeUs; 18711543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } else { 1872309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih int32_t type; 1873309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih sp<AMessage> meta; 1874d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (!switching) { 1875d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // selecting, or adapting but no swap required 1876309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih meta = sources[j]->getLatestDequeuedMeta(); 1877309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } else { 1878d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // adapting and swap required 1879309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih meta = sources[j]->getLatestEnqueuedMeta(); 18807c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (meta != NULL && mCurBandwidthIndex > mOrigBandwidthIndex) { 18817c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // switching up 18827c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang meta = sources[j]->getMetaAfterLastDequeued(mUpSwitchMargin); 18837c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 1884309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 18851543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 18860852843d304006e3ab333081fddda13b07193de8Robert Shih if ((j == kAudioIndex || j == kVideoIndex) 18870852843d304006e3ab333081fddda13b07193de8Robert Shih && meta != NULL && !meta->findInt32("discontinuity", &type)) { 1888d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang HLSTime tmpTime(meta); 1889d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (startTime < tmpTime) { 1890d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang startTime = tmpTime; 18911543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 18921543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 18931543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 1894d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (!switching) { 1895d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // selecting, or adapting but no swap required 1896309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih sources[j]->clear(); 1897309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (j == kSubtitleIndex) { 1898309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih break; 1899309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 1900964adb17885185808398507d2de88665fe193ee2Chong Zhang 19014604458dfe57b0e91a464aefafea50ae7b9876c1Chong Zhang ALOGV("stream[%zu]: queue format change", j); 1902964adb17885185808398507d2de88665fe193ee2Chong Zhang sources[j]->queueDiscontinuity( 1903a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang ATSParser::DISCONTINUITY_FORMAT_ONLY, NULL, true); 1904309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } else { 1905d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // switching, queue discontinuities after resume 1906309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih sources[j] = mPacketSources2.valueFor(indexToType(j)); 1907309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih sources[j]->clear(); 1908a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // the new fetcher might be providing streams that used to be 1909a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // provided by two different fetchers, if one of the fetcher 1910a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // paused in the middle while the other somehow paused in next 1911a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // seg, we have to start from next seg. 1912a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (seekMode < mStreams[j].mSeekMode) { 1913a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang seekMode = mStreams[j].mSeekMode; 1914309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 19151543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 19161543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 1917a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 19188ca002eedc747dd854b61cbe364b52c06869273fRobert Shih streamMask &= ~indexToType(j); 19198ca002eedc747dd854b61cbe364b52c06869273fRobert Shih } 1920a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 192114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 192225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("[fetcher-%d] startAsync: startTimeUs %lld mLastSeekTimeUs %lld " 192325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang "segmentStartTimeUs %lld seekMode %d", 192425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang fetcher->getFetcherID(), 192525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang (long long)startTime.mTimeUs, 192625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang (long long)mLastSeekTimeUs, 1927978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang (long long)startTime.getSegmentTimeUs(), 192825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang seekMode); 192925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 1930d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // Set the target segment start time to the middle point of the 1931d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // segment where the last sample was. 1932d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // This gives a better guess if segments of the two variants are not 1933d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // perfectly aligned. (If the corresponding segment in new variant 1934d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // starts slightly later than that in the old variant, we still want 1935d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // to pick that segment, not the one before) 19368ca002eedc747dd854b61cbe364b52c06869273fRobert Shih fetcher->startAsync( 19378ca002eedc747dd854b61cbe364b52c06869273fRobert Shih sources[kAudioIndex], 19388ca002eedc747dd854b61cbe364b52c06869273fRobert Shih sources[kVideoIndex], 19398ca002eedc747dd854b61cbe364b52c06869273fRobert Shih sources[kSubtitleIndex], 19400852843d304006e3ab333081fddda13b07193de8Robert Shih getMetadataSource(sources, mNewStreamMask, switching), 1941d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang startTime.mTimeUs < 0 ? mLastSeekTimeUs : startTime.mTimeUs, 1942978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang startTime.getSegmentTimeUs(), 1943d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang startTime.mSeq, 1944a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang seekMode); 1945a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1946a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 194714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // All fetchers have now been started, the configuration change 194814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // has completed. 1949a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 195014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mReconfigurationInProgress = false; 19511543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih if (switching) { 19521543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih mSwitchInProgress = true; 19531543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } else { 19541543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih mStreamMask = mNewStreamMask; 19558464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang if (mOrigBandwidthIndex != mCurBandwidthIndex) { 19568464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang ALOGV("#### Finished Bandwidth Switch Early: %zd => %zd", 19578464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang mOrigBandwidthIndex, mCurBandwidthIndex); 19588464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang mOrigBandwidthIndex = mCurBandwidthIndex; 19598464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang } 19601543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 1961a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 196225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("onChangeConfiguration3: mSwitchInProgress %d, mStreamMask 0x%x", 196325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang mSwitchInProgress, mStreamMask); 196425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 1965c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang if (mDisconnectReplyID != NULL) { 196614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber finishDisconnect(); 1967a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 196814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 1969a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1970a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhangvoid LiveSession::swapPacketSource(StreamType stream) { 197125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("[%s] swapPacketSource", getNameForStream(stream)); 1972a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1973a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // transfer packets from source2 to source 1974a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang sp<AnotherPacketSource> &aps = mPacketSources.editValueFor(stream); 1975a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang sp<AnotherPacketSource> &aps2 = mPacketSources2.editValueFor(stream); 1976a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1977a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // queue discontinuity in mPacketSource 1978a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang aps->queueDiscontinuity(ATSParser::DISCONTINUITY_FORMAT_ONLY, NULL, false); 1979a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1980a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // queue packets in mPacketSource2 to mPacketSource 1981a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang status_t finalResult = OK; 1982a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang sp<ABuffer> accessUnit; 1983a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang while (aps2->hasBufferAvailable(&finalResult) && finalResult == OK && 1984a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang OK == aps2->dequeueAccessUnit(&accessUnit)) { 1985a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang aps->queueAccessUnit(accessUnit); 1986a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 1987a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang aps2->clear(); 1988a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang} 1989a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 19907c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::tryToFinishBandwidthSwitch(const AString &oldUri) { 1991a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (!mSwitchInProgress) { 1992a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang return; 1993a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 1994a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 19957c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ssize_t index = mFetcherInfos.indexOfKey(oldUri); 1996a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (index < 0 || !mFetcherInfos[index].mToBeRemoved) { 19971543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih return; 19981543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 19991543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 2000a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // Swap packet source of streams provided by old variant 2001a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang for (size_t idx = 0; idx < kMaxStreams; idx++) { 20027c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang StreamType stream = indexToType(idx); 20037c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if ((mSwapMask & stream) && (oldUri == mStreams[idx].mUri)) { 2004a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang swapPacketSource(stream); 2005a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 2006a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if ((mNewStreamMask & stream) && mStreams[idx].mNewUri.empty()) { 2007a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang ALOGW("swapping stream type %d %s to empty stream", 2008a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang stream, mStreams[idx].mUri.c_str()); 2009a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 2010a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mStreams[idx].mUri = mStreams[idx].mNewUri; 2011a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mStreams[idx].mNewUri.clear(); 2012a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 2013a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mSwapMask &= ~stream; 2014a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 2015f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 2016f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih 20177c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mFetcherInfos.editValueAt(index).mFetcher->stopAsync(false /* clear */); 2018a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 201925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("tryToFinishBandwidthSwitch: mSwapMask=0x%x", mSwapMask); 2020309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (mSwapMask != 0) { 20211543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih return; 20221543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 20231543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 20241543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih // Check if new variant contains extra streams. 20251543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih uint32_t extraStreams = mNewStreamMask & (~mStreamMask); 20261543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih while (extraStreams) { 2027a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang StreamType stream = (StreamType) (extraStreams & ~(extraStreams - 1)); 2028a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang extraStreams &= ~stream; 2029a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 2030a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang swapPacketSource(stream); 2031f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih 2032a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang ssize_t idx = typeToIndex(stream); 2033f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih CHECK(idx >= 0); 2034f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih if (mStreams[idx].mNewUri.empty()) { 2035f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih ALOGW("swapping extra stream type %d %s to empty stream", 2036a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang stream, mStreams[idx].mUri.c_str()); 2037f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 2038f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih mStreams[idx].mUri = mStreams[idx].mNewUri; 2039f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih mStreams[idx].mNewUri.clear(); 20401543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 20411543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 2042a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // Restart new fetcher (it was paused after the first 47k block) 2043a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // and let it fetch into mPacketSources (not mPacketSources2) 2044a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang for (size_t i = 0; i < mFetcherInfos.size(); ++i) { 2045a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang FetcherInfo &info = mFetcherInfos.editValueAt(i); 2046a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (info.mToBeResumed) { 20477c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang resumeFetcher(mFetcherInfos.keyAt(i), mNewStreamMask); 2048a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang info.mToBeResumed = false; 2049a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 2050a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 2051a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 20527c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGI("#### Finished Bandwidth Switch: %zd => %zd", 20537c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mOrigBandwidthIndex, mCurBandwidthIndex); 20547c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 2055a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mStreamMask = mNewStreamMask; 2056a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mSwitchInProgress = false; 20577c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mOrigBandwidthIndex = mCurBandwidthIndex; 2058a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 20597c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang restartPollBuffering(); 20601543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih} 20611543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 2062964adb17885185808398507d2de88665fe193ee2Chong Zhangvoid LiveSession::schedulePollBuffering() { 2063964adb17885185808398507d2de88665fe193ee2Chong Zhang sp<AMessage> msg = new AMessage(kWhatPollBuffering, this); 2064964adb17885185808398507d2de88665fe193ee2Chong Zhang msg->setInt32("generation", mPollBufferingGeneration); 2065964adb17885185808398507d2de88665fe193ee2Chong Zhang msg->post(1000000ll); 2066964adb17885185808398507d2de88665fe193ee2Chong Zhang} 2067678bcdc852dd8f801f5c46fdc85db587b721d83dApurupa Pattapu 2068964adb17885185808398507d2de88665fe193ee2Chong Zhangvoid LiveSession::cancelPollBuffering() { 2069964adb17885185808398507d2de88665fe193ee2Chong Zhang ++mPollBufferingGeneration; 20707c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mPrevBufferPercentage = -1; 20717c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang} 20727c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 20737c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::restartPollBuffering() { 20747c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang cancelPollBuffering(); 20757c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang onPollBuffering(); 2076964adb17885185808398507d2de88665fe193ee2Chong Zhang} 20770ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih 2078964adb17885185808398507d2de88665fe193ee2Chong Zhangvoid LiveSession::onPollBuffering() { 2079964adb17885185808398507d2de88665fe193ee2Chong Zhang ALOGV("onPollBuffering: mSwitchInProgress %d, mReconfigurationInProgress %d, " 2080a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang "mInPreparationPhase %d, mCurBandwidthIndex %zd, mStreamMask 0x%x", 2081964adb17885185808398507d2de88665fe193ee2Chong Zhang mSwitchInProgress, mReconfigurationInProgress, 2082538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mInPreparationPhase, mCurBandwidthIndex, mStreamMask); 20830ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih 20847c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang bool underflow, ready, down, up; 20857c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (checkBuffering(underflow, ready, down, up)) { 20868464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang if (mInPreparationPhase) { 20878464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang // Allow down switch even if we're still preparing. 20888464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang // 20898464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang // Some streams have a high bandwidth index as default, 20908464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang // when bandwidth is low, it takes a long time to buffer 20918464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang // to ready mark, then it immediately pauses after start 20928464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang // as we have to do a down switch. It's better experience 20938464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang // to restart from a lower index, if we detect low bw. 20948464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang if (!switchBandwidthIfNeeded(false /* up */, down) && ready) { 20958464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang postPrepared(OK); 20968464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang } 20970ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih } 20980ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih 2099538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang if (!mInPreparationPhase) { 21007c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (ready) { 21017c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang stopBufferingIfNecessary(); 21027c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } else if (underflow) { 21037c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang startBufferingIfNecessary(); 21047c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 21057c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang switchBandwidthIfNeeded(up, down); 21068464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang } 21070ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih } 21080ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih 2109964adb17885185808398507d2de88665fe193ee2Chong Zhang schedulePollBuffering(); 21100ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih} 21110ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih 21127c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::cancelBandwidthSwitch(bool resume) { 21137c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGV("cancelBandwidthSwitch: mSwitchGen(%d)++, orig %zd, cur %zd", 21147c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mSwitchGeneration, mOrigBandwidthIndex, mCurBandwidthIndex); 21157c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (!mSwitchInProgress) { 21167c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return; 21177c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 2118f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih 2119f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih for (size_t i = 0; i < mFetcherInfos.size(); ++i) { 2120f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih FetcherInfo& info = mFetcherInfos.editValueAt(i); 2121f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih if (info.mToBeRemoved) { 2122f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih info.mToBeRemoved = false; 21237c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (resume) { 21247c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang resumeFetcher(mFetcherInfos.keyAt(i), mSwapMask); 21257c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 2126f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 2127f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 2128f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih 2129f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih for (size_t i = 0; i < kMaxStreams; ++i) { 21307c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang AString newUri = mStreams[i].mNewUri; 21317c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (!newUri.empty()) { 21327c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // clear all mNewUri matching this newUri 21337c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang for (size_t j = i; j < kMaxStreams; ++j) { 21347c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (mStreams[j].mNewUri == newUri) { 21357c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mStreams[j].mNewUri.clear(); 21367c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 21377c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 21387c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGV("stopping newUri = %s", newUri.c_str()); 21397c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ssize_t index = mFetcherInfos.indexOfKey(newUri); 21407c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (index < 0) { 21417c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGE("did not find fetcher for newUri: %s", newUri.c_str()); 2142f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih continue; 2143f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 21447c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang FetcherInfo &info = mFetcherInfos.editValueAt(index); 21457c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang info.mToBeRemoved = true; 2146f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih info.mFetcher->stopAsync(); 2147f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 2148f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 21497c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 21507c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGI("#### Canceled Bandwidth Switch: %zd => %zd", 215125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang mOrigBandwidthIndex, mCurBandwidthIndex); 21527c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 21537c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mSwitchGeneration++; 21547c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mSwitchInProgress = false; 21557c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mCurBandwidthIndex = mOrigBandwidthIndex; 21567c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mSwapMask = 0; 21571543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih} 21581543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 21597c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangbool LiveSession::checkBuffering( 21607c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang bool &underflow, bool &ready, bool &down, bool &up) { 21617c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang underflow = ready = down = up = false; 2162964adb17885185808398507d2de88665fe193ee2Chong Zhang 21637c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (mReconfigurationInProgress) { 2164964adb17885185808398507d2de88665fe193ee2Chong Zhang ALOGV("Switch/Reconfig in progress, defer buffer polling"); 21651543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih return false; 21661543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 21671543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 21687c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang size_t activeCount, underflowCount, readyCount, downCount, upCount; 21697c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang activeCount = underflowCount = readyCount = downCount = upCount =0; 21707c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang int32_t minBufferPercent = -1; 21717c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang int64_t durationUs; 21727c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (getDuration(&durationUs) != OK) { 21737c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang durationUs = -1; 21747c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 2175964adb17885185808398507d2de88665fe193ee2Chong Zhang for (size_t i = 0; i < mPacketSources.size(); ++i) { 2176964adb17885185808398507d2de88665fe193ee2Chong Zhang // we don't check subtitles for buffering level 2177964adb17885185808398507d2de88665fe193ee2Chong Zhang if (!(mStreamMask & mPacketSources.keyAt(i) 2178964adb17885185808398507d2de88665fe193ee2Chong Zhang & (STREAMTYPE_AUDIO | STREAMTYPE_VIDEO))) { 2179964adb17885185808398507d2de88665fe193ee2Chong Zhang continue; 2180964adb17885185808398507d2de88665fe193ee2Chong Zhang } 2181964adb17885185808398507d2de88665fe193ee2Chong Zhang // ignore streams that never had any packet queued. 2182964adb17885185808398507d2de88665fe193ee2Chong Zhang // (it's possible that the variant only has audio or video) 2183964adb17885185808398507d2de88665fe193ee2Chong Zhang sp<AMessage> meta = mPacketSources[i]->getLatestEnqueuedMeta(); 2184964adb17885185808398507d2de88665fe193ee2Chong Zhang if (meta == NULL) { 2185964adb17885185808398507d2de88665fe193ee2Chong Zhang continue; 2186964adb17885185808398507d2de88665fe193ee2Chong Zhang } 2187964adb17885185808398507d2de88665fe193ee2Chong Zhang 21880dd229bb306df68b88e7419b3cc11fc6175be1daRobert Shih status_t finalResult; 2189964adb17885185808398507d2de88665fe193ee2Chong Zhang int64_t bufferedDurationUs = 21900dd229bb306df68b88e7419b3cc11fc6175be1daRobert Shih mPacketSources[i]->getBufferedDurationUs(&finalResult); 219125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("[%s] buffered %lld us", 219225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang getNameForStream(mPacketSources.keyAt(i)), 219325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang (long long)bufferedDurationUs); 21947c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (durationUs >= 0) { 21957c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang int32_t percent; 21967c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (mPacketSources[i]->isFinished(0 /* duration */)) { 21977c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang percent = 100; 21987c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } else { 21998464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang percent = (int32_t)(100.0 * 22008464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang (mLastDequeuedTimeUs + bufferedDurationUs) / durationUs); 22017c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 22027c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (minBufferPercent < 0 || percent < minBufferPercent) { 22037c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang minBufferPercent = percent; 22047c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 2205964adb17885185808398507d2de88665fe193ee2Chong Zhang } 22067c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 22077c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ++activeCount; 220848fa06d1e80a872c7495804979256e021e566ae0Wei Jia int64_t readyMarkUs = 220948fa06d1e80a872c7495804979256e021e566ae0Wei Jia (mInPreparationPhase ? 22109bb3803a80a680ea7a3bc11e07b8a89ccddee003Wei Jia mBufferingSettings.mInitialMarkMs : 22119bb3803a80a680ea7a3bc11e07b8a89ccddee003Wei Jia mBufferingSettings.mResumePlaybackMarkMs) * 1000ll; 221248fa06d1e80a872c7495804979256e021e566ae0Wei Jia if (bufferedDurationUs > readyMarkUs 22137c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang || mPacketSources[i]->isFinished(0)) { 22147c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ++readyCount; 22157c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 22167c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (!mPacketSources[i]->isFinished(0)) { 22179bb3803a80a680ea7a3bc11e07b8a89ccddee003Wei Jia if (bufferedDurationUs < kUnderflowMarkMs * 1000ll) { 22187c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ++underflowCount; 22197c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 22207c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (bufferedDurationUs > mUpSwitchMark) { 22217c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ++upCount; 2222d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang } 2223d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (bufferedDurationUs < mDownSwitchMark) { 22247c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ++downCount; 22257c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 22267c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 22277c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 22287c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 22297c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (minBufferPercent >= 0) { 22307c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notifyBufferingUpdate(minBufferPercent); 223114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 223214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 2233964adb17885185808398507d2de88665fe193ee2Chong Zhang if (activeCount > 0) { 22347c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang up = (upCount == activeCount); 22357c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang down = (downCount > 0); 22367c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ready = (readyCount == activeCount); 22377c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang underflow = (underflowCount > 0); 22381543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih return true; 22391543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 2240964adb17885185808398507d2de88665fe193ee2Chong Zhang 2241964adb17885185808398507d2de88665fe193ee2Chong Zhang return false; 22421543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih} 22431543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 22447c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::startBufferingIfNecessary() { 22457c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGV("startBufferingIfNecessary: mInPreparationPhase=%d, mBuffering=%d", 22467c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mInPreparationPhase, mBuffering); 22477c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (!mBuffering) { 22487c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mBuffering = true; 22497c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 22507c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AMessage> notify = mNotify->dup(); 22517c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->setInt32("what", kWhatBufferingStart); 22527c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->post(); 22537c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 22547c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang} 22557c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 22567c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::stopBufferingIfNecessary() { 22577c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGV("stopBufferingIfNecessary: mInPreparationPhase=%d, mBuffering=%d", 22587c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mInPreparationPhase, mBuffering); 22597c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 22607c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (mBuffering) { 22617c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mBuffering = false; 22627c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 22637c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AMessage> notify = mNotify->dup(); 22647c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->setInt32("what", kWhatBufferingEnd); 22657c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->post(); 22667c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 22677c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang} 22687c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 22697c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::notifyBufferingUpdate(int32_t percentage) { 22707c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (percentage < mPrevBufferPercentage) { 22717c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang percentage = mPrevBufferPercentage; 22727c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } else if (percentage > 100) { 22737c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang percentage = 100; 22747c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 22757c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 22767c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mPrevBufferPercentage = percentage; 22777c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 22787c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGV("notifyBufferingUpdate: percentage=%d%%", percentage); 22797c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 22807c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AMessage> notify = mNotify->dup(); 22817c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->setInt32("what", kWhatBufferingUpdate); 22827c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->setInt32("percentage", percentage); 22837c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->post(); 22847c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang} 22857c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 22865ef659e010e90175eb5282d9642a02f6105189bfChong Zhangbool LiveSession::tryBandwidthFallback() { 22875ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (mInPreparationPhase || mReconfigurationInProgress) { 22885ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // Don't try fallback during prepare or reconfig. 22895ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // If error happens there, it's likely unrecoverable. 22905ef659e010e90175eb5282d9642a02f6105189bfChong Zhang return false; 22915ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } 22925ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (mCurBandwidthIndex > mOrigBandwidthIndex) { 22935ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // if we're switching up, simply cancel and resume old variant 22945ef659e010e90175eb5282d9642a02f6105189bfChong Zhang cancelBandwidthSwitch(true /* resume */); 22955ef659e010e90175eb5282d9642a02f6105189bfChong Zhang return true; 22965ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } else { 22975ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // if we're switching down, we're likely about to underflow (if 22985ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // not already underflowing). try the lowest viable bandwidth if 22995ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // not on that variant already. 23005ef659e010e90175eb5282d9642a02f6105189bfChong Zhang ssize_t lowestValid = getLowestValidBandwidthIndex(); 23015ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (mCurBandwidthIndex > lowestValid) { 23025ef659e010e90175eb5282d9642a02f6105189bfChong Zhang cancelBandwidthSwitch(); 23035ef659e010e90175eb5282d9642a02f6105189bfChong Zhang changeConfiguration(-1ll, lowestValid); 23045ef659e010e90175eb5282d9642a02f6105189bfChong Zhang return true; 23055ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } 23065ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } 23075ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // return false if we couldn't find any fallback 23085ef659e010e90175eb5282d9642a02f6105189bfChong Zhang return false; 23095ef659e010e90175eb5282d9642a02f6105189bfChong Zhang} 23105ef659e010e90175eb5282d9642a02f6105189bfChong Zhang 23118464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang/* 23128464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang * returns true if a bandwidth switch is actually needed (and started), 23138464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang * returns false otherwise 23148464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang */ 23158464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhangbool LiveSession::switchBandwidthIfNeeded(bool bufferHigh, bool bufferLow) { 2316538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang // no need to check bandwidth if we only have 1 bandwidth settings 23175ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (mBandwidthItems.size() < 2) { 23185ef659e010e90175eb5282d9642a02f6105189bfChong Zhang return false; 23195ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } 23205ef659e010e90175eb5282d9642a02f6105189bfChong Zhang 23215ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (mSwitchInProgress) { 23225ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (mBuffering) { 23235ef659e010e90175eb5282d9642a02f6105189bfChong Zhang tryBandwidthFallback(); 23245ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } 23258464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang return false; 2326538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang } 2327538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 23285ef659e010e90175eb5282d9642a02f6105189bfChong Zhang int32_t bandwidthBps, shortTermBps; 2329978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang bool isStable; 23305ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (mBandwidthEstimator->estimateBandwidth( 23315ef659e010e90175eb5282d9642a02f6105189bfChong Zhang &bandwidthBps, &isStable, &shortTermBps)) { 23325ef659e010e90175eb5282d9642a02f6105189bfChong Zhang ALOGV("bandwidth estimated at %.2f kbps, " 23335ef659e010e90175eb5282d9642a02f6105189bfChong Zhang "stable %d, shortTermBps %.2f kbps", 23345ef659e010e90175eb5282d9642a02f6105189bfChong Zhang bandwidthBps / 1024.0f, isStable, shortTermBps / 1024.0f); 2335a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mLastBandwidthBps = bandwidthBps; 23365ef659e010e90175eb5282d9642a02f6105189bfChong Zhang mLastBandwidthStable = isStable; 2337538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang } else { 2338538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang ALOGV("no bandwidth estimate."); 23398464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang return false; 2340538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang } 2341538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 2342538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang int32_t curBandwidth = mBandwidthItems.itemAt(mCurBandwidthIndex).mBandwidth; 2343d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // canSwithDown and canSwitchUp can't both be true. 2344d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // we only want to switch up when measured bw is 120% higher than current variant, 2345d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // and we only want to switch down when measured bw is below current variant. 2346978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang bool canSwitchDown = bufferLow 2347d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang && (bandwidthBps < (int32_t)curBandwidth); 2348d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang bool canSwitchUp = bufferHigh 2349d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang && (bandwidthBps > (int32_t)curBandwidth * 12 / 10); 2350d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang 2351978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (canSwitchDown || canSwitchUp) { 2352978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang // bandwidth estimating has some delay, if we have to downswitch when 23535ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // it hasn't stabilized, use the short term to guess real bandwidth, 23545ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // since it may be dropping too fast. 23555ef659e010e90175eb5282d9642a02f6105189bfChong Zhang // (note this doesn't apply to upswitch, always use longer average there) 2356978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (!isStable && canSwitchDown) { 23575ef659e010e90175eb5282d9642a02f6105189bfChong Zhang if (shortTermBps < bandwidthBps) { 23585ef659e010e90175eb5282d9642a02f6105189bfChong Zhang bandwidthBps = shortTermBps; 23595ef659e010e90175eb5282d9642a02f6105189bfChong Zhang } 2360978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 2361978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang 2362538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang ssize_t bandwidthIndex = getBandwidthIndex(bandwidthBps); 2363538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 2364d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // it's possible that we're checking for canSwitchUp case, but the returned 2365d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // bandwidthIndex is < mCurBandwidthIndex, as getBandwidthIndex() only uses 70% 2366d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // of measured bw. In that case we don't want to do anything, since we have 2367d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // both enough buffer and enough bw. 23688464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang if ((canSwitchUp && bandwidthIndex > mCurBandwidthIndex) 2369978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang || (canSwitchDown && bandwidthIndex < mCurBandwidthIndex)) { 23708464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang // if not yet prepared, just restart again with new bw index. 23718464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang // this is faster and playback experience is cleaner. 23728464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang changeConfiguration( 23738464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang mInPreparationPhase ? 0 : -1ll, bandwidthIndex); 23748464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang return true; 2375538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang } 237614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 23778464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang return false; 2378a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 2379a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 23807c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::postError(status_t err) { 23817c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // if we reached EOS, notify buffering of 100% 23827c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (err == ERROR_END_OF_STREAM) { 23837c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notifyBufferingUpdate(100); 23847c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 23857c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // we'll stop buffer polling now, before that notify 23867c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // stop buffering to stop the spinning icon 23877c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang stopBufferingIfNecessary(); 23887c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang cancelPollBuffering(); 23897c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 23907c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AMessage> notify = mNotify->dup(); 23917c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->setInt32("what", kWhatError); 23927c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->setInt32("err", err); 23937c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->post(); 23947c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang} 23957c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 239614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::postPrepared(status_t err) { 239714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(mInPreparationPhase); 2398a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 239914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AMessage> notify = mNotify->dup(); 240014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (err == OK || err == ERROR_END_OF_STREAM) { 240114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->setInt32("what", kWhatPrepared); 240214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else { 24037c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang cancelPollBuffering(); 24047c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 240514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->setInt32("what", kWhatPreparationFailed); 240614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->setInt32("err", err); 240714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 2408a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 240914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->post(); 2410a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 241114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mInPreparationPhase = false; 2412b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber} 2413b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber 2414964adb17885185808398507d2de88665fe193ee2Chong Zhang 2415a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} // namespace android 2416a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 2417