LiveSession.cpp revision 8a048338d9291b2db1b3a325fff58cb1aa69f04d
1a44153c1a57202fb538659eb50706e60454d6273Andreas Huber/* 2a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * Copyright (C) 2010 The Android Open Source Project 3a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * 4a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 5a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * you may not use this file except in compliance with the License. 6a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * You may obtain a copy of the License at 7a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * 8a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * http://www.apache.org/licenses/LICENSE-2.0 9a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * 10a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * Unless required by applicable law or agreed to in writing, software 11a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 12a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * See the License for the specific language governing permissions and 14a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * limitations under the License. 15a44153c1a57202fb538659eb50706e60454d6273Andreas Huber */ 16a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 17a44153c1a57202fb538659eb50706e60454d6273Andreas Huber//#define LOG_NDEBUG 0 18a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#define LOG_TAG "LiveSession" 19a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <utils/Log.h> 20a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 2114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include "LiveSession.h" 225abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang#include "HTTPDownloader.h" 2314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include "M3UParser.h" 2414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include "PlaylistFetcher.h" 25a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 2614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include "mpeg2ts/AnotherPacketSource.h" 27a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 28a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <cutils/properties.h> 291b86fe063badb5f28c467ade39be0f4008688947Andreas Huber#include <media/IMediaHTTPService.h> 30a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <media/stagefright/foundation/ABuffer.h> 31a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <media/stagefright/foundation/ADebug.h> 32a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <media/stagefright/foundation/AMessage.h> 337c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang#include <media/stagefright/foundation/AUtils.h> 340852843d304006e3ab333081fddda13b07193de8Robert Shih#include <media/stagefright/MediaDefs.h> 3514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include <media/stagefright/MetaData.h> 3614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include <media/stagefright/Utils.h> 37a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 381543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih#include <utils/Mutex.h> 391543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 40a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <ctype.h> 41b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross#include <inttypes.h> 42a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 43a44153c1a57202fb538659eb50706e60454d6273Andreas Hubernamespace android { 44a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 45765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang// static 46765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang// Bandwidth Switch Mark Defaults 47d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhangconst int64_t LiveSession::kUpSwitchMarkUs = 15000000ll; 48d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhangconst int64_t LiveSession::kDownSwitchMarkUs = 20000000ll; 49765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhangconst int64_t LiveSession::kUpSwitchMarginUs = 5000000ll; 50d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhangconst int64_t LiveSession::kResumeThresholdUs = 100000ll; 51765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang 52765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang// Buffer Prepare/Ready/Underflow Marks 53765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhangconst int64_t LiveSession::kReadyMarkUs = 5000000ll; 54765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhangconst int64_t LiveSession::kPrepareMarkUs = 1500000ll; 55765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhangconst int64_t LiveSession::kUnderflowMarkUs = 1000000ll; 56765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang 57538b6d22a3578c0201d48f8548289aa254d81484Chong Zhangstruct LiveSession::BandwidthEstimator : public RefBase { 58538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang BandwidthEstimator(); 59538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 60538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang void addBandwidthMeasurement(size_t numBytes, int64_t delayUs); 61978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang bool estimateBandwidth(int32_t *bandwidth, bool *isStable = NULL); 62538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 63538b6d22a3578c0201d48f8548289aa254d81484Chong Zhangprivate: 64538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang // Bandwidth estimation parameters 6581636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang static const int32_t kMinBandwidthHistoryItems = 20; 6681636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang static const int64_t kMinBandwidthHistoryWindowUs = 5000000ll; // 5 sec 6781636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang static const int64_t kMaxBandwidthHistoryWindowUs = 30000000ll; // 30 sec 68538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 69538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang struct BandwidthEntry { 70538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang int64_t mDelayUs; 71538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang size_t mNumBytes; 72538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang }; 73538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 74538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang Mutex mLock; 75538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang List<BandwidthEntry> mBandwidthHistory; 76978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang List<int32_t> mPrevEstimates; 77978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang bool mHasNewSample; 78978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang bool mIsStable; 79538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang int64_t mTotalTransferTimeUs; 80538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang size_t mTotalTransferBytes; 81538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 82538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang DISALLOW_EVIL_CONSTRUCTORS(BandwidthEstimator); 83538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang}; 84538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 85538b6d22a3578c0201d48f8548289aa254d81484Chong ZhangLiveSession::BandwidthEstimator::BandwidthEstimator() : 86978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mHasNewSample(false), 87978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mIsStable(true), 88538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mTotalTransferTimeUs(0), 89538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mTotalTransferBytes(0) { 90538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang} 91538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 92538b6d22a3578c0201d48f8548289aa254d81484Chong Zhangvoid LiveSession::BandwidthEstimator::addBandwidthMeasurement( 93538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang size_t numBytes, int64_t delayUs) { 94538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang AutoMutex autoLock(mLock); 95538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 96538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang BandwidthEntry entry; 97538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang entry.mDelayUs = delayUs; 98538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang entry.mNumBytes = numBytes; 99538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mTotalTransferTimeUs += delayUs; 100538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mTotalTransferBytes += numBytes; 101538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mBandwidthHistory.push_back(entry); 102978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mHasNewSample = true; 103538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 10481636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang // Remove no more than 10% of total transfer time at a time 10581636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang // to avoid sudden jump on bandwidth estimation. There might 10681636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang // be long blocking reads that takes up signification time, 10781636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang // we have to keep a longer window in that case. 10881636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang int64_t bandwidthHistoryWindowUs = mTotalTransferTimeUs * 9 / 10; 10981636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang if (bandwidthHistoryWindowUs < kMinBandwidthHistoryWindowUs) { 11081636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang bandwidthHistoryWindowUs = kMinBandwidthHistoryWindowUs; 11181636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang } else if (bandwidthHistoryWindowUs > kMaxBandwidthHistoryWindowUs) { 11281636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang bandwidthHistoryWindowUs = kMaxBandwidthHistoryWindowUs; 11381636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang } 114538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang // trim old samples, keeping at least kMaxBandwidthHistoryItems samples, 115538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang // and total transfer time at least kMaxBandwidthHistoryWindowUs. 11681636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang while (mBandwidthHistory.size() > kMinBandwidthHistoryItems) { 117538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang List<BandwidthEntry>::iterator it = mBandwidthHistory.begin(); 11881636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang if (mTotalTransferTimeUs - it->mDelayUs < bandwidthHistoryWindowUs) { 119538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang break; 120538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang } 121538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mTotalTransferTimeUs -= it->mDelayUs; 122538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mTotalTransferBytes -= it->mNumBytes; 123538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mBandwidthHistory.erase(mBandwidthHistory.begin()); 124538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang } 125538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang} 126538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 12781636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhangbool LiveSession::BandwidthEstimator::estimateBandwidth( 12881636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang int32_t *bandwidthBps, bool *isStable) { 129538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang AutoMutex autoLock(mLock); 130538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 131538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang if (mBandwidthHistory.size() < 2) { 132538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang return false; 133538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang } 134538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 135978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (!mHasNewSample) { 136978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang *bandwidthBps = *(--mPrevEstimates.end()); 137978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (isStable) { 138978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang *isStable = mIsStable; 139978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 140978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang return true; 141978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 142978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang 143538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang *bandwidthBps = ((double)mTotalTransferBytes * 8E6 / mTotalTransferTimeUs); 144978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mPrevEstimates.push_back(*bandwidthBps); 145978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang while (mPrevEstimates.size() > 3) { 146978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mPrevEstimates.erase(mPrevEstimates.begin()); 147978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 148978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mHasNewSample = false; 149978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang 150978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang int32_t minEstimate = -1, maxEstimate = -1; 151978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang List<int32_t>::iterator it; 152978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang for (it = mPrevEstimates.begin(); it != mPrevEstimates.end(); it++) { 153978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang int32_t estimate = *it; 154978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (minEstimate < 0 || minEstimate > estimate) { 155978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang minEstimate = estimate; 156978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 157978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (maxEstimate < 0 || maxEstimate < estimate) { 158978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang maxEstimate = estimate; 159978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 160978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 161978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mIsStable = (maxEstimate <= minEstimate * 4 / 3); 162978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (isStable) { 163978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang *isStable = mIsStable; 164978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 16581636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang#if 0 16681636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang { 16781636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang char dumpStr[1024] = {0}; 16881636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang size_t itemIdx = 0; 16981636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang size_t histSize = mBandwidthHistory.size(); 17081636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang sprintf(dumpStr, "estimate bps=%d stable=%d history (n=%d): {", 17181636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang *bandwidthBps, mIsStable, histSize); 17281636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang List<BandwidthEntry>::iterator it = mBandwidthHistory.begin(); 17381636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang for (; it != mBandwidthHistory.end(); ++it) { 17481636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang if (itemIdx > 50) { 17581636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang sprintf(dumpStr + strlen(dumpStr), 17681636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang "...(%zd more items)... }", histSize - itemIdx); 17781636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang break; 17881636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang } 17981636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang sprintf(dumpStr + strlen(dumpStr), "%dk/%.3fs%s", 18081636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang it->mNumBytes / 1024, 18181636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang (double)it->mDelayUs * 1.0e-6, 18281636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang (it == (--mBandwidthHistory.end())) ? "}" : ", "); 18381636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang itemIdx++; 18481636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang } 18581636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang ALOGE(dumpStr); 18681636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang } 18781636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang#endif 188538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang return true; 189538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang} 190538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 1917c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang//static 1927c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangconst char *LiveSession::getKeyForStream(StreamType type) { 1937c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang switch (type) { 1947c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang case STREAMTYPE_VIDEO: 1957c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return "timeUsVideo"; 1967c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang case STREAMTYPE_AUDIO: 1977c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return "timeUsAudio"; 1987c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang case STREAMTYPE_SUBTITLES: 1997c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return "timeUsSubtitle"; 2000852843d304006e3ab333081fddda13b07193de8Robert Shih case STREAMTYPE_METADATA: 2010852843d304006e3ab333081fddda13b07193de8Robert Shih return "timeUsMetadata"; // unused 2027c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang default: 2037c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang TRESPASS(); 2047c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 2057c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return NULL; 2067c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang} 2077c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 20825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang//static 20925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhangconst char *LiveSession::getNameForStream(StreamType type) { 21025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang switch (type) { 21125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang case STREAMTYPE_VIDEO: 21225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang return "video"; 21325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang case STREAMTYPE_AUDIO: 21425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang return "audio"; 21525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang case STREAMTYPE_SUBTITLES: 21625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang return "subs"; 2170852843d304006e3ab333081fddda13b07193de8Robert Shih case STREAMTYPE_METADATA: 2180852843d304006e3ab333081fddda13b07193de8Robert Shih return "metadata"; 21925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang default: 22025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang break; 22125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang } 22225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang return "unknown"; 22325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang} 22425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 2250852843d304006e3ab333081fddda13b07193de8Robert Shih//static 2260852843d304006e3ab333081fddda13b07193de8Robert ShihATSParser::SourceType LiveSession::getSourceTypeForStream(StreamType type) { 2270852843d304006e3ab333081fddda13b07193de8Robert Shih switch (type) { 2280852843d304006e3ab333081fddda13b07193de8Robert Shih case STREAMTYPE_VIDEO: 2290852843d304006e3ab333081fddda13b07193de8Robert Shih return ATSParser::VIDEO; 2300852843d304006e3ab333081fddda13b07193de8Robert Shih case STREAMTYPE_AUDIO: 2310852843d304006e3ab333081fddda13b07193de8Robert Shih return ATSParser::AUDIO; 2320852843d304006e3ab333081fddda13b07193de8Robert Shih case STREAMTYPE_METADATA: 2330852843d304006e3ab333081fddda13b07193de8Robert Shih return ATSParser::META; 2340852843d304006e3ab333081fddda13b07193de8Robert Shih case STREAMTYPE_SUBTITLES: 2350852843d304006e3ab333081fddda13b07193de8Robert Shih default: 2360852843d304006e3ab333081fddda13b07193de8Robert Shih TRESPASS(); 2370852843d304006e3ab333081fddda13b07193de8Robert Shih } 2380852843d304006e3ab333081fddda13b07193de8Robert Shih return ATSParser::NUM_SOURCE_TYPES; // should not reach here 2390852843d304006e3ab333081fddda13b07193de8Robert Shih} 2400852843d304006e3ab333081fddda13b07193de8Robert Shih 2410df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas HuberLiveSession::LiveSession( 2421b86fe063badb5f28c467ade39be0f4008688947Andreas Huber const sp<AMessage> ¬ify, uint32_t flags, 24381e68448f3361eaf8618930471fdc3c21bdf5cbcAndreas Huber const sp<IMediaHTTPService> &httpService) 2440df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas Huber : mNotify(notify), 2450df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas Huber mFlags(flags), 2461b86fe063badb5f28c467ade39be0f4008688947Andreas Huber mHTTPService(httpService), 2477c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mBuffering(false), 2480df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas Huber mInPreparationPhase(true), 2497c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mPollBufferingGeneration(0), 2507c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mPrevBufferPercentage(-1), 251309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mCurBandwidthIndex(-1), 2527c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mOrigBandwidthIndex(-1), 253a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mLastBandwidthBps(-1ll), 254538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mBandwidthEstimator(new BandwidthEstimator()), 255a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang mMaxWidth(720), 256a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang mMaxHeight(480), 25714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mStreamMask(0), 2581543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih mNewStreamMask(0), 2591543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih mSwapMask(0), 2601543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih mSwitchGeneration(0), 261b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih mSubtitleGeneration(0), 26214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mLastDequeuedTimeUs(0ll), 263dcb89b3b505522efde173c105a851c412f947178Chong Zhang mRealTimeBaseUs(0ll), 26414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mReconfigurationInProgress(false), 2651543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih mSwitchInProgress(false), 266765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang mUpSwitchMark(kUpSwitchMarkUs), 267765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang mDownSwitchMark(kDownSwitchMarkUs), 268765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang mUpSwitchMargin(kUpSwitchMarginUs), 269309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mFirstTimeUsValid(false), 270309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mFirstTimeUs(0), 2710852843d304006e3ab333081fddda13b07193de8Robert Shih mLastSeekTimeUs(0), 2720852843d304006e3ab333081fddda13b07193de8Robert Shih mHasMetadata(false) { 2738ca002eedc747dd854b61cbe364b52c06869273fRobert Shih mStreams[kAudioIndex] = StreamItem("audio"); 2748ca002eedc747dd854b61cbe364b52c06869273fRobert Shih mStreams[kVideoIndex] = StreamItem("video"); 275e4f25c280a8f1655c31a745978e0fcbc61f91deeRobert Shih mStreams[kSubtitleIndex] = StreamItem("subtitles"); 27614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 2770852843d304006e3ab333081fddda13b07193de8Robert Shih for (size_t i = 0; i < kNumSources; ++i) { 2788ca002eedc747dd854b61cbe364b52c06869273fRobert Shih mPacketSources.add(indexToType(i), new AnotherPacketSource(NULL /* meta */)); 2791543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih mPacketSources2.add(indexToType(i), new AnotherPacketSource(NULL /* meta */)); 2808ca002eedc747dd854b61cbe364b52c06869273fRobert Shih } 281a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 282a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 283a44153c1a57202fb538659eb50706e60454d6273Andreas HuberLiveSession::~LiveSession() { 284964adb17885185808398507d2de88665fe193ee2Chong Zhang if (mFetcherLooper != NULL) { 285964adb17885185808398507d2de88665fe193ee2Chong Zhang mFetcherLooper->stop(); 286964adb17885185808398507d2de88665fe193ee2Chong Zhang } 287a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 288a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 2890852843d304006e3ab333081fddda13b07193de8Robert Shihint64_t LiveSession::calculateMediaTimeUs( 2900852843d304006e3ab333081fddda13b07193de8Robert Shih int64_t firstTimeUs, int64_t timeUs, int32_t discontinuitySeq) { 2910852843d304006e3ab333081fddda13b07193de8Robert Shih if (timeUs >= firstTimeUs) { 2920852843d304006e3ab333081fddda13b07193de8Robert Shih timeUs -= firstTimeUs; 2930852843d304006e3ab333081fddda13b07193de8Robert Shih } else { 2940852843d304006e3ab333081fddda13b07193de8Robert Shih timeUs = 0; 2950852843d304006e3ab333081fddda13b07193de8Robert Shih } 2960852843d304006e3ab333081fddda13b07193de8Robert Shih timeUs += mLastSeekTimeUs; 2970852843d304006e3ab333081fddda13b07193de8Robert Shih if (mDiscontinuityOffsetTimesUs.indexOfKey(discontinuitySeq) >= 0) { 2980852843d304006e3ab333081fddda13b07193de8Robert Shih timeUs += mDiscontinuityOffsetTimesUs.valueFor(discontinuitySeq); 2990852843d304006e3ab333081fddda13b07193de8Robert Shih } 3000852843d304006e3ab333081fddda13b07193de8Robert Shih return timeUs; 3010852843d304006e3ab333081fddda13b07193de8Robert Shih} 3020852843d304006e3ab333081fddda13b07193de8Robert Shih 30314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::dequeueAccessUnit( 30414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber StreamType stream, sp<ABuffer> *accessUnit) { 305964adb17885185808398507d2de88665fe193ee2Chong Zhang status_t finalResult = OK; 30614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AnotherPacketSource> packetSource = mPacketSources.valueFor(stream); 30714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 30825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ssize_t streamIdx = typeToIndex(stream); 30925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang if (streamIdx < 0) { 3105abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang return BAD_VALUE; 31125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang } 31225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang const char *streamStr = getNameForStream(stream); 313a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // Do not let client pull data if we don't have data packets yet. 314a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // We might only have a format discontinuity queued without data. 315a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // When NuPlayerDecoder dequeues the format discontinuity, it will 316a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // immediately try to getFormat. If we return NULL, NuPlayerDecoder 317a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // thinks it can do seamless change, so will not shutdown decoder. 318a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // When the actual format arrives, it can't handle it and get stuck. 319a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (!packetSource->hasDataBufferAvailable(&finalResult)) { 32025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("[%s] dequeueAccessUnit: no buffer available (finalResult=%d)", 32125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang streamStr, finalResult); 32225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 323f69c996864844e8f669308af8412cede043062a2Robert Shih if (finalResult == OK) { 324f69c996864844e8f669308af8412cede043062a2Robert Shih return -EAGAIN; 325f69c996864844e8f669308af8412cede043062a2Robert Shih } else { 326f69c996864844e8f669308af8412cede043062a2Robert Shih return finalResult; 327f69c996864844e8f669308af8412cede043062a2Robert Shih } 328f69c996864844e8f669308af8412cede043062a2Robert Shih } 329f69c996864844e8f669308af8412cede043062a2Robert Shih 330a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // Let the client dequeue as long as we have buffers available 331a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // Do not make pause/resume decisions here. 332309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 33314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber status_t err = packetSource->dequeueAccessUnit(accessUnit); 33414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 33514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (err == INFO_DISCONTINUITY) { 336309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih // adaptive streaming, discontinuities in the playlist 33714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int32_t type; 33814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK((*accessUnit)->meta()->findInt32("discontinuity", &type)); 33914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 34014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AMessage> extra; 34114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (!(*accessUnit)->meta()->findMessage("extra", &extra)) { 34214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber extra.clear(); 34314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 34414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 34514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGI("[%s] read discontinuity of type %d, extra = %s", 34614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber streamStr, 34714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber type, 34814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber extra == NULL ? "NULL" : extra->debugString().c_str()); 34914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else if (err == OK) { 350309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 351dcb89b3b505522efde173c105a851c412f947178Chong Zhang if (stream == STREAMTYPE_AUDIO || stream == STREAMTYPE_VIDEO) { 35225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang int64_t timeUs, originalTimeUs; 353309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih int32_t discontinuitySeq = 0; 3540852843d304006e3ab333081fddda13b07193de8Robert Shih StreamItem& strm = mStreams[streamIdx]; 355dcb89b3b505522efde173c105a851c412f947178Chong Zhang CHECK((*accessUnit)->meta()->findInt64("timeUs", &timeUs)); 35625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang originalTimeUs = timeUs; 357309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih (*accessUnit)->meta()->findInt32("discontinuitySeq", &discontinuitySeq); 3587c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (discontinuitySeq > (int32_t) strm.mCurDiscontinuitySeq) { 3597c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang int64_t offsetTimeUs; 3607c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (mDiscontinuityOffsetTimesUs.indexOfKey(strm.mCurDiscontinuitySeq) >= 0) { 3617c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang offsetTimeUs = mDiscontinuityOffsetTimesUs.valueFor(strm.mCurDiscontinuitySeq); 3627c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } else { 3637c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang offsetTimeUs = 0; 3647c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 3657c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 36681636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang if (mDiscontinuityAbsStartTimesUs.indexOfKey(strm.mCurDiscontinuitySeq) >= 0 36781636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang && strm.mLastDequeuedTimeUs >= 0) { 3687c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang int64_t firstTimeUs; 3697c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang firstTimeUs = mDiscontinuityAbsStartTimesUs.valueFor(strm.mCurDiscontinuitySeq); 3707c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang offsetTimeUs += strm.mLastDequeuedTimeUs - firstTimeUs; 3717c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang offsetTimeUs += strm.mLastSampleDurationUs; 3727c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } else { 3737c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang offsetTimeUs += strm.mLastSampleDurationUs; 3747c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 3757c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 3767c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mDiscontinuityOffsetTimesUs.add(discontinuitySeq, offsetTimeUs); 3777c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang strm.mCurDiscontinuitySeq = discontinuitySeq; 3787c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 379309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 380309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih int32_t discard = 0; 381309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih int64_t firstTimeUs; 382309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (mDiscontinuityAbsStartTimesUs.indexOfKey(strm.mCurDiscontinuitySeq) >= 0) { 383309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih int64_t durUs; // approximate sample duration 384309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (timeUs > strm.mLastDequeuedTimeUs) { 385309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih durUs = timeUs - strm.mLastDequeuedTimeUs; 386309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } else { 387309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih durUs = strm.mLastDequeuedTimeUs - timeUs; 388309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 389309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih strm.mLastSampleDurationUs = durUs; 390309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih firstTimeUs = mDiscontinuityAbsStartTimesUs.valueFor(strm.mCurDiscontinuitySeq); 391309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } else if ((*accessUnit)->meta()->findInt32("discard", &discard) && discard) { 392309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih firstTimeUs = timeUs; 393309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } else { 394309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mDiscontinuityAbsStartTimesUs.add(strm.mCurDiscontinuitySeq, timeUs); 395309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih firstTimeUs = timeUs; 396309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 397309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 398309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih strm.mLastDequeuedTimeUs = timeUs; 3990852843d304006e3ab333081fddda13b07193de8Robert Shih timeUs = calculateMediaTimeUs(firstTimeUs, timeUs, discontinuitySeq); 400dcb89b3b505522efde173c105a851c412f947178Chong Zhang 40125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("[%s] dequeueAccessUnit: time %lld us, original %lld us", 40225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang streamStr, (long long)timeUs, (long long)originalTimeUs); 403309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih (*accessUnit)->meta()->setInt64("timeUs", timeUs); 404dcb89b3b505522efde173c105a851c412f947178Chong Zhang mLastDequeuedTimeUs = timeUs; 405dcb89b3b505522efde173c105a851c412f947178Chong Zhang mRealTimeBaseUs = ALooper::GetNowUs() - timeUs; 406dcb89b3b505522efde173c105a851c412f947178Chong Zhang } else if (stream == STREAMTYPE_SUBTITLES) { 407b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih int32_t subtitleGeneration; 408b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih if ((*accessUnit)->meta()->findInt32("subtitleGeneration", &subtitleGeneration) 409b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih && subtitleGeneration != mSubtitleGeneration) { 410b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih return -EAGAIN; 411b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih }; 412dcb89b3b505522efde173c105a851c412f947178Chong Zhang (*accessUnit)->meta()->setInt32( 413dcb89b3b505522efde173c105a851c412f947178Chong Zhang "trackIndex", mPlaylist->getSelectedIndex()); 414dcb89b3b505522efde173c105a851c412f947178Chong Zhang (*accessUnit)->meta()->setInt64("baseUs", mRealTimeBaseUs); 4150852843d304006e3ab333081fddda13b07193de8Robert Shih } else if (stream == STREAMTYPE_METADATA) { 4160852843d304006e3ab333081fddda13b07193de8Robert Shih HLSTime mdTime((*accessUnit)->meta()); 4170852843d304006e3ab333081fddda13b07193de8Robert Shih if (mDiscontinuityAbsStartTimesUs.indexOfKey(mdTime.mSeq) < 0) { 4180852843d304006e3ab333081fddda13b07193de8Robert Shih packetSource->requeueAccessUnit((*accessUnit)); 4190852843d304006e3ab333081fddda13b07193de8Robert Shih return -EAGAIN; 4200852843d304006e3ab333081fddda13b07193de8Robert Shih } else { 4210852843d304006e3ab333081fddda13b07193de8Robert Shih int64_t firstTimeUs = mDiscontinuityAbsStartTimesUs.valueFor(mdTime.mSeq); 4220852843d304006e3ab333081fddda13b07193de8Robert Shih int64_t timeUs = calculateMediaTimeUs(firstTimeUs, mdTime.mTimeUs, mdTime.mSeq); 4230852843d304006e3ab333081fddda13b07193de8Robert Shih (*accessUnit)->meta()->setInt64("timeUs", timeUs); 4240852843d304006e3ab333081fddda13b07193de8Robert Shih (*accessUnit)->meta()->setInt64("baseUs", mRealTimeBaseUs); 4250852843d304006e3ab333081fddda13b07193de8Robert Shih } 426dcb89b3b505522efde173c105a851c412f947178Chong Zhang } 42714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else { 42814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGI("[%s] encountered error %d", streamStr, err); 42914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 43014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 43114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return err; 43214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 43314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 43414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::getStreamFormat(StreamType stream, sp<AMessage> *format) { 43514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (!(mStreamMask & stream)) { 43614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return UNKNOWN_ERROR; 43714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 43814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 43914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AnotherPacketSource> packetSource = mPacketSources.valueFor(stream); 44014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 44114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<MetaData> meta = packetSource->getFormat(); 44214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 44314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (meta == NULL) { 44414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return -EAGAIN; 44514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 44614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 4477c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (stream == STREAMTYPE_AUDIO) { 4487c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // set AAC input buffer size to 32K bytes (256kbps x 1sec) 4497c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang meta->setInt32(kKeyMaxInputSize, 32 * 1024); 450a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang } else if (stream == STREAMTYPE_VIDEO) { 451a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang meta->setInt32(kKeyMaxWidth, mMaxWidth); 452a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang meta->setInt32(kKeyMaxHeight, mMaxHeight); 4537c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 4547c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 45514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return convertMetaDataToMessage(meta, format); 456a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 457a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 4585abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhangsp<HTTPDownloader> LiveSession::getHTTPDownloader() { 4595abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang return new HTTPDownloader(mHTTPService, mExtraHeaders); 460a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang} 461a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 46214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::connectAsync( 463ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber const char *url, const KeyedVector<String8, String8> *headers) { 4641d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> msg = new AMessage(kWhatConnect, this); 465a44153c1a57202fb538659eb50706e60454d6273Andreas Huber msg->setString("url", url); 466ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber 467ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber if (headers != NULL) { 468ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber msg->setPointer( 469ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber "headers", 470ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber new KeyedVector<String8, String8>(*headers)); 471ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber } 472ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber 473a44153c1a57202fb538659eb50706e60454d6273Andreas Huber msg->post(); 474a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 475a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 47614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::disconnect() { 4771d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> msg = new AMessage(kWhatDisconnect, this); 478ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber 47914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AMessage> response; 48014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber status_t err = msg->postAndAwaitResponse(&response); 481ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber 48214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return err; 483a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 484a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 48514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::seekTo(int64_t timeUs) { 4861d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> msg = new AMessage(kWhatSeek, this); 487a44153c1a57202fb538659eb50706e60454d6273Andreas Huber msg->setInt64("timeUs", timeUs); 488a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 48914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AMessage> response; 49014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber status_t err = msg->postAndAwaitResponse(&response); 49114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 49214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return err; 493a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 494a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 4957c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangbool LiveSession::checkSwitchProgress( 4967c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AMessage> &stopParams, int64_t delayUs, bool *needResumeUntil) { 4977c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang AString newUri; 4987c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang CHECK(stopParams->findString("uri", &newUri)); 4997c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 5007c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang *needResumeUntil = false; 5017c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AMessage> firstNewMeta[kMaxStreams]; 5027c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang for (size_t i = 0; i < kMaxStreams; ++i) { 5037c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang StreamType stream = indexToType(i); 5047c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (!(mSwapMask & mNewStreamMask & stream) 5057c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang || (mStreams[i].mNewUri != newUri)) { 5067c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang continue; 5077c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 5087c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (stream == STREAMTYPE_SUBTITLES) { 5097c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang continue; 5107c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 5117c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AnotherPacketSource> &source = mPacketSources.editValueAt(i); 5127c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 5137c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // First, get latest dequeued meta, which is where the decoder is at. 5147c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // (when upswitching, we take the meta after a certain delay, so that 5157c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // the decoder is left with some cushion) 5167c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AMessage> lastDequeueMeta, lastEnqueueMeta; 5177c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (delayUs > 0) { 5187c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang lastDequeueMeta = source->getMetaAfterLastDequeued(delayUs); 519d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (lastDequeueMeta == NULL) { 520d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // this means we don't have enough cushion, try again later 521d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang ALOGV("[%s] up switching failed due to insufficient buffer", 52225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang getNameForStream(stream)); 523d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang return false; 524d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang } 5257c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } else { 526d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // It's okay for lastDequeueMeta to be NULL here, it means the 527d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // decoder hasn't even started dequeueing 5287c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang lastDequeueMeta = source->getLatestDequeuedMeta(); 5297c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 5307c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // Then, trim off packets at beginning of mPacketSources2 that's before 5317c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // the latest dequeued time. These samples are definitely too late. 532d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang firstNewMeta[i] = mPacketSources2.editValueAt(i) 533d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang ->trimBuffersBeforeMeta(lastDequeueMeta); 534d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang 5357c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // Now firstNewMeta[i] is the first sample after the trim. 5367c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // If it's NULL, we failed because dequeue already past all samples 5377c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // in mPacketSource2, we have to try again. 5387c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (firstNewMeta[i] == NULL) { 539d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang HLSTime dequeueTime(lastDequeueMeta); 5407c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGV("[%s] dequeue time (%d, %lld) past start time", 54125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang getNameForStream(stream), 542d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang dequeueTime.mSeq, (long long) dequeueTime.mTimeUs); 5437c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return false; 5447c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 5457c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 5467c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // Otherwise, we check if mPacketSources2 overlaps with what old fetcher 5477c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // already fetched, and see if we need to resumeUntil 5487c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang lastEnqueueMeta = source->getLatestEnqueuedMeta(); 5497c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // lastEnqueueMeta == NULL means old fetcher stopped at a discontinuity 5507c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // boundary, no need to resume as the content will look different anyways 5517c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (lastEnqueueMeta != NULL) { 552d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang HLSTime lastTime(lastEnqueueMeta), startTime(firstNewMeta[i]); 5537c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 5547c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // no need to resume old fetcher if new fetcher started in different 5557c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // discontinuity sequence, as the content will look different. 556d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang *needResumeUntil |= (startTime.mSeq == lastTime.mSeq 557d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang && startTime.mTimeUs - lastTime.mTimeUs > kResumeThresholdUs); 5587c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 559d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // update the stopTime for resumeUntil 560d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang stopParams->setInt32("discontinuitySeq", startTime.mSeq); 561d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang stopParams->setInt64(getKeyForStream(stream), startTime.mTimeUs); 5627c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 5637c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 5647c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 5657c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // if we're here, it means dequeue progress hasn't passed some samples in 5667c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // mPacketSource2, we can trim off the excess in mPacketSource. 5677c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // (old fetcher might still need to resumeUntil the start time of new fetcher) 5687c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang for (size_t i = 0; i < kMaxStreams; ++i) { 5697c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang StreamType stream = indexToType(i); 5707c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (!(mSwapMask & mNewStreamMask & stream) 571d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang || (newUri != mStreams[i].mNewUri) 572d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang || stream == STREAMTYPE_SUBTITLES) { 5737c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang continue; 5747c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 575d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang mPacketSources.valueFor(stream)->trimBuffersAfterMeta(firstNewMeta[i]); 5767c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 5777c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 5787c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // no resumeUntil if already underflow 5797c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang *needResumeUntil &= !mBuffering; 5807c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 5817c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return true; 5827c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang} 5837c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 584a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onMessageReceived(const sp<AMessage> &msg) { 585a44153c1a57202fb538659eb50706e60454d6273Andreas Huber switch (msg->what()) { 586a44153c1a57202fb538659eb50706e60454d6273Andreas Huber case kWhatConnect: 58714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 588a44153c1a57202fb538659eb50706e60454d6273Andreas Huber onConnect(msg); 589a44153c1a57202fb538659eb50706e60454d6273Andreas Huber break; 59014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 591a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 592a44153c1a57202fb538659eb50706e60454d6273Andreas Huber case kWhatDisconnect: 59314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 59414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->senderAwaitsResponse(&mDisconnectReplyID)); 59514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 59614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (mReconfigurationInProgress) { 59714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 59814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 59914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 60014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber finishDisconnect(); 601a44153c1a57202fb538659eb50706e60454d6273Andreas Huber break; 60214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 603a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 60414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case kWhatSeek: 60514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 606a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar if (mReconfigurationInProgress) { 607800599cdd50737de1cde483a34b39923750b0658Robert Shih msg->post(50000); 608a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar break; 609800599cdd50737de1cde483a34b39923750b0658Robert Shih } 610a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar 611a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar CHECK(msg->senderAwaitsResponse(&mSeekReplyID)); 612a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar mSeekReply = new AMessage; 613a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar 614a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar onSeek(msg); 61514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 61614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 61714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 61814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case kWhatFetcherNotify: 61914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 62014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int32_t what; 62114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->findInt32("what", &what)); 62214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 62314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber switch (what) { 62414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case PlaylistFetcher::kWhatStarted: 62514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 62614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case PlaylistFetcher::kWhatPaused: 62714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case PlaylistFetcher::kWhatStopped: 62814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 629a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang AString uri; 630a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang CHECK(msg->findString("uri", &uri)); 631a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang ssize_t index = mFetcherInfos.indexOfKey(uri); 632a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (index < 0) { 633a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // ignore msgs from fetchers that's already gone 634a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang break; 635a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 636a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 63725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("fetcher-%d %s", 63825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang mFetcherInfos[index].mFetcher->getFetcherID(), 63925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang what == PlaylistFetcher::kWhatPaused ? 64025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang "paused" : "stopped"); 64125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 64214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (what == PlaylistFetcher::kWhatStopped) { 643964adb17885185808398507d2de88665fe193ee2Chong Zhang mFetcherLooper->unregisterHandler( 644964adb17885185808398507d2de88665fe193ee2Chong Zhang mFetcherInfos[index].mFetcher->id()); 645964adb17885185808398507d2de88665fe193ee2Chong Zhang mFetcherInfos.removeItemsAt(index); 646a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } else if (what == PlaylistFetcher::kWhatPaused) { 647a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang int32_t seekMode; 648a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang CHECK(msg->findInt32("seekMode", &seekMode)); 649a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang for (size_t i = 0; i < kMaxStreams; ++i) { 650a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (mStreams[i].mUri == uri) { 651a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mStreams[i].mSeekMode = (SeekMode) seekMode; 652a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 653309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 65414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 65514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 65614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (mContinuation != NULL) { 65714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK_GT(mContinuationCounter, 0); 65814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (--mContinuationCounter == 0) { 65914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mContinuation->post(); 66014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 66125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("%zu fetcher(s) left", mContinuationCounter); 66214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 66314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 66414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 66514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 66614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case PlaylistFetcher::kWhatDurationUpdate: 66714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 66814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber AString uri; 66914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->findString("uri", &uri)); 67014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 67114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int64_t durationUs; 67214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->findInt64("durationUs", &durationUs)); 67314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 674964adb17885185808398507d2de88665fe193ee2Chong Zhang ssize_t index = mFetcherInfos.indexOfKey(uri); 675964adb17885185808398507d2de88665fe193ee2Chong Zhang if (index >= 0) { 676964adb17885185808398507d2de88665fe193ee2Chong Zhang FetcherInfo *info = &mFetcherInfos.editValueFor(uri); 677964adb17885185808398507d2de88665fe193ee2Chong Zhang info->mDurationUs = durationUs; 678964adb17885185808398507d2de88665fe193ee2Chong Zhang } 67914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 68014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 68114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 6827c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang case PlaylistFetcher::kWhatTargetDurationUpdate: 6837c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang { 6847c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang int64_t targetDurationUs; 6857c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang CHECK(msg->findInt64("targetDurationUs", &targetDurationUs)); 686d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang mUpSwitchMark = min(kUpSwitchMarkUs, targetDurationUs * 7 / 4); 687765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang mDownSwitchMark = min(kDownSwitchMarkUs, targetDurationUs * 9 / 4); 688765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang mUpSwitchMargin = min(kUpSwitchMarginUs, targetDurationUs); 6897c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang break; 6907c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 6917c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 69214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case PlaylistFetcher::kWhatError: 69314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 69414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber status_t err; 69514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->findInt32("err", &err)); 69614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 69714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGE("XXX Received error %d from PlaylistFetcher.", err); 69814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 69915f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih // handle EOS on subtitle tracks independently 70015f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih AString uri; 70115f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih if (err == ERROR_END_OF_STREAM && msg->findString("uri", &uri)) { 70215f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih ssize_t i = mFetcherInfos.indexOfKey(uri); 70315f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih if (i >= 0) { 70415f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih const sp<PlaylistFetcher> &fetcher = mFetcherInfos.valueAt(i).mFetcher; 70515f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih if (fetcher != NULL) { 70615f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih uint32_t type = fetcher->getStreamTypeMask(); 70715f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih if (type == STREAMTYPE_SUBTITLES) { 70815f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih mPacketSources.valueFor( 70915f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih STREAMTYPE_SUBTITLES)->signalEOS(err);; 71015f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih break; 71115f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih } 71215f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih } 71315f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih } 71415f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih } 71515f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih 71614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (mInPreparationPhase) { 71714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber postPrepared(err); 71814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 71914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 7201543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih cancelBandwidthSwitch(); 7211543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 72214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mPacketSources.valueFor(STREAMTYPE_AUDIO)->signalEOS(err); 72314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 72414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mPacketSources.valueFor(STREAMTYPE_VIDEO)->signalEOS(err); 72514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 72614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mPacketSources.valueFor( 72714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber STREAMTYPE_SUBTITLES)->signalEOS(err); 72814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 7297c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang postError(err); 7307c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang break; 7317c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 7327c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 7337c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang case PlaylistFetcher::kWhatStopReached: 7347c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang { 7357c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGV("kWhatStopReached"); 7367c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 737d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang AString oldUri; 738d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang CHECK(msg->findString("uri", &oldUri)); 7397c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 740d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang ssize_t index = mFetcherInfos.indexOfKey(oldUri); 7417c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (index < 0) { 7427c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang break; 7437c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 7447c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 745d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang tryToFinishBandwidthSwitch(oldUri); 74614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 74714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 74814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 7491543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih case PlaylistFetcher::kWhatStartedAt: 7501543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih { 7511543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih int32_t switchGeneration; 7521543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih CHECK(msg->findInt32("switchGeneration", &switchGeneration)); 7531543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 75425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("kWhatStartedAt: switchGen=%d, mSwitchGen=%d", 75525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang switchGeneration, mSwitchGeneration); 75625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 7571543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih if (switchGeneration != mSwitchGeneration) { 7581543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih break; 7591543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 7601543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 761a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang AString uri; 762a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang CHECK(msg->findString("uri", &uri)); 7637c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 7647c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // mark new fetcher mToBeResumed 765a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang ssize_t index = mFetcherInfos.indexOfKey(uri); 766a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (index >= 0) { 767a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mFetcherInfos.editValueAt(index).mToBeResumed = true; 768a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 769a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 7707c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // temporarily disable packet sources to be swapped to prevent 7717c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // NuPlayerDecoder from dequeuing while we check progress 7727c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang for (size_t i = 0; i < mPacketSources.size(); ++i) { 7737c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if ((mSwapMask & mPacketSources.keyAt(i)) 7747c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang && uri == mStreams[i].mNewUri) { 7757c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mPacketSources.editValueAt(i)->enable(false); 7761543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 7771543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 7787c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang bool switchUp = (mCurBandwidthIndex > mOrigBandwidthIndex); 7797c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // If switching up, require a cushion bigger than kUnderflowMark 7807c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // to avoid buffering immediately after the switch. 7817c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // (If we don't have that cushion we'd rather cancel and try again.) 782765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang int64_t delayUs = switchUp ? (kUnderflowMarkUs + 1000000ll) : 0; 7837c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang bool needResumeUntil = false; 7847c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AMessage> stopParams = msg; 7857c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (checkSwitchProgress(stopParams, delayUs, &needResumeUntil)) { 7867c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // playback time hasn't passed startAt time 7877c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (!needResumeUntil) { 78825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("finish switch"); 7897c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang for (size_t i = 0; i < kMaxStreams; ++i) { 7907c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if ((mSwapMask & indexToType(i)) 7917c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang && uri == mStreams[i].mNewUri) { 7927c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // have to make a copy of mStreams[i].mUri because 7937c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // tryToFinishBandwidthSwitch is modifying mStreams[] 7947c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang AString oldURI = mStreams[i].mUri; 7957c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang tryToFinishBandwidthSwitch(oldURI); 7967c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang break; 7977c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 7987c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 7997c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } else { 8007c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // startAt time is after last enqueue time 8017c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // Resume fetcher for the original variant; the resumed fetcher should 8027c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // continue until the timestamps found in msg, which is stored by the 8037c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // new fetcher to indicate where the new variant has started buffering. 80425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("finish switch with resumeUntilAsync"); 8057c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang for (size_t i = 0; i < mFetcherInfos.size(); i++) { 8067c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang const FetcherInfo &info = mFetcherInfos.valueAt(i); 8077c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (info.mToBeRemoved) { 8087c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang info.mFetcher->resumeUntilAsync(stopParams); 8097c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 8107c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 8117c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 8127c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } else { 8137c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // playback time passed startAt time 8147c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (switchUp) { 8157c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // if switching up, cancel and retry if condition satisfies again 81625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("cancel up switch because we're too late"); 8177c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang cancelBandwidthSwitch(true /* resume */); 8187c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } else { 81925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("retry down switch at next sample"); 8207c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang resumeFetcher(uri, mSwapMask, -1, true /* newUri */); 8217c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 8227c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 8237c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // re-enable all packet sources 8247c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang for (size_t i = 0; i < mPacketSources.size(); ++i) { 8257c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mPacketSources.editValueAt(i)->enable(true); 8267c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 8277c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 8281543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih break; 8291543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 8301543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 8315abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang case PlaylistFetcher::kWhatPlaylistFetched: 8325abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang { 8335abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang onMasterPlaylistFetched(msg); 8345abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang break; 8355abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } 8365abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 8370852843d304006e3ab333081fddda13b07193de8Robert Shih case PlaylistFetcher::kWhatMetadataDetected: 8380852843d304006e3ab333081fddda13b07193de8Robert Shih { 8390852843d304006e3ab333081fddda13b07193de8Robert Shih if (!mHasMetadata) { 8400852843d304006e3ab333081fddda13b07193de8Robert Shih mHasMetadata = true; 8410852843d304006e3ab333081fddda13b07193de8Robert Shih sp<AMessage> notify = mNotify->dup(); 8420852843d304006e3ab333081fddda13b07193de8Robert Shih notify->setInt32("what", kWhatMetadataDetected); 8430852843d304006e3ab333081fddda13b07193de8Robert Shih notify->post(); 8440852843d304006e3ab333081fddda13b07193de8Robert Shih } 8450852843d304006e3ab333081fddda13b07193de8Robert Shih break; 8460852843d304006e3ab333081fddda13b07193de8Robert Shih } 8470852843d304006e3ab333081fddda13b07193de8Robert Shih 84814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber default: 84914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber TRESPASS(); 85014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 85114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 85214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 85314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 85414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 855dcb89b3b505522efde173c105a851c412f947178Chong Zhang case kWhatChangeConfiguration: 856dcb89b3b505522efde173c105a851c412f947178Chong Zhang { 857dcb89b3b505522efde173c105a851c412f947178Chong Zhang onChangeConfiguration(msg); 858dcb89b3b505522efde173c105a851c412f947178Chong Zhang break; 859dcb89b3b505522efde173c105a851c412f947178Chong Zhang } 860dcb89b3b505522efde173c105a851c412f947178Chong Zhang 86114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case kWhatChangeConfiguration2: 86214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 86314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber onChangeConfiguration2(msg); 86414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 86514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 86614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 86714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case kWhatChangeConfiguration3: 86814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 86914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber onChangeConfiguration3(msg); 87014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 87114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 87214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 873964adb17885185808398507d2de88665fe193ee2Chong Zhang case kWhatPollBuffering: 8740ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih { 875964adb17885185808398507d2de88665fe193ee2Chong Zhang int32_t generation; 876964adb17885185808398507d2de88665fe193ee2Chong Zhang CHECK(msg->findInt32("generation", &generation)); 877964adb17885185808398507d2de88665fe193ee2Chong Zhang if (generation == mPollBufferingGeneration) { 878964adb17885185808398507d2de88665fe193ee2Chong Zhang onPollBuffering(); 879964adb17885185808398507d2de88665fe193ee2Chong Zhang } 8800ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih break; 8810ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih } 8820ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih 883a44153c1a57202fb538659eb50706e60454d6273Andreas Huber default: 884a44153c1a57202fb538659eb50706e60454d6273Andreas Huber TRESPASS(); 885a44153c1a57202fb538659eb50706e60454d6273Andreas Huber break; 886a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 887a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 888a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 889a44153c1a57202fb538659eb50706e60454d6273Andreas Huber// static 890a44153c1a57202fb538659eb50706e60454d6273Andreas Huberint LiveSession::SortByBandwidth(const BandwidthItem *a, const BandwidthItem *b) { 891a44153c1a57202fb538659eb50706e60454d6273Andreas Huber if (a->mBandwidth < b->mBandwidth) { 892a44153c1a57202fb538659eb50706e60454d6273Andreas Huber return -1; 893a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } else if (a->mBandwidth == b->mBandwidth) { 894a44153c1a57202fb538659eb50706e60454d6273Andreas Huber return 0; 895a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 896a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 897a44153c1a57202fb538659eb50706e60454d6273Andreas Huber return 1; 898a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 899a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 9008ca002eedc747dd854b61cbe364b52c06869273fRobert Shih// static 9018ca002eedc747dd854b61cbe364b52c06869273fRobert ShihLiveSession::StreamType LiveSession::indexToType(int idx) { 9020852843d304006e3ab333081fddda13b07193de8Robert Shih CHECK(idx >= 0 && idx < kNumSources); 9038ca002eedc747dd854b61cbe364b52c06869273fRobert Shih return (StreamType)(1 << idx); 9048ca002eedc747dd854b61cbe364b52c06869273fRobert Shih} 9058ca002eedc747dd854b61cbe364b52c06869273fRobert Shih 906f69c996864844e8f669308af8412cede043062a2Robert Shih// static 907f69c996864844e8f669308af8412cede043062a2Robert Shihssize_t LiveSession::typeToIndex(int32_t type) { 908f69c996864844e8f669308af8412cede043062a2Robert Shih switch (type) { 909f69c996864844e8f669308af8412cede043062a2Robert Shih case STREAMTYPE_AUDIO: 910f69c996864844e8f669308af8412cede043062a2Robert Shih return 0; 911f69c996864844e8f669308af8412cede043062a2Robert Shih case STREAMTYPE_VIDEO: 912f69c996864844e8f669308af8412cede043062a2Robert Shih return 1; 913f69c996864844e8f669308af8412cede043062a2Robert Shih case STREAMTYPE_SUBTITLES: 914f69c996864844e8f669308af8412cede043062a2Robert Shih return 2; 9150852843d304006e3ab333081fddda13b07193de8Robert Shih case STREAMTYPE_METADATA: 9160852843d304006e3ab333081fddda13b07193de8Robert Shih return 3; 917f69c996864844e8f669308af8412cede043062a2Robert Shih default: 918f69c996864844e8f669308af8412cede043062a2Robert Shih return -1; 919f69c996864844e8f669308af8412cede043062a2Robert Shih }; 920f69c996864844e8f669308af8412cede043062a2Robert Shih return -1; 921f69c996864844e8f669308af8412cede043062a2Robert Shih} 922f69c996864844e8f669308af8412cede043062a2Robert Shih 923a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onConnect(const sp<AMessage> &msg) { 9245abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang CHECK(msg->findString("url", &mMasterURL)); 9255abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 9265abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // TODO currently we don't know if we are coming here from incognito mode 9275abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang ALOGI("onConnect %s", uriDebugString(mMasterURL).c_str()); 928a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 929ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber KeyedVector<String8, String8> *headers = NULL; 930ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber if (!msg->findPointer("headers", (void **)&headers)) { 931ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber mExtraHeaders.clear(); 932ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber } else { 933ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber mExtraHeaders = *headers; 934ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber 935ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber delete headers; 936ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber headers = NULL; 937ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber } 938ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber 939964adb17885185808398507d2de88665fe193ee2Chong Zhang // create looper for fetchers 940964adb17885185808398507d2de88665fe193ee2Chong Zhang if (mFetcherLooper == NULL) { 941964adb17885185808398507d2de88665fe193ee2Chong Zhang mFetcherLooper = new ALooper(); 942964adb17885185808398507d2de88665fe193ee2Chong Zhang 943964adb17885185808398507d2de88665fe193ee2Chong Zhang mFetcherLooper->setName("Fetcher"); 944964adb17885185808398507d2de88665fe193ee2Chong Zhang mFetcherLooper->start(false, false); 945964adb17885185808398507d2de88665fe193ee2Chong Zhang } 946964adb17885185808398507d2de88665fe193ee2Chong Zhang 9475abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // create fetcher to fetch the master playlist 9485abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang addFetcher(mMasterURL.c_str())->fetchPlaylistAsync(); 9495abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang} 9505abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 9515abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhangvoid LiveSession::onMasterPlaylistFetched(const sp<AMessage> &msg) { 9525abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang AString uri; 9535abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang CHECK(msg->findString("uri", &uri)); 9545abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang ssize_t index = mFetcherInfos.indexOfKey(uri); 9555abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang if (index < 0) { 9565abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang ALOGW("fetcher for master playlist is gone."); 9575abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang return; 9585abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } 9595abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 9605abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // no longer useful, remove 9615abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang mFetcherLooper->unregisterHandler(mFetcherInfos[index].mFetcher->id()); 9625abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang mFetcherInfos.removeItemsAt(index); 9635abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 9645abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang CHECK(msg->findObject("playlist", (sp<RefBase> *)&mPlaylist)); 9655abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang if (mPlaylist == NULL) { 9665abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang ALOGE("unable to fetch master playlist %s.", 9675abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang uriDebugString(mMasterURL).c_str()); 9685abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 9695abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang postPrepared(ERROR_IO); 9705abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang return; 9715abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } 97214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // We trust the content provider to make a reasonable choice of preferred 97314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // initial bandwidth by listing it first in the variant playlist. 97414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // At startup we really don't have a good estimate on the available 97514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // network bandwidth since we haven't tranferred any data yet. Once 97614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // we have we can make a better informed choice. 97714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber size_t initialBandwidth = 0; 97814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber size_t initialBandwidthIndex = 0; 97914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 980a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang int32_t maxWidth = 0; 981a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang int32_t maxHeight = 0; 982a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang 98314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (mPlaylist->isVariantPlaylist()) { 984d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang Vector<BandwidthItem> itemsWithVideo; 98514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber for (size_t i = 0; i < mPlaylist->size(); ++i) { 986a44153c1a57202fb538659eb50706e60454d6273Andreas Huber BandwidthItem item; 987a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 98814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber item.mPlaylistIndex = i; 98914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 990a44153c1a57202fb538659eb50706e60454d6273Andreas Huber sp<AMessage> meta; 99114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber AString uri; 99214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mPlaylist->itemAt(i, &uri, &meta); 993a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 994a44153c1a57202fb538659eb50706e60454d6273Andreas Huber CHECK(meta->findInt32("bandwidth", (int32_t *)&item.mBandwidth)); 995a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 996a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang int32_t width, height; 997a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang if (meta->findInt32("width", &width)) { 998a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang maxWidth = max(maxWidth, width); 999a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang } 1000a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang if (meta->findInt32("height", &height)) { 1001a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang maxHeight = max(maxHeight, height); 1002a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang } 1003a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang 1004a44153c1a57202fb538659eb50706e60454d6273Andreas Huber mBandwidthItems.push(item); 1005d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (mPlaylist->hasType(i, "video")) { 1006d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang itemsWithVideo.push(item); 1007d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang } 1008d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang } 1009d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // remove the audio-only variants if we have at least one with video 1010d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (!itemsWithVideo.empty() 1011d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang && itemsWithVideo.size() < mBandwidthItems.size()) { 1012d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang mBandwidthItems.clear(); 1013d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang for (size_t i = 0; i < itemsWithVideo.size(); ++i) { 1014d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang mBandwidthItems.push(itemsWithVideo[i]); 1015d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang } 1016a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1017a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1018a44153c1a57202fb538659eb50706e60454d6273Andreas Huber CHECK_GT(mBandwidthItems.size(), 0u); 1019d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang initialBandwidth = mBandwidthItems[0].mBandwidth; 1020a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1021a44153c1a57202fb538659eb50706e60454d6273Andreas Huber mBandwidthItems.sort(SortByBandwidth); 102214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 102314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber for (size_t i = 0; i < mBandwidthItems.size(); ++i) { 102414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (mBandwidthItems.itemAt(i).mBandwidth == initialBandwidth) { 102514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber initialBandwidthIndex = i; 102614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 102714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 102814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 102914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else { 103014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // dummy item. 103114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber BandwidthItem item; 103214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber item.mPlaylistIndex = 0; 103314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber item.mBandwidth = 0; 103414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mBandwidthItems.push(item); 1035a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1036a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1037a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang mMaxWidth = maxWidth > 0 ? maxWidth : mMaxWidth; 1038a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang mMaxHeight = maxHeight > 0 ? maxHeight : mMaxHeight; 1039a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang 1040309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mPlaylist->pickRandomMediaItems(); 1041dcb89b3b505522efde173c105a851c412f947178Chong Zhang changeConfiguration( 1042309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 0ll /* timeUs */, initialBandwidthIndex, false /* pickTrack */); 1043a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 1044a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 104514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::finishDisconnect() { 1046a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang ALOGV("finishDisconnect"); 1047a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 104814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // No reconfiguration is currently pending, make sure none will trigger 104914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // during disconnection either. 10501543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih cancelBandwidthSwitch(); 10511543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 1052964adb17885185808398507d2de88665fe193ee2Chong Zhang // cancel buffer polling 1053964adb17885185808398507d2de88665fe193ee2Chong Zhang cancelPollBuffering(); 10540ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih 10555abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // TRICKY: don't wait for all fetcher to be stopped when disconnecting 10565abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // 10575abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // Some fetchers might be stuck in connect/getSize at this point. These 10585abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // operations will eventually timeout (as we have a timeout set in 10595abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // MediaHTTPConnection), but we don't want to block the main UI thread 10605abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // until then. Here we just need to make sure we clear all references 10615abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // to the fetchers, so that when they finally exit from the blocking 10625abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // operation, they can be destructed. 10635abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // 10645abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // There is one very tricky point though. For this scheme to work, the 10655abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // fecther must hold a reference to LiveSession, so that LiveSession is 10665abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // destroyed after fetcher. Otherwise LiveSession would get stuck in its 10675abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // own destructor when it waits for mFetcherLooper to stop, which still 10685abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // blocks main UI thread. 106914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber for (size_t i = 0; i < mFetcherInfos.size(); ++i) { 107014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mFetcherInfos.valueAt(i).mFetcher->stopAsync(); 10715abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang mFetcherLooper->unregisterHandler( 10725abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang mFetcherInfos.valueAt(i).mFetcher->id()); 107314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 10745abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang mFetcherInfos.clear(); 107514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 107614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mPacketSources.valueFor(STREAMTYPE_AUDIO)->signalEOS(ERROR_END_OF_STREAM); 107714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mPacketSources.valueFor(STREAMTYPE_VIDEO)->signalEOS(ERROR_END_OF_STREAM); 107814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 107914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mPacketSources.valueFor( 108014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber STREAMTYPE_SUBTITLES)->signalEOS(ERROR_END_OF_STREAM); 108114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 108214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AMessage> response = new AMessage; 108314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber response->setInt32("err", OK); 108414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 108514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber response->postReply(mDisconnectReplyID); 1086c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang mDisconnectReplyID.clear(); 108714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 108814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 108914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubersp<PlaylistFetcher> LiveSession::addFetcher(const char *uri) { 109014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ssize_t index = mFetcherInfos.indexOfKey(uri); 109114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 109214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (index >= 0) { 109314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return NULL; 109414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 109514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 10961d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> notify = new AMessage(kWhatFetcherNotify, this); 109714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->setString("uri", uri); 10981543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih notify->setInt32("switchGeneration", mSwitchGeneration); 109914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 110014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber FetcherInfo info; 110125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang info.mFetcher = new PlaylistFetcher( 110225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang notify, this, uri, mCurBandwidthIndex, mSubtitleGeneration); 110314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber info.mDurationUs = -1ll; 11041543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih info.mToBeRemoved = false; 1105a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang info.mToBeResumed = false; 1106964adb17885185808398507d2de88665fe193ee2Chong Zhang mFetcherLooper->registerHandler(info.mFetcher); 110714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 110814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mFetcherInfos.add(uri, info); 110914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 111014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return info.mFetcher; 1111a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 1112a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1113b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe#if 0 1114a44153c1a57202fb538659eb50706e60454d6273Andreas Huberstatic double uniformRand() { 1115a44153c1a57202fb538659eb50706e60454d6273Andreas Huber return (double)rand() / RAND_MAX; 1116a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 1117b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe#endif 1118a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 11190852843d304006e3ab333081fddda13b07193de8Robert Shihbool LiveSession::UriIsSameAsIndex(const AString &uri, int32_t i, bool newUri) { 11200852843d304006e3ab333081fddda13b07193de8Robert Shih ALOGI("[timed_id3] i %d UriIsSameAsIndex newUri %s, %s", i, 11210852843d304006e3ab333081fddda13b07193de8Robert Shih newUri ? "true" : "false", 11220852843d304006e3ab333081fddda13b07193de8Robert Shih newUri ? mStreams[i].mNewUri.c_str() : mStreams[i].mUri.c_str()); 11230852843d304006e3ab333081fddda13b07193de8Robert Shih return i >= 0 11240852843d304006e3ab333081fddda13b07193de8Robert Shih && ((!newUri && uri == mStreams[i].mUri) 11250852843d304006e3ab333081fddda13b07193de8Robert Shih || (newUri && uri == mStreams[i].mNewUri)); 11260852843d304006e3ab333081fddda13b07193de8Robert Shih} 11270852843d304006e3ab333081fddda13b07193de8Robert Shih 11280852843d304006e3ab333081fddda13b07193de8Robert Shihsp<AnotherPacketSource> LiveSession::getPacketSourceForStreamIndex( 11290852843d304006e3ab333081fddda13b07193de8Robert Shih size_t trackIndex, bool newUri) { 11300852843d304006e3ab333081fddda13b07193de8Robert Shih StreamType type = indexToType(trackIndex); 11310852843d304006e3ab333081fddda13b07193de8Robert Shih sp<AnotherPacketSource> source = NULL; 11320852843d304006e3ab333081fddda13b07193de8Robert Shih if (newUri) { 11330852843d304006e3ab333081fddda13b07193de8Robert Shih source = mPacketSources2.valueFor(type); 11340852843d304006e3ab333081fddda13b07193de8Robert Shih source->clear(); 11350852843d304006e3ab333081fddda13b07193de8Robert Shih } else { 11360852843d304006e3ab333081fddda13b07193de8Robert Shih source = mPacketSources.valueFor(type); 11370852843d304006e3ab333081fddda13b07193de8Robert Shih }; 11380852843d304006e3ab333081fddda13b07193de8Robert Shih return source; 11390852843d304006e3ab333081fddda13b07193de8Robert Shih} 11400852843d304006e3ab333081fddda13b07193de8Robert Shih 11410852843d304006e3ab333081fddda13b07193de8Robert Shihsp<AnotherPacketSource> LiveSession::getMetadataSource( 11420852843d304006e3ab333081fddda13b07193de8Robert Shih sp<AnotherPacketSource> sources[kNumSources], uint32_t streamMask, bool newUri) { 11430852843d304006e3ab333081fddda13b07193de8Robert Shih // todo: One case where the following strategy can fail is when audio and video 11440852843d304006e3ab333081fddda13b07193de8Robert Shih // are in separate playlists, both are transport streams, and the metadata 11450852843d304006e3ab333081fddda13b07193de8Robert Shih // is actually contained in the audio stream. 11460852843d304006e3ab333081fddda13b07193de8Robert Shih ALOGV("[timed_id3] getMetadataSourceForUri streamMask %x newUri %s", 11470852843d304006e3ab333081fddda13b07193de8Robert Shih streamMask, newUri ? "true" : "false"); 11480852843d304006e3ab333081fddda13b07193de8Robert Shih 11490852843d304006e3ab333081fddda13b07193de8Robert Shih if ((sources[kVideoIndex] != NULL) // video fetcher; or ... 11500852843d304006e3ab333081fddda13b07193de8Robert Shih || (!(streamMask & STREAMTYPE_VIDEO) && sources[kAudioIndex] != NULL)) { 11510852843d304006e3ab333081fddda13b07193de8Robert Shih // ... audio fetcher for audio only variant 11520852843d304006e3ab333081fddda13b07193de8Robert Shih return getPacketSourceForStreamIndex(kMetaDataIndex, newUri); 11530852843d304006e3ab333081fddda13b07193de8Robert Shih } 11540852843d304006e3ab333081fddda13b07193de8Robert Shih 11550852843d304006e3ab333081fddda13b07193de8Robert Shih return NULL; 11560852843d304006e3ab333081fddda13b07193de8Robert Shih} 11570852843d304006e3ab333081fddda13b07193de8Robert Shih 11587c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangbool LiveSession::resumeFetcher( 11597c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang const AString &uri, uint32_t streamMask, int64_t timeUs, bool newUri) { 11607c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ssize_t index = mFetcherInfos.indexOfKey(uri); 11617c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (index < 0) { 11627c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGE("did not find fetcher for uri: %s", uri.c_str()); 11637c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return false; 11647c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 11657c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 11667c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang bool resume = false; 11670852843d304006e3ab333081fddda13b07193de8Robert Shih sp<AnotherPacketSource> sources[kNumSources]; 11687c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang for (size_t i = 0; i < kMaxStreams; ++i) { 11690852843d304006e3ab333081fddda13b07193de8Robert Shih if ((streamMask & indexToType(i)) && UriIsSameAsIndex(uri, i, newUri)) { 11707c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang resume = true; 11710852843d304006e3ab333081fddda13b07193de8Robert Shih sources[i] = getPacketSourceForStreamIndex(i, newUri); 11727c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 11737c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 11747c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 11757c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (resume) { 117625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang sp<PlaylistFetcher> &fetcher = mFetcherInfos.editValueAt(index).mFetcher; 11777c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang SeekMode seekMode = newUri ? kSeekModeNextSample : kSeekModeExactPosition; 117825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 117925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("resuming fetcher-%d, timeUs=%lld, seekMode=%d", 118025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang fetcher->getFetcherID(), (long long)timeUs, seekMode); 118125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 118225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang fetcher->startAsync( 11837c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sources[kAudioIndex], 11847c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sources[kVideoIndex], 11857c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sources[kSubtitleIndex], 11860852843d304006e3ab333081fddda13b07193de8Robert Shih getMetadataSource(sources, streamMask, newUri), 11877c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang timeUs, -1, -1, seekMode); 11887c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 11897c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 11907c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return resume; 11917c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang} 11927c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 1193a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhangfloat LiveSession::getAbortThreshold( 1194a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang ssize_t currentBWIndex, ssize_t targetBWIndex) const { 1195a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang float abortThreshold = -1.0f; 1196a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (currentBWIndex > 0 && targetBWIndex < currentBWIndex) { 1197a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang /* 1198a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang If we're switching down, we need to decide whether to 1199a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1200a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1) finish last segment of high-bandwidth variant, or 1201a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 2) abort last segment of high-bandwidth variant, and fetch an 1202a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang overlapping portion from low-bandwidth variant. 1203a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1204a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang Here we try to maximize the amount of buffer left when the 1205a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang switch point is met. Given the following parameters: 1206a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1207a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang B: our current buffering level in seconds 1208a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang T: target duration in seconds 1209a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang X: sample duration in seconds remain to fetch in last segment 1210a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang bw0: bandwidth of old variant (as specified in playlist) 1211a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang bw1: bandwidth of new variant (as specified in playlist) 1212a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang bw: measured bandwidth available 1213a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1214a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang If we choose 1), when switch happens at the end of current 1215a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang segment, our buffering will be 1216a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang B + X - X * bw0 / bw 1217a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1218a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang If we choose 2), when switch happens where we aborted current 1219a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang segment, our buffering will be 1220a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang B - (T - X) * bw1 / bw 1221a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1222a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang We should only choose 1) if 1223a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang X/T < bw1 / (bw1 + bw0 - bw) 1224a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang */ 1225a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 12267c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // Taking the measured current bandwidth at 50% face value only, 12277c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // as our bandwidth estimation is a lagging indicator. Being 12287c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // conservative on this, we prefer switching to lower bandwidth 12297c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // unless we're really confident finishing up the last segment 12307c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // of higher bandwidth will be fast. 1231a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang CHECK(mLastBandwidthBps >= 0); 1232a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang abortThreshold = 1233a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang (float)mBandwidthItems.itemAt(targetBWIndex).mBandwidth 1234a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang / ((float)mBandwidthItems.itemAt(targetBWIndex).mBandwidth 1235a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang + (float)mBandwidthItems.itemAt(currentBWIndex).mBandwidth 12367c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang - (float)mLastBandwidthBps * 0.5f); 1237a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (abortThreshold < 0.0f) { 1238a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang abortThreshold = -1.0f; // do not abort 1239a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 1240a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang ALOGV("Switching Down: bps %ld => %ld, measured %d, abort ratio %.2f", 1241a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mBandwidthItems.itemAt(currentBWIndex).mBandwidth, 1242a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mBandwidthItems.itemAt(targetBWIndex).mBandwidth, 1243a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mLastBandwidthBps, 1244a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang abortThreshold); 1245a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 1246a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang return abortThreshold; 1247a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang} 1248a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1249538b6d22a3578c0201d48f8548289aa254d81484Chong Zhangvoid LiveSession::addBandwidthMeasurement(size_t numBytes, int64_t delayUs) { 1250538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mBandwidthEstimator->addBandwidthMeasurement(numBytes, delayUs); 1251538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang} 1252538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 1253538b6d22a3578c0201d48f8548289aa254d81484Chong Zhangsize_t LiveSession::getBandwidthIndex(int32_t bandwidthBps) { 1254538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang if (mBandwidthItems.size() < 2) { 1255538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang // shouldn't be here if we only have 1 bandwidth, check 1256538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang // logic to get rid of redundant bandwidth polling 1257538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang ALOGW("getBandwidthIndex() called for single bandwidth playlist!"); 1258a44153c1a57202fb538659eb50706e60454d6273Andreas Huber return 0; 1259a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1260a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1261a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#if 1 1262a44153c1a57202fb538659eb50706e60454d6273Andreas Huber char value[PROPERTY_VALUE_MAX]; 1263673158582c9589cee1d5e4d7c79622609938b8f8Andreas Huber ssize_t index = -1; 126414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (property_get("media.httplive.bw-index", value, NULL)) { 1265a44153c1a57202fb538659eb50706e60454d6273Andreas Huber char *end; 126614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber index = strtol(value, &end, 10); 126714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(end > value && *end == '\0'); 126814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 126914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (index >= 0 && (size_t)index >= mBandwidthItems.size()) { 127014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber index = mBandwidthItems.size() - 1; 1271a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1272a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1273a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 127414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (index < 0) { 127514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber char value[PROPERTY_VALUE_MAX]; 127614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (property_get("media.httplive.max-bw", value, NULL)) { 127714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber char *end; 127814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber long maxBw = strtoul(value, &end, 10); 127914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (end > value && *end == '\0') { 128014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (maxBw > 0 && bandwidthBps > maxBw) { 128114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGV("bandwidth capped to %ld bps", maxBw); 128214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber bandwidthBps = maxBw; 128314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 128414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 128514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 1286a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 128714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // Pick the highest bandwidth stream below or equal to estimated bandwidth. 128814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 128914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber index = mBandwidthItems.size() - 1; 129000598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih while (index > 0) { 1291538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang // be conservative (70%) to avoid overestimating and immediately 1292538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang // switching down again. 1293538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang size_t adjustedBandwidthBps = bandwidthBps * 7 / 10; 129400598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih if (mBandwidthItems.itemAt(index).mBandwidth <= adjustedBandwidthBps) { 129500598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih break; 129600598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih } 129714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber --index; 129814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 1299a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1300a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0 1301a44153c1a57202fb538659eb50706e60454d6273Andreas Huber // Change bandwidth at random() 1302a44153c1a57202fb538659eb50706e60454d6273Andreas Huber size_t index = uniformRand() * mBandwidthItems.size(); 1303a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0 1304a44153c1a57202fb538659eb50706e60454d6273Andreas Huber // There's a 50% chance to stay on the current bandwidth and 1305a44153c1a57202fb538659eb50706e60454d6273Andreas Huber // a 50% chance to switch to the next higher bandwidth (wrapping around 1306a44153c1a57202fb538659eb50706e60454d6273Andreas Huber // to lowest) 1307a44153c1a57202fb538659eb50706e60454d6273Andreas Huber const size_t kMinIndex = 0; 1308a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1309309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih static ssize_t mCurBandwidthIndex = -1; 131014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 1311a44153c1a57202fb538659eb50706e60454d6273Andreas Huber size_t index; 1312309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (mCurBandwidthIndex < 0) { 1313a44153c1a57202fb538659eb50706e60454d6273Andreas Huber index = kMinIndex; 1314a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } else if (uniformRand() < 0.5) { 1315309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih index = (size_t)mCurBandwidthIndex; 1316a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } else { 1317309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih index = mCurBandwidthIndex + 1; 1318a44153c1a57202fb538659eb50706e60454d6273Andreas Huber if (index == mBandwidthItems.size()) { 1319a44153c1a57202fb538659eb50706e60454d6273Andreas Huber index = kMinIndex; 1320a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1321a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1322309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mCurBandwidthIndex = index; 1323a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0 1324a44153c1a57202fb538659eb50706e60454d6273Andreas Huber // Pick the highest bandwidth stream below or equal to 1.2 Mbit/sec 1325a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1326a44153c1a57202fb538659eb50706e60454d6273Andreas Huber size_t index = mBandwidthItems.size() - 1; 1327a44153c1a57202fb538659eb50706e60454d6273Andreas Huber while (index > 0 && mBandwidthItems.itemAt(index).mBandwidth > 1200000) { 1328a44153c1a57202fb538659eb50706e60454d6273Andreas Huber --index; 1329a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 133014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#elif 1 133114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber char value[PROPERTY_VALUE_MAX]; 133214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber size_t index; 133314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (property_get("media.httplive.bw-index", value, NULL)) { 133414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber char *end; 133514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber index = strtoul(value, &end, 10); 133614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(end > value && *end == '\0'); 133714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 133814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (index >= mBandwidthItems.size()) { 133914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber index = mBandwidthItems.size() - 1; 134014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 134114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else { 134214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber index = 0; 134314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 1344a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#else 1345a44153c1a57202fb538659eb50706e60454d6273Andreas Huber size_t index = mBandwidthItems.size() - 1; // Highest bandwidth stream 1346a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#endif 1347a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 134814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK_GE(index, 0); 134914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 1350a44153c1a57202fb538659eb50706e60454d6273Andreas Huber return index; 1351a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 1352a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1353d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong ZhangHLSTime LiveSession::latestMediaSegmentStartTime() const { 1354d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang HLSTime audioTime(mPacketSources.valueFor( 1355d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang STREAMTYPE_AUDIO)->getLatestDequeuedMeta()); 1356b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih 1357d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang HLSTime videoTime(mPacketSources.valueFor( 1358d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang STREAMTYPE_VIDEO)->getLatestDequeuedMeta()); 1359b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih 1360d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang return audioTime < videoTime ? videoTime : audioTime; 1361b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih} 1362b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih 1363a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnarvoid LiveSession::onSeek(const sp<AMessage> &msg) { 136414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int64_t timeUs; 136514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->findInt64("timeUs", &timeUs)); 1366a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar changeConfiguration(timeUs); 13677e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber} 13687e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber 136914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::getDuration(int64_t *durationUs) const { 1370895651b07fec30b0f9b0d2499599a179d95c9be4Wei Jia int64_t maxDurationUs = -1ll; 137114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber for (size_t i = 0; i < mFetcherInfos.size(); ++i) { 137214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int64_t fetcherDurationUs = mFetcherInfos.valueAt(i).mDurationUs; 1373b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber 1374895651b07fec30b0f9b0d2499599a179d95c9be4Wei Jia if (fetcherDurationUs > maxDurationUs) { 137514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber maxDurationUs = fetcherDurationUs; 1376a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1377a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1378a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 137914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber *durationUs = maxDurationUs; 1380a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 138114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return OK; 138214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 13830f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber 138414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberbool LiveSession::isSeekable() const { 138514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int64_t durationUs; 138614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return getDuration(&durationUs) == OK && durationUs >= 0; 138714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 13880f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber 138914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberbool LiveSession::hasDynamicDuration() const { 139014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return false; 139114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 13920f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber 1393404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhangsize_t LiveSession::getTrackCount() const { 13949d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih if (mPlaylist == NULL) { 13959d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih return 0; 13969d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih } else { 13970852843d304006e3ab333081fddda13b07193de8Robert Shih return mPlaylist->getTrackCount() + (mHasMetadata ? 1 : 0); 13989d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih } 1399404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang} 1400404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang 1401404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhangsp<AMessage> LiveSession::getTrackInfo(size_t trackIndex) const { 14029d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih if (mPlaylist == NULL) { 14039d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih return NULL; 14049d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih } else { 14050852843d304006e3ab333081fddda13b07193de8Robert Shih if (trackIndex == mPlaylist->getTrackCount() && mHasMetadata) { 14060852843d304006e3ab333081fddda13b07193de8Robert Shih sp<AMessage> format = new AMessage(); 14070852843d304006e3ab333081fddda13b07193de8Robert Shih format->setInt32("type", MEDIA_TRACK_TYPE_METADATA); 14080852843d304006e3ab333081fddda13b07193de8Robert Shih format->setString("language", "und"); 14090852843d304006e3ab333081fddda13b07193de8Robert Shih format->setString("mime", MEDIA_MIMETYPE_DATA_METADATA); 14100852843d304006e3ab333081fddda13b07193de8Robert Shih return format; 14110852843d304006e3ab333081fddda13b07193de8Robert Shih } 14129d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih return mPlaylist->getTrackInfo(trackIndex); 14139d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih } 1414dcb89b3b505522efde173c105a851c412f947178Chong Zhang} 1415dcb89b3b505522efde173c105a851c412f947178Chong Zhang 1416dcb89b3b505522efde173c105a851c412f947178Chong Zhangstatus_t LiveSession::selectTrack(size_t index, bool select) { 1417b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih if (mPlaylist == NULL) { 1418b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih return INVALID_OPERATION; 1419b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih } 1420b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih 142125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("selectTrack: index=%zu, select=%d, mSubtitleGen=%d++", 142225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang index, select, mSubtitleGeneration); 142325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 1424b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih ++mSubtitleGeneration; 1425dcb89b3b505522efde173c105a851c412f947178Chong Zhang status_t err = mPlaylist->selectTrack(index, select); 1426dcb89b3b505522efde173c105a851c412f947178Chong Zhang if (err == OK) { 14271d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> msg = new AMessage(kWhatChangeConfiguration, this); 1428309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih msg->setInt32("pickTrack", select); 1429309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih msg->post(); 1430dcb89b3b505522efde173c105a851c412f947178Chong Zhang } 1431dcb89b3b505522efde173c105a851c412f947178Chong Zhang return err; 1432dcb89b3b505522efde173c105a851c412f947178Chong Zhang} 1433dcb89b3b505522efde173c105a851c412f947178Chong Zhang 143489bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shihssize_t LiveSession::getSelectedTrack(media_track_type type) const { 143589bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih if (mPlaylist == NULL) { 143689bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih return -1; 143789bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih } else { 143889bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih return mPlaylist->getSelectedTrack(type); 143989bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih } 144089bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih} 144189bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih 1442dcb89b3b505522efde173c105a851c412f947178Chong Zhangvoid LiveSession::changeConfiguration( 14437c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang int64_t timeUs, ssize_t bandwidthIndex, bool pickTrack) { 144425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("changeConfiguration: timeUs=%lld us, bwIndex=%zd, pickTrack=%d", 144525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang (long long)timeUs, bandwidthIndex, pickTrack); 144625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 14471543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih cancelBandwidthSwitch(); 14481543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 144914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(!mReconfigurationInProgress); 145014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mReconfigurationInProgress = true; 14517c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (bandwidthIndex >= 0) { 14527c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mOrigBandwidthIndex = mCurBandwidthIndex; 14537c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mCurBandwidthIndex = bandwidthIndex; 14548464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang if (mOrigBandwidthIndex != mCurBandwidthIndex) { 14558464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang ALOGI("#### Starting Bandwidth Switch: %zd => %zd", 14568464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang mOrigBandwidthIndex, mCurBandwidthIndex); 14578464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang } 14587c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 14597c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang CHECK_LT(mCurBandwidthIndex, mBandwidthItems.size()); 14607c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang const BandwidthItem &item = mBandwidthItems.itemAt(mCurBandwidthIndex); 1461a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 14621543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih uint32_t streamMask = 0; // streams that should be fetched by the new fetcher 14631543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih uint32_t resumeMask = 0; // streams that should be fetched by the original fetcher 1464a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 14658ca002eedc747dd854b61cbe364b52c06869273fRobert Shih AString URIs[kMaxStreams]; 14668ca002eedc747dd854b61cbe364b52c06869273fRobert Shih for (size_t i = 0; i < kMaxStreams; ++i) { 14678ca002eedc747dd854b61cbe364b52c06869273fRobert Shih if (mPlaylist->getTypeURI(item.mPlaylistIndex, mStreams[i].mType, &URIs[i])) { 14688ca002eedc747dd854b61cbe364b52c06869273fRobert Shih streamMask |= indexToType(i); 14698ca002eedc747dd854b61cbe364b52c06869273fRobert Shih } 147014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 1471aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber 147214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // Step 1, stop and discard fetchers that are no longer needed. 147314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // Pause those that we'll reuse. 147414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber for (size_t i = 0; i < mFetcherInfos.size(); ++i) { 14757c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // skip fetchers that are marked mToBeRemoved, 14767c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // these are done and can't be reused 14777c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (mFetcherInfos[i].mToBeRemoved) { 14787c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang continue; 14797c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 14807c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 148114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber const AString &uri = mFetcherInfos.keyAt(i); 1482d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang sp<PlaylistFetcher> &fetcher = mFetcherInfos.editValueAt(i).mFetcher; 1483aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber 1484d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang bool discardFetcher = true, delayRemoval = false; 1485c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang for (size_t j = 0; j < kMaxStreams; ++j) { 1486c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang StreamType type = indexToType(j); 1487c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang if ((streamMask & type) && uri == URIs[j]) { 1488c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang resumeMask |= type; 1489c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang streamMask &= ~type; 1490c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang discardFetcher = false; 14916801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber } 149214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 1493d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // Delay fetcher removal if not picking tracks, AND old fetcher 1494d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // has stream mask that overlaps new variant. (Okay to discard 1495d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // old fetcher now, if completely no overlap.) 1496d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (discardFetcher && timeUs < 0ll && !pickTrack 1497d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang && (fetcher->getStreamTypeMask() & streamMask)) { 1498d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang discardFetcher = false; 1499d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang delayRemoval = true; 1500d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang } 1501a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 150214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (discardFetcher) { 150325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("discarding fetcher-%d", fetcher->getFetcherID()); 1504d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang fetcher->stopAsync(); 15056801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber } else { 15068a048338d9291b2db1b3a325fff58cb1aa69f04dChong Zhang float threshold = 0.0f; // default to pause after current block (47Kbytes) 15075abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang bool disconnect = false; 1508a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (timeUs >= 0ll) { 1509a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // seeking, no need to finish fetching 15105abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang disconnect = true; 1511d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang } else if (delayRemoval) { 1512a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // adapting, abort if remaining of current segment is over threshold 1513a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang threshold = getAbortThreshold( 15147c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mOrigBandwidthIndex, mCurBandwidthIndex); 1515a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 1516a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 151725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("pausing fetcher-%d, threshold=%.2f", 151825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang fetcher->getFetcherID(), threshold); 15195abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang fetcher->pauseAsync(threshold, disconnect); 15206801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber } 1521a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1522a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 15231543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih sp<AMessage> msg; 15241543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih if (timeUs < 0ll) { 1525309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih // skip onChangeConfiguration2 (decoder destruction) if not seeking. 15261d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar msg = new AMessage(kWhatChangeConfiguration3, this); 15271543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } else { 15281d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar msg = new AMessage(kWhatChangeConfiguration2, this); 15291543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 153014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber msg->setInt32("streamMask", streamMask); 15311543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih msg->setInt32("resumeMask", resumeMask); 1532309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih msg->setInt32("pickTrack", pickTrack); 153314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber msg->setInt64("timeUs", timeUs); 15348ca002eedc747dd854b61cbe364b52c06869273fRobert Shih for (size_t i = 0; i < kMaxStreams; ++i) { 1535309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if ((streamMask | resumeMask) & indexToType(i)) { 15368ca002eedc747dd854b61cbe364b52c06869273fRobert Shih msg->setString(mStreams[i].uriKey().c_str(), URIs[i].c_str()); 15378ca002eedc747dd854b61cbe364b52c06869273fRobert Shih } 15386e6b1cae2bac1b78205cefab8e4e9e9538982965Andreas Huber } 1539a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 154014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // Every time a fetcher acknowledges the stopAsync or pauseAsync request 154114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // we'll decrement mContinuationCounter, once it reaches zero, i.e. all 154214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // fetchers have completed their asynchronous operation, we'll post 154314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // mContinuation, which then is handled below in onChangeConfiguration2. 154414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mContinuationCounter = mFetcherInfos.size(); 154514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mContinuation = msg; 154688b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber 154714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (mContinuationCounter == 0) { 154814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber msg->post(); 154988b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber } 155014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 1551a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1552dcb89b3b505522efde173c105a851c412f947178Chong Zhangvoid LiveSession::onChangeConfiguration(const sp<AMessage> &msg) { 155325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("onChangeConfiguration"); 155425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 1555dcb89b3b505522efde173c105a851c412f947178Chong Zhang if (!mReconfigurationInProgress) { 15567c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang int32_t pickTrack = 0; 1557309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih msg->findInt32("pickTrack", &pickTrack); 15587c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang changeConfiguration(-1ll /* timeUs */, -1, pickTrack); 1559dcb89b3b505522efde173c105a851c412f947178Chong Zhang } else { 1560dcb89b3b505522efde173c105a851c412f947178Chong Zhang msg->post(1000000ll); // retry in 1 sec 1561dcb89b3b505522efde173c105a851c412f947178Chong Zhang } 1562dcb89b3b505522efde173c105a851c412f947178Chong Zhang} 1563dcb89b3b505522efde173c105a851c412f947178Chong Zhang 156414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::onChangeConfiguration2(const sp<AMessage> &msg) { 156525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("onChangeConfiguration2"); 156625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 156714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mContinuation.clear(); 1568bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber 156914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // All fetchers are either suspended or have been removed now. 1570bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber 1571964adb17885185808398507d2de88665fe193ee2Chong Zhang // If we're seeking, clear all packet sources before we report 1572964adb17885185808398507d2de88665fe193ee2Chong Zhang // seek complete, to prevent decoder from pulling stale data. 1573964adb17885185808398507d2de88665fe193ee2Chong Zhang int64_t timeUs; 1574964adb17885185808398507d2de88665fe193ee2Chong Zhang CHECK(msg->findInt64("timeUs", &timeUs)); 1575964adb17885185808398507d2de88665fe193ee2Chong Zhang 1576964adb17885185808398507d2de88665fe193ee2Chong Zhang if (timeUs >= 0) { 1577964adb17885185808398507d2de88665fe193ee2Chong Zhang mLastSeekTimeUs = timeUs; 15788464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang mLastDequeuedTimeUs = timeUs; 1579964adb17885185808398507d2de88665fe193ee2Chong Zhang 1580964adb17885185808398507d2de88665fe193ee2Chong Zhang for (size_t i = 0; i < mPacketSources.size(); i++) { 1581964adb17885185808398507d2de88665fe193ee2Chong Zhang mPacketSources.editValueAt(i)->clear(); 1582964adb17885185808398507d2de88665fe193ee2Chong Zhang } 1583964adb17885185808398507d2de88665fe193ee2Chong Zhang 15847c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang for (size_t i = 0; i < kMaxStreams; ++i) { 158581636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang mStreams[i].reset(); 15867c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 15877c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 1588964adb17885185808398507d2de88665fe193ee2Chong Zhang mDiscontinuityOffsetTimesUs.clear(); 1589964adb17885185808398507d2de88665fe193ee2Chong Zhang mDiscontinuityAbsStartTimesUs.clear(); 1590964adb17885185808398507d2de88665fe193ee2Chong Zhang 1591c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang if (mSeekReplyID != NULL) { 1592964adb17885185808398507d2de88665fe193ee2Chong Zhang CHECK(mSeekReply != NULL); 1593964adb17885185808398507d2de88665fe193ee2Chong Zhang mSeekReply->setInt32("err", OK); 1594964adb17885185808398507d2de88665fe193ee2Chong Zhang mSeekReply->postReply(mSeekReplyID); 1595c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang mSeekReplyID.clear(); 1596964adb17885185808398507d2de88665fe193ee2Chong Zhang mSeekReply.clear(); 1597964adb17885185808398507d2de88665fe193ee2Chong Zhang } 15987c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 15997c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // restart buffer polling after seek becauese previous 16007c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // buffering position is no longer valid. 16017c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang restartPollBuffering(); 1602964adb17885185808398507d2de88665fe193ee2Chong Zhang } 1603964adb17885185808398507d2de88665fe193ee2Chong Zhang 1604309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih uint32_t streamMask, resumeMask; 160514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->findInt32("streamMask", (int32_t *)&streamMask)); 1606309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih CHECK(msg->findInt32("resumeMask", (int32_t *)&resumeMask)); 1607309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 1608309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih streamMask |= resumeMask; 1609bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber 16108ca002eedc747dd854b61cbe364b52c06869273fRobert Shih AString URIs[kMaxStreams]; 16118ca002eedc747dd854b61cbe364b52c06869273fRobert Shih for (size_t i = 0; i < kMaxStreams; ++i) { 16128ca002eedc747dd854b61cbe364b52c06869273fRobert Shih if (streamMask & indexToType(i)) { 16138ca002eedc747dd854b61cbe364b52c06869273fRobert Shih const AString &uriKey = mStreams[i].uriKey(); 16148ca002eedc747dd854b61cbe364b52c06869273fRobert Shih CHECK(msg->findString(uriKey.c_str(), &URIs[i])); 16158ca002eedc747dd854b61cbe364b52c06869273fRobert Shih ALOGV("%s = '%s'", uriKey.c_str(), URIs[i].c_str()); 16168ca002eedc747dd854b61cbe364b52c06869273fRobert Shih } 161722fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber } 16183831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber 161914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber uint32_t changedMask = 0; 16208ca002eedc747dd854b61cbe364b52c06869273fRobert Shih for (size_t i = 0; i < kMaxStreams && i != kSubtitleIndex; ++i) { 1621c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // stream URI could change even if onChangeConfiguration2 is only 1622c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // used for seek. Seek could happen during a bw switch, in this 1623c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // case bw switch will be cancelled, but the seekTo position will 1624c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // fetch from the new URI. 1625c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang if ((mStreamMask & streamMask & indexToType(i)) 1626c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang && !mStreams[i].mUri.empty() 1627c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang && !(URIs[i] == mStreams[i].mUri)) { 16284604458dfe57b0e91a464aefafea50ae7b9876c1Chong Zhang ALOGV("stream %zu changed: oldURI %s, newURI %s", i, 1629c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang mStreams[i].mUri.c_str(), URIs[i].c_str()); 1630c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang sp<AnotherPacketSource> source = mPacketSources.valueFor(indexToType(i)); 16318464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang if (source->getLatestDequeuedMeta() != NULL) { 16328464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang source->queueDiscontinuity( 16338464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang ATSParser::DISCONTINUITY_FORMATCHANGE, NULL, true); 16348464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang } 1635c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang } 1636c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // Determine which decoders to shutdown on the player side, 1637c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // a decoder has to be shutdown if its streamtype was active 1638c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // before but now longer isn't. 1639c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang if ((mStreamMask & ~streamMask & indexToType(i))) { 16408ca002eedc747dd854b61cbe364b52c06869273fRobert Shih changedMask |= indexToType(i); 16418ca002eedc747dd854b61cbe364b52c06869273fRobert Shih } 1642b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber } 1643b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber 164414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (changedMask == 0) { 164514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // If nothing changed as far as the audio/video decoders 164614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // are concerned we can proceed. 164714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber onChangeConfiguration3(msg); 164814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return; 164914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 165043c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber 165114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // Something changed, inform the player which will shutdown the 165214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // corresponding decoders and will post the reply once that's done. 165314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // Handling the reply will continue executing below in 165414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // onChangeConfiguration3. 165514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AMessage> notify = mNotify->dup(); 165614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->setInt32("what", kWhatStreamsChanged); 165714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->setInt32("changedMask", changedMask); 165820f725ebcef13ded1b4b85c61c8a4b37cd030656Andreas Huber 165914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber msg->setWhat(kWhatChangeConfiguration3); 16601d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar msg->setTarget(this); 1661b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber 166214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->setMessage("reply", msg); 166314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->post(); 166414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 1665b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber 166614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::onChangeConfiguration3(const sp<AMessage> &msg) { 16671543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih mContinuation.clear(); 166814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // All remaining fetchers are still suspended, the player has shutdown 166914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // any decoders that needed it. 1670b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber 16711543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih uint32_t streamMask, resumeMask; 167214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->findInt32("streamMask", (int32_t *)&streamMask)); 16731543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih CHECK(msg->findInt32("resumeMask", (int32_t *)&resumeMask)); 1674a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1675d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang mNewStreamMask = streamMask | resumeMask; 1676d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang 167714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int64_t timeUs; 1678309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih int32_t pickTrack; 16791543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih bool switching = false; 168014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->findInt64("timeUs", &timeUs)); 1681309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih CHECK(msg->findInt32("pickTrack", &pickTrack)); 1682a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 168314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (timeUs < 0ll) { 1684309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (!pickTrack) { 1685d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // mSwapMask contains streams that are in both old and new variant, 1686d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // (in mNewStreamMask & mStreamMask) but with different URIs 1687d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // (not in resumeMask). 1688d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // For example, old variant has video and audio in two separate 1689d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // URIs, and new variant has only audio with unchanged URI. mSwapMask 1690d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // should be 0 as there is nothing to swap. We only need to stop video, 1691d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // and resume audio. 1692d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang mSwapMask = mNewStreamMask & mStreamMask & ~resumeMask; 1693d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang switching = (mSwapMask != 0); 1694309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 1695309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mRealTimeBaseUs = ALooper::GetNowUs() - mLastDequeuedTimeUs; 1696309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } else { 1697309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mRealTimeBaseUs = ALooper::GetNowUs() - timeUs; 169814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 1699a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 170025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("onChangeConfiguration3: timeUs=%lld, switching=%d, pickTrack=%d, " 170125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang "mStreamMask=0x%x, mNewStreamMask=0x%x, mSwapMask=0x%x", 170225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang (long long)timeUs, switching, pickTrack, 170325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang mStreamMask, mNewStreamMask, mSwapMask); 170425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 1705f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih for (size_t i = 0; i < kMaxStreams; ++i) { 1706f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih if (streamMask & indexToType(i)) { 1707f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih if (switching) { 1708f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih CHECK(msg->findString(mStreams[i].uriKey().c_str(), &mStreams[i].mNewUri)); 1709f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } else { 1710f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih CHECK(msg->findString(mStreams[i].uriKey().c_str(), &mStreams[i].mUri)); 1711f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 1712f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 1713f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 1714f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih 17151543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih // Of all existing fetchers: 17161543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih // * Resume fetchers that are still needed and assign them original packet sources. 17171543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih // * Mark otherwise unneeded fetchers for removal. 17181543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih ALOGV("resuming fetchers for mask 0x%08x", resumeMask); 171914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber for (size_t i = 0; i < mFetcherInfos.size(); ++i) { 172014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber const AString &uri = mFetcherInfos.keyAt(i); 17217c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (!resumeFetcher(uri, resumeMask, timeUs)) { 172225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("marking fetcher-%d to be removed", 172325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang mFetcherInfos[i].mFetcher->getFetcherID()); 172425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 17257c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mFetcherInfos.editValueAt(i).mToBeRemoved = true; 17261543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 1727a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1728a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 172914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // streamMask now only contains the types that need a new fetcher created. 173014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (streamMask != 0) { 173114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGV("creating new fetchers for mask 0x%08x", streamMask); 1732a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1733a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 17341543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih // Find out when the original fetchers have buffered up to and start the new fetchers 17351543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih // at a later timestamp. 17368ca002eedc747dd854b61cbe364b52c06869273fRobert Shih for (size_t i = 0; i < kMaxStreams; i++) { 17378ca002eedc747dd854b61cbe364b52c06869273fRobert Shih if (!(indexToType(i) & streamMask)) { 17388ca002eedc747dd854b61cbe364b52c06869273fRobert Shih continue; 17398ca002eedc747dd854b61cbe364b52c06869273fRobert Shih } 17401156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 174114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber AString uri; 1742f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih uri = switching ? mStreams[i].mNewUri : mStreams[i].mUri; 17439b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber 174414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<PlaylistFetcher> fetcher = addFetcher(uri.c_str()); 174514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(fetcher != NULL); 1746a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1747d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang HLSTime startTime; 1748a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang SeekMode seekMode = kSeekModeExactPosition; 17490852843d304006e3ab333081fddda13b07193de8Robert Shih sp<AnotherPacketSource> sources[kNumSources]; 17501543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 1751d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (i == kSubtitleIndex || (!pickTrack && !switching)) { 1752d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang startTime = latestMediaSegmentStartTime(); 1753b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih } 1754b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih 17558ca002eedc747dd854b61cbe364b52c06869273fRobert Shih // TRICKY: looping from i as earlier streams are already removed from streamMask 17568ca002eedc747dd854b61cbe364b52c06869273fRobert Shih for (size_t j = i; j < kMaxStreams; ++j) { 1757f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih const AString &streamUri = switching ? mStreams[j].mNewUri : mStreams[j].mUri; 1758f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih if ((streamMask & indexToType(j)) && uri == streamUri) { 17598ca002eedc747dd854b61cbe364b52c06869273fRobert Shih sources[j] = mPacketSources.valueFor(indexToType(j)); 17601543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 1761309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (timeUs >= 0) { 1762d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang startTime.mTimeUs = timeUs; 17631543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } else { 1764309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih int32_t type; 1765309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih sp<AMessage> meta; 1766d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (!switching) { 1767d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // selecting, or adapting but no swap required 1768309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih meta = sources[j]->getLatestDequeuedMeta(); 1769309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } else { 1770d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // adapting and swap required 1771309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih meta = sources[j]->getLatestEnqueuedMeta(); 17727c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (meta != NULL && mCurBandwidthIndex > mOrigBandwidthIndex) { 17737c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // switching up 17747c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang meta = sources[j]->getMetaAfterLastDequeued(mUpSwitchMargin); 17757c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 1776309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 17771543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 17780852843d304006e3ab333081fddda13b07193de8Robert Shih if ((j == kAudioIndex || j == kVideoIndex) 17790852843d304006e3ab333081fddda13b07193de8Robert Shih && meta != NULL && !meta->findInt32("discontinuity", &type)) { 1780d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang HLSTime tmpTime(meta); 1781d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (startTime < tmpTime) { 1782d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang startTime = tmpTime; 17831543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 17841543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 17851543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 1786d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (!switching) { 1787d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // selecting, or adapting but no swap required 1788309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih sources[j]->clear(); 1789309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (j == kSubtitleIndex) { 1790309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih break; 1791309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 1792964adb17885185808398507d2de88665fe193ee2Chong Zhang 17934604458dfe57b0e91a464aefafea50ae7b9876c1Chong Zhang ALOGV("stream[%zu]: queue format change", j); 1794964adb17885185808398507d2de88665fe193ee2Chong Zhang sources[j]->queueDiscontinuity( 1795a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang ATSParser::DISCONTINUITY_FORMAT_ONLY, NULL, true); 1796309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } else { 1797d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // switching, queue discontinuities after resume 1798309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih sources[j] = mPacketSources2.valueFor(indexToType(j)); 1799309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih sources[j]->clear(); 1800a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // the new fetcher might be providing streams that used to be 1801a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // provided by two different fetchers, if one of the fetcher 1802a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // paused in the middle while the other somehow paused in next 1803a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // seg, we have to start from next seg. 1804a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (seekMode < mStreams[j].mSeekMode) { 1805a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang seekMode = mStreams[j].mSeekMode; 1806309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 18071543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 18081543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 1809a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 18108ca002eedc747dd854b61cbe364b52c06869273fRobert Shih streamMask &= ~indexToType(j); 18118ca002eedc747dd854b61cbe364b52c06869273fRobert Shih } 1812a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 181314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 181425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("[fetcher-%d] startAsync: startTimeUs %lld mLastSeekTimeUs %lld " 181525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang "segmentStartTimeUs %lld seekMode %d", 181625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang fetcher->getFetcherID(), 181725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang (long long)startTime.mTimeUs, 181825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang (long long)mLastSeekTimeUs, 1819978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang (long long)startTime.getSegmentTimeUs(), 182025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang seekMode); 182125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 1822d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // Set the target segment start time to the middle point of the 1823d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // segment where the last sample was. 1824d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // This gives a better guess if segments of the two variants are not 1825d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // perfectly aligned. (If the corresponding segment in new variant 1826d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // starts slightly later than that in the old variant, we still want 1827d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // to pick that segment, not the one before) 18288ca002eedc747dd854b61cbe364b52c06869273fRobert Shih fetcher->startAsync( 18298ca002eedc747dd854b61cbe364b52c06869273fRobert Shih sources[kAudioIndex], 18308ca002eedc747dd854b61cbe364b52c06869273fRobert Shih sources[kVideoIndex], 18318ca002eedc747dd854b61cbe364b52c06869273fRobert Shih sources[kSubtitleIndex], 18320852843d304006e3ab333081fddda13b07193de8Robert Shih getMetadataSource(sources, mNewStreamMask, switching), 1833d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang startTime.mTimeUs < 0 ? mLastSeekTimeUs : startTime.mTimeUs, 1834978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang startTime.getSegmentTimeUs(), 1835d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang startTime.mSeq, 1836a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang seekMode); 1837a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1838a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 183914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // All fetchers have now been started, the configuration change 184014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // has completed. 1841a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 184214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mReconfigurationInProgress = false; 18431543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih if (switching) { 18441543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih mSwitchInProgress = true; 18451543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } else { 18461543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih mStreamMask = mNewStreamMask; 18478464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang if (mOrigBandwidthIndex != mCurBandwidthIndex) { 18488464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang ALOGV("#### Finished Bandwidth Switch Early: %zd => %zd", 18498464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang mOrigBandwidthIndex, mCurBandwidthIndex); 18508464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang mOrigBandwidthIndex = mCurBandwidthIndex; 18518464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang } 18521543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 1853a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 185425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("onChangeConfiguration3: mSwitchInProgress %d, mStreamMask 0x%x", 185525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang mSwitchInProgress, mStreamMask); 185625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 1857c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang if (mDisconnectReplyID != NULL) { 185814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber finishDisconnect(); 1859a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 186014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 1861a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1862a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhangvoid LiveSession::swapPacketSource(StreamType stream) { 186325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("[%s] swapPacketSource", getNameForStream(stream)); 1864a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1865a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // transfer packets from source2 to source 1866a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang sp<AnotherPacketSource> &aps = mPacketSources.editValueFor(stream); 1867a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang sp<AnotherPacketSource> &aps2 = mPacketSources2.editValueFor(stream); 1868a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1869a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // queue discontinuity in mPacketSource 1870a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang aps->queueDiscontinuity(ATSParser::DISCONTINUITY_FORMAT_ONLY, NULL, false); 1871a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1872a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // queue packets in mPacketSource2 to mPacketSource 1873a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang status_t finalResult = OK; 1874a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang sp<ABuffer> accessUnit; 1875a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang while (aps2->hasBufferAvailable(&finalResult) && finalResult == OK && 1876a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang OK == aps2->dequeueAccessUnit(&accessUnit)) { 1877a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang aps->queueAccessUnit(accessUnit); 1878a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 1879a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang aps2->clear(); 1880a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang} 1881a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 18827c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::tryToFinishBandwidthSwitch(const AString &oldUri) { 1883a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (!mSwitchInProgress) { 1884a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang return; 1885a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 1886a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 18877c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ssize_t index = mFetcherInfos.indexOfKey(oldUri); 1888a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (index < 0 || !mFetcherInfos[index].mToBeRemoved) { 18891543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih return; 18901543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 18911543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 1892a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // Swap packet source of streams provided by old variant 1893a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang for (size_t idx = 0; idx < kMaxStreams; idx++) { 18947c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang StreamType stream = indexToType(idx); 18957c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if ((mSwapMask & stream) && (oldUri == mStreams[idx].mUri)) { 1896a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang swapPacketSource(stream); 1897a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1898a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if ((mNewStreamMask & stream) && mStreams[idx].mNewUri.empty()) { 1899a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang ALOGW("swapping stream type %d %s to empty stream", 1900a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang stream, mStreams[idx].mUri.c_str()); 1901a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 1902a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mStreams[idx].mUri = mStreams[idx].mNewUri; 1903a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mStreams[idx].mNewUri.clear(); 1904a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1905a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mSwapMask &= ~stream; 1906a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 1907f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 1908f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih 19097c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mFetcherInfos.editValueAt(index).mFetcher->stopAsync(false /* clear */); 1910a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 191125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("tryToFinishBandwidthSwitch: mSwapMask=0x%x", mSwapMask); 1912309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (mSwapMask != 0) { 19131543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih return; 19141543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 19151543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 19161543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih // Check if new variant contains extra streams. 19171543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih uint32_t extraStreams = mNewStreamMask & (~mStreamMask); 19181543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih while (extraStreams) { 1919a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang StreamType stream = (StreamType) (extraStreams & ~(extraStreams - 1)); 1920a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang extraStreams &= ~stream; 1921a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1922a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang swapPacketSource(stream); 1923f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih 1924a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang ssize_t idx = typeToIndex(stream); 1925f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih CHECK(idx >= 0); 1926f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih if (mStreams[idx].mNewUri.empty()) { 1927f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih ALOGW("swapping extra stream type %d %s to empty stream", 1928a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang stream, mStreams[idx].mUri.c_str()); 1929f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 1930f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih mStreams[idx].mUri = mStreams[idx].mNewUri; 1931f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih mStreams[idx].mNewUri.clear(); 19321543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 19331543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 1934a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // Restart new fetcher (it was paused after the first 47k block) 1935a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // and let it fetch into mPacketSources (not mPacketSources2) 1936a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang for (size_t i = 0; i < mFetcherInfos.size(); ++i) { 1937a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang FetcherInfo &info = mFetcherInfos.editValueAt(i); 1938a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (info.mToBeResumed) { 19397c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang resumeFetcher(mFetcherInfos.keyAt(i), mNewStreamMask); 1940a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang info.mToBeResumed = false; 1941a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 1942a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 1943a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 19447c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGI("#### Finished Bandwidth Switch: %zd => %zd", 19457c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mOrigBandwidthIndex, mCurBandwidthIndex); 19467c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 1947a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mStreamMask = mNewStreamMask; 1948a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mSwitchInProgress = false; 19497c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mOrigBandwidthIndex = mCurBandwidthIndex; 1950a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 19517c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang restartPollBuffering(); 19521543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih} 19531543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 1954964adb17885185808398507d2de88665fe193ee2Chong Zhangvoid LiveSession::schedulePollBuffering() { 1955964adb17885185808398507d2de88665fe193ee2Chong Zhang sp<AMessage> msg = new AMessage(kWhatPollBuffering, this); 1956964adb17885185808398507d2de88665fe193ee2Chong Zhang msg->setInt32("generation", mPollBufferingGeneration); 1957964adb17885185808398507d2de88665fe193ee2Chong Zhang msg->post(1000000ll); 1958964adb17885185808398507d2de88665fe193ee2Chong Zhang} 1959678bcdc852dd8f801f5c46fdc85db587b721d83dApurupa Pattapu 1960964adb17885185808398507d2de88665fe193ee2Chong Zhangvoid LiveSession::cancelPollBuffering() { 1961964adb17885185808398507d2de88665fe193ee2Chong Zhang ++mPollBufferingGeneration; 19627c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mPrevBufferPercentage = -1; 19637c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang} 19647c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 19657c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::restartPollBuffering() { 19667c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang cancelPollBuffering(); 19677c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang onPollBuffering(); 1968964adb17885185808398507d2de88665fe193ee2Chong Zhang} 19690ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih 1970964adb17885185808398507d2de88665fe193ee2Chong Zhangvoid LiveSession::onPollBuffering() { 1971964adb17885185808398507d2de88665fe193ee2Chong Zhang ALOGV("onPollBuffering: mSwitchInProgress %d, mReconfigurationInProgress %d, " 1972a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang "mInPreparationPhase %d, mCurBandwidthIndex %zd, mStreamMask 0x%x", 1973964adb17885185808398507d2de88665fe193ee2Chong Zhang mSwitchInProgress, mReconfigurationInProgress, 1974538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mInPreparationPhase, mCurBandwidthIndex, mStreamMask); 19750ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih 19767c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang bool underflow, ready, down, up; 19777c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (checkBuffering(underflow, ready, down, up)) { 19788464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang if (mInPreparationPhase) { 19798464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang // Allow down switch even if we're still preparing. 19808464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang // 19818464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang // Some streams have a high bandwidth index as default, 19828464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang // when bandwidth is low, it takes a long time to buffer 19838464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang // to ready mark, then it immediately pauses after start 19848464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang // as we have to do a down switch. It's better experience 19858464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang // to restart from a lower index, if we detect low bw. 19868464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang if (!switchBandwidthIfNeeded(false /* up */, down) && ready) { 19878464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang postPrepared(OK); 19888464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang } 19890ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih } 19900ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih 1991538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang if (!mInPreparationPhase) { 19927c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (ready) { 19937c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang stopBufferingIfNecessary(); 19947c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } else if (underflow) { 19957c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang startBufferingIfNecessary(); 19967c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 19977c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang switchBandwidthIfNeeded(up, down); 19988464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang } 19990ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih } 20000ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih 2001964adb17885185808398507d2de88665fe193ee2Chong Zhang schedulePollBuffering(); 20020ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih} 20030ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih 20047c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::cancelBandwidthSwitch(bool resume) { 20057c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGV("cancelBandwidthSwitch: mSwitchGen(%d)++, orig %zd, cur %zd", 20067c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mSwitchGeneration, mOrigBandwidthIndex, mCurBandwidthIndex); 20077c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (!mSwitchInProgress) { 20087c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return; 20097c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 2010f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih 2011f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih for (size_t i = 0; i < mFetcherInfos.size(); ++i) { 2012f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih FetcherInfo& info = mFetcherInfos.editValueAt(i); 2013f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih if (info.mToBeRemoved) { 2014f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih info.mToBeRemoved = false; 20157c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (resume) { 20167c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang resumeFetcher(mFetcherInfos.keyAt(i), mSwapMask); 20177c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 2018f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 2019f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 2020f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih 2021f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih for (size_t i = 0; i < kMaxStreams; ++i) { 20227c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang AString newUri = mStreams[i].mNewUri; 20237c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (!newUri.empty()) { 20247c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // clear all mNewUri matching this newUri 20257c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang for (size_t j = i; j < kMaxStreams; ++j) { 20267c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (mStreams[j].mNewUri == newUri) { 20277c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mStreams[j].mNewUri.clear(); 20287c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 20297c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 20307c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGV("stopping newUri = %s", newUri.c_str()); 20317c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ssize_t index = mFetcherInfos.indexOfKey(newUri); 20327c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (index < 0) { 20337c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGE("did not find fetcher for newUri: %s", newUri.c_str()); 2034f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih continue; 2035f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 20367c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang FetcherInfo &info = mFetcherInfos.editValueAt(index); 20377c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang info.mToBeRemoved = true; 2038f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih info.mFetcher->stopAsync(); 2039f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 2040f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 20417c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 20427c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGI("#### Canceled Bandwidth Switch: %zd => %zd", 204325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang mOrigBandwidthIndex, mCurBandwidthIndex); 20447c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 20457c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mSwitchGeneration++; 20467c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mSwitchInProgress = false; 20477c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mCurBandwidthIndex = mOrigBandwidthIndex; 20487c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mSwapMask = 0; 20491543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih} 20501543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 20517c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangbool LiveSession::checkBuffering( 20527c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang bool &underflow, bool &ready, bool &down, bool &up) { 20537c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang underflow = ready = down = up = false; 2054964adb17885185808398507d2de88665fe193ee2Chong Zhang 20557c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (mReconfigurationInProgress) { 2056964adb17885185808398507d2de88665fe193ee2Chong Zhang ALOGV("Switch/Reconfig in progress, defer buffer polling"); 20571543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih return false; 20581543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 20591543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 20607c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang size_t activeCount, underflowCount, readyCount, downCount, upCount; 20617c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang activeCount = underflowCount = readyCount = downCount = upCount =0; 20627c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang int32_t minBufferPercent = -1; 20637c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang int64_t durationUs; 20647c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (getDuration(&durationUs) != OK) { 20657c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang durationUs = -1; 20667c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 2067964adb17885185808398507d2de88665fe193ee2Chong Zhang for (size_t i = 0; i < mPacketSources.size(); ++i) { 2068964adb17885185808398507d2de88665fe193ee2Chong Zhang // we don't check subtitles for buffering level 2069964adb17885185808398507d2de88665fe193ee2Chong Zhang if (!(mStreamMask & mPacketSources.keyAt(i) 2070964adb17885185808398507d2de88665fe193ee2Chong Zhang & (STREAMTYPE_AUDIO | STREAMTYPE_VIDEO))) { 2071964adb17885185808398507d2de88665fe193ee2Chong Zhang continue; 2072964adb17885185808398507d2de88665fe193ee2Chong Zhang } 2073964adb17885185808398507d2de88665fe193ee2Chong Zhang // ignore streams that never had any packet queued. 2074964adb17885185808398507d2de88665fe193ee2Chong Zhang // (it's possible that the variant only has audio or video) 2075964adb17885185808398507d2de88665fe193ee2Chong Zhang sp<AMessage> meta = mPacketSources[i]->getLatestEnqueuedMeta(); 2076964adb17885185808398507d2de88665fe193ee2Chong Zhang if (meta == NULL) { 2077964adb17885185808398507d2de88665fe193ee2Chong Zhang continue; 2078964adb17885185808398507d2de88665fe193ee2Chong Zhang } 2079964adb17885185808398507d2de88665fe193ee2Chong Zhang 20800dd229bb306df68b88e7419b3cc11fc6175be1daRobert Shih status_t finalResult; 2081964adb17885185808398507d2de88665fe193ee2Chong Zhang int64_t bufferedDurationUs = 20820dd229bb306df68b88e7419b3cc11fc6175be1daRobert Shih mPacketSources[i]->getBufferedDurationUs(&finalResult); 208325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("[%s] buffered %lld us", 208425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang getNameForStream(mPacketSources.keyAt(i)), 208525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang (long long)bufferedDurationUs); 20867c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (durationUs >= 0) { 20877c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang int32_t percent; 20887c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (mPacketSources[i]->isFinished(0 /* duration */)) { 20897c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang percent = 100; 20907c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } else { 20918464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang percent = (int32_t)(100.0 * 20928464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang (mLastDequeuedTimeUs + bufferedDurationUs) / durationUs); 20937c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 20947c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (minBufferPercent < 0 || percent < minBufferPercent) { 20957c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang minBufferPercent = percent; 20967c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 2097964adb17885185808398507d2de88665fe193ee2Chong Zhang } 20987c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 20997c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ++activeCount; 2100765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang int64_t readyMark = mInPreparationPhase ? kPrepareMarkUs : kReadyMarkUs; 21017c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (bufferedDurationUs > readyMark 21027c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang || mPacketSources[i]->isFinished(0)) { 21037c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ++readyCount; 21047c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 21057c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (!mPacketSources[i]->isFinished(0)) { 2106765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang if (bufferedDurationUs < kUnderflowMarkUs) { 21077c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ++underflowCount; 21087c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 21097c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (bufferedDurationUs > mUpSwitchMark) { 21107c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ++upCount; 2111d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang } 2112d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (bufferedDurationUs < mDownSwitchMark) { 21137c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ++downCount; 21147c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 21157c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 21167c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 21177c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 21187c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (minBufferPercent >= 0) { 21197c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notifyBufferingUpdate(minBufferPercent); 212014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 212114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 2122964adb17885185808398507d2de88665fe193ee2Chong Zhang if (activeCount > 0) { 21237c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang up = (upCount == activeCount); 21247c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang down = (downCount > 0); 21257c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ready = (readyCount == activeCount); 21267c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang underflow = (underflowCount > 0); 21271543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih return true; 21281543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 2129964adb17885185808398507d2de88665fe193ee2Chong Zhang 2130964adb17885185808398507d2de88665fe193ee2Chong Zhang return false; 21311543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih} 21321543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 21337c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::startBufferingIfNecessary() { 21347c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGV("startBufferingIfNecessary: mInPreparationPhase=%d, mBuffering=%d", 21357c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mInPreparationPhase, mBuffering); 21367c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (!mBuffering) { 21377c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mBuffering = true; 21387c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 21397c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AMessage> notify = mNotify->dup(); 21407c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->setInt32("what", kWhatBufferingStart); 21417c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->post(); 21427c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 21437c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang} 21447c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 21457c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::stopBufferingIfNecessary() { 21467c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGV("stopBufferingIfNecessary: mInPreparationPhase=%d, mBuffering=%d", 21477c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mInPreparationPhase, mBuffering); 21487c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 21497c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (mBuffering) { 21507c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mBuffering = false; 21517c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 21527c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AMessage> notify = mNotify->dup(); 21537c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->setInt32("what", kWhatBufferingEnd); 21547c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->post(); 21557c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 21567c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang} 21577c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 21587c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::notifyBufferingUpdate(int32_t percentage) { 21597c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (percentage < mPrevBufferPercentage) { 21607c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang percentage = mPrevBufferPercentage; 21617c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } else if (percentage > 100) { 21627c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang percentage = 100; 21637c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 21647c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 21657c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mPrevBufferPercentage = percentage; 21667c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 21677c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGV("notifyBufferingUpdate: percentage=%d%%", percentage); 21687c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 21697c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AMessage> notify = mNotify->dup(); 21707c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->setInt32("what", kWhatBufferingUpdate); 21717c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->setInt32("percentage", percentage); 21727c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->post(); 21737c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang} 21747c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 21758464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang/* 21768464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang * returns true if a bandwidth switch is actually needed (and started), 21778464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang * returns false otherwise 21788464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang */ 21798464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhangbool LiveSession::switchBandwidthIfNeeded(bool bufferHigh, bool bufferLow) { 2180538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang // no need to check bandwidth if we only have 1 bandwidth settings 21817c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (mSwitchInProgress || mBandwidthItems.size() < 2) { 21828464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang return false; 2183538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang } 2184538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 2185538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang int32_t bandwidthBps; 2186978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang bool isStable; 2187978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (mBandwidthEstimator->estimateBandwidth(&bandwidthBps, &isStable)) { 2188538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang ALOGV("bandwidth estimated at %.2f kbps", bandwidthBps / 1024.0f); 2189a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mLastBandwidthBps = bandwidthBps; 2190538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang } else { 2191538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang ALOGV("no bandwidth estimate."); 21928464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang return false; 2193538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang } 2194538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 2195538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang int32_t curBandwidth = mBandwidthItems.itemAt(mCurBandwidthIndex).mBandwidth; 2196d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // canSwithDown and canSwitchUp can't both be true. 2197d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // we only want to switch up when measured bw is 120% higher than current variant, 2198d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // and we only want to switch down when measured bw is below current variant. 2199978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang bool canSwitchDown = bufferLow 2200d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang && (bandwidthBps < (int32_t)curBandwidth); 2201d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang bool canSwitchUp = bufferHigh 2202d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang && (bandwidthBps > (int32_t)curBandwidth * 12 / 10); 2203d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang 2204978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (canSwitchDown || canSwitchUp) { 2205978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang // bandwidth estimating has some delay, if we have to downswitch when 2206978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang // it hasn't stabilized, be very conservative on bandwidth. 2207978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (!isStable && canSwitchDown) { 2208978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang bandwidthBps /= 2; 2209978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 2210978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang 2211538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang ssize_t bandwidthIndex = getBandwidthIndex(bandwidthBps); 2212538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 2213d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // it's possible that we're checking for canSwitchUp case, but the returned 2214d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // bandwidthIndex is < mCurBandwidthIndex, as getBandwidthIndex() only uses 70% 2215d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // of measured bw. In that case we don't want to do anything, since we have 2216d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // both enough buffer and enough bw. 22178464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang if ((canSwitchUp && bandwidthIndex > mCurBandwidthIndex) 2218978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang || (canSwitchDown && bandwidthIndex < mCurBandwidthIndex)) { 22198464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang // if not yet prepared, just restart again with new bw index. 22208464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang // this is faster and playback experience is cleaner. 22218464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang changeConfiguration( 22228464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang mInPreparationPhase ? 0 : -1ll, bandwidthIndex); 22238464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang return true; 2224538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang } 222514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 22268464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang return false; 2227a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 2228a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 22297c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::postError(status_t err) { 22307c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // if we reached EOS, notify buffering of 100% 22317c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (err == ERROR_END_OF_STREAM) { 22327c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notifyBufferingUpdate(100); 22337c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 22347c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // we'll stop buffer polling now, before that notify 22357c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // stop buffering to stop the spinning icon 22367c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang stopBufferingIfNecessary(); 22377c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang cancelPollBuffering(); 22387c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 22397c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AMessage> notify = mNotify->dup(); 22407c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->setInt32("what", kWhatError); 22417c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->setInt32("err", err); 22427c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->post(); 22437c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang} 22447c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 224514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::postPrepared(status_t err) { 224614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(mInPreparationPhase); 2247a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 224814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AMessage> notify = mNotify->dup(); 224914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (err == OK || err == ERROR_END_OF_STREAM) { 225014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->setInt32("what", kWhatPrepared); 225114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else { 22527c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang cancelPollBuffering(); 22537c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 225414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->setInt32("what", kWhatPreparationFailed); 225514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->setInt32("err", err); 225614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 2257a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 225814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->post(); 2259a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 226014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mInPreparationPhase = false; 2261b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber} 2262b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber 2263964adb17885185808398507d2de88665fe193ee2Chong Zhang 2264a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} // namespace android 2265a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 2266