LiveSession.cpp revision 0852843d304006e3ab333081fddda13b07193de8
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" 22a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 2314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include "M3UParser.h" 2414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include "PlaylistFetcher.h" 25a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 261156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber#include "include/HTTPBase.h" 2714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include "mpeg2ts/AnotherPacketSource.h" 28a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 29a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <cutils/properties.h> 301b86fe063badb5f28c467ade39be0f4008688947Andreas Huber#include <media/IMediaHTTPConnection.h> 311b86fe063badb5f28c467ade39be0f4008688947Andreas Huber#include <media/IMediaHTTPService.h> 32a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <media/stagefright/foundation/hexdump.h> 33a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <media/stagefright/foundation/ABuffer.h> 34a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <media/stagefright/foundation/ADebug.h> 35a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <media/stagefright/foundation/AMessage.h> 367c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang#include <media/stagefright/foundation/AUtils.h> 37a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <media/stagefright/DataSource.h> 38a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <media/stagefright/FileSource.h> 39a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <media/stagefright/MediaErrors.h> 401b86fe063badb5f28c467ade39be0f4008688947Andreas Huber#include <media/stagefright/MediaHTTP.h> 410852843d304006e3ab333081fddda13b07193de8Robert Shih#include <media/stagefright/MediaDefs.h> 4214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include <media/stagefright/MetaData.h> 4314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include <media/stagefright/Utils.h> 44a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 451543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih#include <utils/Mutex.h> 461543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 47a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <ctype.h> 48b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross#include <inttypes.h> 49a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <openssl/aes.h> 507e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber#include <openssl/md5.h> 51a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 52a44153c1a57202fb538659eb50706e60454d6273Andreas Hubernamespace android { 53a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 54765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang// static 55765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang// Bandwidth Switch Mark Defaults 56d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhangconst int64_t LiveSession::kUpSwitchMarkUs = 15000000ll; 57d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhangconst int64_t LiveSession::kDownSwitchMarkUs = 20000000ll; 58765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhangconst int64_t LiveSession::kUpSwitchMarginUs = 5000000ll; 59d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhangconst int64_t LiveSession::kResumeThresholdUs = 100000ll; 60765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang 61765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang// Buffer Prepare/Ready/Underflow Marks 62765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhangconst int64_t LiveSession::kReadyMarkUs = 5000000ll; 63765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhangconst int64_t LiveSession::kPrepareMarkUs = 1500000ll; 64765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhangconst int64_t LiveSession::kUnderflowMarkUs = 1000000ll; 65765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang 66538b6d22a3578c0201d48f8548289aa254d81484Chong Zhangstruct LiveSession::BandwidthEstimator : public RefBase { 67538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang BandwidthEstimator(); 68538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 69538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang void addBandwidthMeasurement(size_t numBytes, int64_t delayUs); 70538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang bool estimateBandwidth(int32_t *bandwidth); 71538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 72538b6d22a3578c0201d48f8548289aa254d81484Chong Zhangprivate: 73538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang // Bandwidth estimation parameters 74538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang static const int32_t kMaxBandwidthHistoryItems = 20; 75d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang static const int64_t kMaxBandwidthHistoryWindowUs = 5000000ll; // 5 sec 76538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 77538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang struct BandwidthEntry { 78538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang int64_t mDelayUs; 79538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang size_t mNumBytes; 80538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang }; 81538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 82538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang Mutex mLock; 83538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang List<BandwidthEntry> mBandwidthHistory; 84538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang int64_t mTotalTransferTimeUs; 85538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang size_t mTotalTransferBytes; 86538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 87538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang DISALLOW_EVIL_CONSTRUCTORS(BandwidthEstimator); 88538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang}; 89538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 90538b6d22a3578c0201d48f8548289aa254d81484Chong ZhangLiveSession::BandwidthEstimator::BandwidthEstimator() : 91538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mTotalTransferTimeUs(0), 92538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mTotalTransferBytes(0) { 93538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang} 94538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 95538b6d22a3578c0201d48f8548289aa254d81484Chong Zhangvoid LiveSession::BandwidthEstimator::addBandwidthMeasurement( 96538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang size_t numBytes, int64_t delayUs) { 97538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang AutoMutex autoLock(mLock); 98538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 99538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang BandwidthEntry entry; 100538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang entry.mDelayUs = delayUs; 101538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang entry.mNumBytes = numBytes; 102538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mTotalTransferTimeUs += delayUs; 103538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mTotalTransferBytes += numBytes; 104538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mBandwidthHistory.push_back(entry); 105538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 106538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang // trim old samples, keeping at least kMaxBandwidthHistoryItems samples, 107538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang // and total transfer time at least kMaxBandwidthHistoryWindowUs. 108538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang while (mBandwidthHistory.size() > kMaxBandwidthHistoryItems) { 109538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang List<BandwidthEntry>::iterator it = mBandwidthHistory.begin(); 110538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang if (mTotalTransferTimeUs - it->mDelayUs < kMaxBandwidthHistoryWindowUs) { 111538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang break; 112538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang } 113538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mTotalTransferTimeUs -= it->mDelayUs; 114538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mTotalTransferBytes -= it->mNumBytes; 115538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mBandwidthHistory.erase(mBandwidthHistory.begin()); 116538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang } 117538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang} 118538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 119538b6d22a3578c0201d48f8548289aa254d81484Chong Zhangbool LiveSession::BandwidthEstimator::estimateBandwidth(int32_t *bandwidthBps) { 120538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang AutoMutex autoLock(mLock); 121538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 122538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang if (mBandwidthHistory.size() < 2) { 123538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang return false; 124538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang } 125538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 126538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang *bandwidthBps = ((double)mTotalTransferBytes * 8E6 / mTotalTransferTimeUs); 127538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang return true; 128538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang} 129538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 1307c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang//static 1317c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangconst char *LiveSession::getKeyForStream(StreamType type) { 1327c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang switch (type) { 1337c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang case STREAMTYPE_VIDEO: 1347c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return "timeUsVideo"; 1357c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang case STREAMTYPE_AUDIO: 1367c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return "timeUsAudio"; 1377c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang case STREAMTYPE_SUBTITLES: 1387c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return "timeUsSubtitle"; 1390852843d304006e3ab333081fddda13b07193de8Robert Shih case STREAMTYPE_METADATA: 1400852843d304006e3ab333081fddda13b07193de8Robert Shih return "timeUsMetadata"; // unused 1417c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang default: 1427c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang TRESPASS(); 1437c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 1447c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return NULL; 1457c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang} 1467c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 14725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang//static 14825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhangconst char *LiveSession::getNameForStream(StreamType type) { 14925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang switch (type) { 15025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang case STREAMTYPE_VIDEO: 15125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang return "video"; 15225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang case STREAMTYPE_AUDIO: 15325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang return "audio"; 15425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang case STREAMTYPE_SUBTITLES: 15525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang return "subs"; 1560852843d304006e3ab333081fddda13b07193de8Robert Shih case STREAMTYPE_METADATA: 1570852843d304006e3ab333081fddda13b07193de8Robert Shih return "metadata"; 15825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang default: 15925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang break; 16025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang } 16125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang return "unknown"; 16225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang} 16325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 1640852843d304006e3ab333081fddda13b07193de8Robert Shih//static 1650852843d304006e3ab333081fddda13b07193de8Robert ShihATSParser::SourceType LiveSession::getSourceTypeForStream(StreamType type) { 1660852843d304006e3ab333081fddda13b07193de8Robert Shih switch (type) { 1670852843d304006e3ab333081fddda13b07193de8Robert Shih case STREAMTYPE_VIDEO: 1680852843d304006e3ab333081fddda13b07193de8Robert Shih return ATSParser::VIDEO; 1690852843d304006e3ab333081fddda13b07193de8Robert Shih case STREAMTYPE_AUDIO: 1700852843d304006e3ab333081fddda13b07193de8Robert Shih return ATSParser::AUDIO; 1710852843d304006e3ab333081fddda13b07193de8Robert Shih case STREAMTYPE_METADATA: 1720852843d304006e3ab333081fddda13b07193de8Robert Shih return ATSParser::META; 1730852843d304006e3ab333081fddda13b07193de8Robert Shih case STREAMTYPE_SUBTITLES: 1740852843d304006e3ab333081fddda13b07193de8Robert Shih default: 1750852843d304006e3ab333081fddda13b07193de8Robert Shih TRESPASS(); 1760852843d304006e3ab333081fddda13b07193de8Robert Shih } 1770852843d304006e3ab333081fddda13b07193de8Robert Shih return ATSParser::NUM_SOURCE_TYPES; // should not reach here 1780852843d304006e3ab333081fddda13b07193de8Robert Shih} 1790852843d304006e3ab333081fddda13b07193de8Robert Shih 1800df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas HuberLiveSession::LiveSession( 1811b86fe063badb5f28c467ade39be0f4008688947Andreas Huber const sp<AMessage> ¬ify, uint32_t flags, 18281e68448f3361eaf8618930471fdc3c21bdf5cbcAndreas Huber const sp<IMediaHTTPService> &httpService) 1830df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas Huber : mNotify(notify), 1840df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas Huber mFlags(flags), 1851b86fe063badb5f28c467ade39be0f4008688947Andreas Huber mHTTPService(httpService), 1867c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mBuffering(false), 1870df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas Huber mInPreparationPhase(true), 1887c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mPollBufferingGeneration(0), 1897c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mPrevBufferPercentage(-1), 1901b86fe063badb5f28c467ade39be0f4008688947Andreas Huber mHTTPDataSource(new MediaHTTP(mHTTPService->makeHTTPConnection())), 191309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mCurBandwidthIndex(-1), 1927c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mOrigBandwidthIndex(-1), 193a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mLastBandwidthBps(-1ll), 194538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mBandwidthEstimator(new BandwidthEstimator()), 195a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang mMaxWidth(720), 196a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang mMaxHeight(480), 19714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mStreamMask(0), 1981543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih mNewStreamMask(0), 1991543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih mSwapMask(0), 2001543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih mSwitchGeneration(0), 201b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih mSubtitleGeneration(0), 20214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mLastDequeuedTimeUs(0ll), 203dcb89b3b505522efde173c105a851c412f947178Chong Zhang mRealTimeBaseUs(0ll), 20414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mReconfigurationInProgress(false), 2051543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih mSwitchInProgress(false), 206765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang mUpSwitchMark(kUpSwitchMarkUs), 207765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang mDownSwitchMark(kDownSwitchMarkUs), 208765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang mUpSwitchMargin(kUpSwitchMarginUs), 209309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mFirstTimeUsValid(false), 210309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mFirstTimeUs(0), 2110852843d304006e3ab333081fddda13b07193de8Robert Shih mLastSeekTimeUs(0), 2120852843d304006e3ab333081fddda13b07193de8Robert Shih mHasMetadata(false) { 2138ca002eedc747dd854b61cbe364b52c06869273fRobert Shih mStreams[kAudioIndex] = StreamItem("audio"); 2148ca002eedc747dd854b61cbe364b52c06869273fRobert Shih mStreams[kVideoIndex] = StreamItem("video"); 215e4f25c280a8f1655c31a745978e0fcbc61f91deeRobert Shih mStreams[kSubtitleIndex] = StreamItem("subtitles"); 21614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 2170852843d304006e3ab333081fddda13b07193de8Robert Shih for (size_t i = 0; i < kNumSources; ++i) { 2188ca002eedc747dd854b61cbe364b52c06869273fRobert Shih mPacketSources.add(indexToType(i), new AnotherPacketSource(NULL /* meta */)); 2191543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih mPacketSources2.add(indexToType(i), new AnotherPacketSource(NULL /* meta */)); 2208ca002eedc747dd854b61cbe364b52c06869273fRobert Shih } 221a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 222a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 223a44153c1a57202fb538659eb50706e60454d6273Andreas HuberLiveSession::~LiveSession() { 224964adb17885185808398507d2de88665fe193ee2Chong Zhang if (mFetcherLooper != NULL) { 225964adb17885185808398507d2de88665fe193ee2Chong Zhang mFetcherLooper->stop(); 226964adb17885185808398507d2de88665fe193ee2Chong Zhang } 227a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 228a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 2290852843d304006e3ab333081fddda13b07193de8Robert Shihint64_t LiveSession::calculateMediaTimeUs( 2300852843d304006e3ab333081fddda13b07193de8Robert Shih int64_t firstTimeUs, int64_t timeUs, int32_t discontinuitySeq) { 2310852843d304006e3ab333081fddda13b07193de8Robert Shih if (timeUs >= firstTimeUs) { 2320852843d304006e3ab333081fddda13b07193de8Robert Shih timeUs -= firstTimeUs; 2330852843d304006e3ab333081fddda13b07193de8Robert Shih } else { 2340852843d304006e3ab333081fddda13b07193de8Robert Shih timeUs = 0; 2350852843d304006e3ab333081fddda13b07193de8Robert Shih } 2360852843d304006e3ab333081fddda13b07193de8Robert Shih timeUs += mLastSeekTimeUs; 2370852843d304006e3ab333081fddda13b07193de8Robert Shih if (mDiscontinuityOffsetTimesUs.indexOfKey(discontinuitySeq) >= 0) { 2380852843d304006e3ab333081fddda13b07193de8Robert Shih timeUs += mDiscontinuityOffsetTimesUs.valueFor(discontinuitySeq); 2390852843d304006e3ab333081fddda13b07193de8Robert Shih } 2400852843d304006e3ab333081fddda13b07193de8Robert Shih return timeUs; 2410852843d304006e3ab333081fddda13b07193de8Robert Shih} 2420852843d304006e3ab333081fddda13b07193de8Robert Shih 24314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::dequeueAccessUnit( 24414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber StreamType stream, sp<ABuffer> *accessUnit) { 245964adb17885185808398507d2de88665fe193ee2Chong Zhang status_t finalResult = OK; 24614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AnotherPacketSource> packetSource = mPacketSources.valueFor(stream); 24714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 24825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ssize_t streamIdx = typeToIndex(stream); 24925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang if (streamIdx < 0) { 25025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang return INVALID_VALUE; 25125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang } 25225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang const char *streamStr = getNameForStream(stream); 253a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // Do not let client pull data if we don't have data packets yet. 254a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // We might only have a format discontinuity queued without data. 255a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // When NuPlayerDecoder dequeues the format discontinuity, it will 256a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // immediately try to getFormat. If we return NULL, NuPlayerDecoder 257a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // thinks it can do seamless change, so will not shutdown decoder. 258a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // When the actual format arrives, it can't handle it and get stuck. 259a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (!packetSource->hasDataBufferAvailable(&finalResult)) { 26025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("[%s] dequeueAccessUnit: no buffer available (finalResult=%d)", 26125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang streamStr, finalResult); 26225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 263f69c996864844e8f669308af8412cede043062a2Robert Shih if (finalResult == OK) { 264f69c996864844e8f669308af8412cede043062a2Robert Shih return -EAGAIN; 265f69c996864844e8f669308af8412cede043062a2Robert Shih } else { 266f69c996864844e8f669308af8412cede043062a2Robert Shih return finalResult; 267f69c996864844e8f669308af8412cede043062a2Robert Shih } 268f69c996864844e8f669308af8412cede043062a2Robert Shih } 269f69c996864844e8f669308af8412cede043062a2Robert Shih 270a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // Let the client dequeue as long as we have buffers available 271a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // Do not make pause/resume decisions here. 272309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 27314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber status_t err = packetSource->dequeueAccessUnit(accessUnit); 27414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 27514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (err == INFO_DISCONTINUITY) { 276309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih // adaptive streaming, discontinuities in the playlist 27714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int32_t type; 27814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK((*accessUnit)->meta()->findInt32("discontinuity", &type)); 27914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 28014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AMessage> extra; 28114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (!(*accessUnit)->meta()->findMessage("extra", &extra)) { 28214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber extra.clear(); 28314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 28414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 28514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGI("[%s] read discontinuity of type %d, extra = %s", 28614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber streamStr, 28714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber type, 28814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber extra == NULL ? "NULL" : extra->debugString().c_str()); 28914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else if (err == OK) { 290309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 291dcb89b3b505522efde173c105a851c412f947178Chong Zhang if (stream == STREAMTYPE_AUDIO || stream == STREAMTYPE_VIDEO) { 29225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang int64_t timeUs, originalTimeUs; 293309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih int32_t discontinuitySeq = 0; 2940852843d304006e3ab333081fddda13b07193de8Robert Shih StreamItem& strm = mStreams[streamIdx]; 295dcb89b3b505522efde173c105a851c412f947178Chong Zhang CHECK((*accessUnit)->meta()->findInt64("timeUs", &timeUs)); 29625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang originalTimeUs = timeUs; 297309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih (*accessUnit)->meta()->findInt32("discontinuitySeq", &discontinuitySeq); 2987c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (discontinuitySeq > (int32_t) strm.mCurDiscontinuitySeq) { 2997c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang int64_t offsetTimeUs; 3007c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (mDiscontinuityOffsetTimesUs.indexOfKey(strm.mCurDiscontinuitySeq) >= 0) { 3017c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang offsetTimeUs = mDiscontinuityOffsetTimesUs.valueFor(strm.mCurDiscontinuitySeq); 3027c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } else { 3037c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang offsetTimeUs = 0; 3047c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 3057c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 3067c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (mDiscontinuityAbsStartTimesUs.indexOfKey(strm.mCurDiscontinuitySeq) >= 0) { 3077c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang int64_t firstTimeUs; 3087c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang firstTimeUs = mDiscontinuityAbsStartTimesUs.valueFor(strm.mCurDiscontinuitySeq); 3097c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang offsetTimeUs += strm.mLastDequeuedTimeUs - firstTimeUs; 3107c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang offsetTimeUs += strm.mLastSampleDurationUs; 3117c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } else { 3127c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang offsetTimeUs += strm.mLastSampleDurationUs; 3137c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 3147c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 3157c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mDiscontinuityOffsetTimesUs.add(discontinuitySeq, offsetTimeUs); 3167c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang strm.mCurDiscontinuitySeq = discontinuitySeq; 3177c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 318309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 319309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih int32_t discard = 0; 320309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih int64_t firstTimeUs; 321309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (mDiscontinuityAbsStartTimesUs.indexOfKey(strm.mCurDiscontinuitySeq) >= 0) { 322309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih int64_t durUs; // approximate sample duration 323309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (timeUs > strm.mLastDequeuedTimeUs) { 324309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih durUs = timeUs - strm.mLastDequeuedTimeUs; 325309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } else { 326309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih durUs = strm.mLastDequeuedTimeUs - timeUs; 327309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 328309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih strm.mLastSampleDurationUs = durUs; 329309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih firstTimeUs = mDiscontinuityAbsStartTimesUs.valueFor(strm.mCurDiscontinuitySeq); 330309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } else if ((*accessUnit)->meta()->findInt32("discard", &discard) && discard) { 331309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih firstTimeUs = timeUs; 332309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } else { 333309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mDiscontinuityAbsStartTimesUs.add(strm.mCurDiscontinuitySeq, timeUs); 334309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih firstTimeUs = timeUs; 335309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 336309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 337309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih strm.mLastDequeuedTimeUs = timeUs; 3380852843d304006e3ab333081fddda13b07193de8Robert Shih timeUs = calculateMediaTimeUs(firstTimeUs, timeUs, discontinuitySeq); 339dcb89b3b505522efde173c105a851c412f947178Chong Zhang 34025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("[%s] dequeueAccessUnit: time %lld us, original %lld us", 34125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang streamStr, (long long)timeUs, (long long)originalTimeUs); 342309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih (*accessUnit)->meta()->setInt64("timeUs", timeUs); 343dcb89b3b505522efde173c105a851c412f947178Chong Zhang mLastDequeuedTimeUs = timeUs; 344dcb89b3b505522efde173c105a851c412f947178Chong Zhang mRealTimeBaseUs = ALooper::GetNowUs() - timeUs; 345dcb89b3b505522efde173c105a851c412f947178Chong Zhang } else if (stream == STREAMTYPE_SUBTITLES) { 346b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih int32_t subtitleGeneration; 347b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih if ((*accessUnit)->meta()->findInt32("subtitleGeneration", &subtitleGeneration) 348b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih && subtitleGeneration != mSubtitleGeneration) { 349b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih return -EAGAIN; 350b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih }; 351dcb89b3b505522efde173c105a851c412f947178Chong Zhang (*accessUnit)->meta()->setInt32( 352dcb89b3b505522efde173c105a851c412f947178Chong Zhang "trackIndex", mPlaylist->getSelectedIndex()); 353dcb89b3b505522efde173c105a851c412f947178Chong Zhang (*accessUnit)->meta()->setInt64("baseUs", mRealTimeBaseUs); 3540852843d304006e3ab333081fddda13b07193de8Robert Shih } else if (stream == STREAMTYPE_METADATA) { 3550852843d304006e3ab333081fddda13b07193de8Robert Shih HLSTime mdTime((*accessUnit)->meta()); 3560852843d304006e3ab333081fddda13b07193de8Robert Shih if (mDiscontinuityAbsStartTimesUs.indexOfKey(mdTime.mSeq) < 0) { 3570852843d304006e3ab333081fddda13b07193de8Robert Shih packetSource->requeueAccessUnit((*accessUnit)); 3580852843d304006e3ab333081fddda13b07193de8Robert Shih return -EAGAIN; 3590852843d304006e3ab333081fddda13b07193de8Robert Shih } else { 3600852843d304006e3ab333081fddda13b07193de8Robert Shih int64_t firstTimeUs = mDiscontinuityAbsStartTimesUs.valueFor(mdTime.mSeq); 3610852843d304006e3ab333081fddda13b07193de8Robert Shih int64_t timeUs = calculateMediaTimeUs(firstTimeUs, mdTime.mTimeUs, mdTime.mSeq); 3620852843d304006e3ab333081fddda13b07193de8Robert Shih (*accessUnit)->meta()->setInt64("timeUs", timeUs); 3630852843d304006e3ab333081fddda13b07193de8Robert Shih (*accessUnit)->meta()->setInt64("baseUs", mRealTimeBaseUs); 3640852843d304006e3ab333081fddda13b07193de8Robert Shih } 365dcb89b3b505522efde173c105a851c412f947178Chong Zhang } 36614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else { 36714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGI("[%s] encountered error %d", streamStr, err); 36814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 36914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 37014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return err; 37114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 37214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 37314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::getStreamFormat(StreamType stream, sp<AMessage> *format) { 37414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (!(mStreamMask & stream)) { 37514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return UNKNOWN_ERROR; 37614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 37714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 37814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AnotherPacketSource> packetSource = mPacketSources.valueFor(stream); 37914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 38014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<MetaData> meta = packetSource->getFormat(); 38114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 38214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (meta == NULL) { 38314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return -EAGAIN; 38414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 38514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 3867c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (stream == STREAMTYPE_AUDIO) { 3877c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // set AAC input buffer size to 32K bytes (256kbps x 1sec) 3887c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang meta->setInt32(kKeyMaxInputSize, 32 * 1024); 389a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang } else if (stream == STREAMTYPE_VIDEO) { 390a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang meta->setInt32(kKeyMaxWidth, mMaxWidth); 391a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang meta->setInt32(kKeyMaxHeight, mMaxHeight); 3927c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 3937c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 39414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return convertMetaDataToMessage(meta, format); 395a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 396a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 397a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhangsp<HTTPBase> LiveSession::getHTTPDataSource() { 398a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang return new MediaHTTP(mHTTPService->makeHTTPConnection()); 399a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang} 400a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 40114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::connectAsync( 402ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber const char *url, const KeyedVector<String8, String8> *headers) { 4031d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> msg = new AMessage(kWhatConnect, this); 404a44153c1a57202fb538659eb50706e60454d6273Andreas Huber msg->setString("url", url); 405ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber 406ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber if (headers != NULL) { 407ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber msg->setPointer( 408ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber "headers", 409ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber new KeyedVector<String8, String8>(*headers)); 410ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber } 411ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber 412a44153c1a57202fb538659eb50706e60454d6273Andreas Huber msg->post(); 413a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 414a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 41514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::disconnect() { 4161d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> msg = new AMessage(kWhatDisconnect, this); 417ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber 41814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AMessage> response; 41914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber status_t err = msg->postAndAwaitResponse(&response); 420ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber 42114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return err; 422a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 423a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 42414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::seekTo(int64_t timeUs) { 4251d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> msg = new AMessage(kWhatSeek, this); 426a44153c1a57202fb538659eb50706e60454d6273Andreas Huber msg->setInt64("timeUs", timeUs); 427a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 42814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AMessage> response; 42914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber status_t err = msg->postAndAwaitResponse(&response); 43014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 43114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return err; 432a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 433a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 4347c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangbool LiveSession::checkSwitchProgress( 4357c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AMessage> &stopParams, int64_t delayUs, bool *needResumeUntil) { 4367c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang AString newUri; 4377c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang CHECK(stopParams->findString("uri", &newUri)); 4387c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 4397c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang *needResumeUntil = false; 4407c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AMessage> firstNewMeta[kMaxStreams]; 4417c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang for (size_t i = 0; i < kMaxStreams; ++i) { 4427c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang StreamType stream = indexToType(i); 4437c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (!(mSwapMask & mNewStreamMask & stream) 4447c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang || (mStreams[i].mNewUri != newUri)) { 4457c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang continue; 4467c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 4477c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (stream == STREAMTYPE_SUBTITLES) { 4487c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang continue; 4497c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 4507c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AnotherPacketSource> &source = mPacketSources.editValueAt(i); 4517c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 4527c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // First, get latest dequeued meta, which is where the decoder is at. 4537c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // (when upswitching, we take the meta after a certain delay, so that 4547c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // the decoder is left with some cushion) 4557c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AMessage> lastDequeueMeta, lastEnqueueMeta; 4567c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (delayUs > 0) { 4577c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang lastDequeueMeta = source->getMetaAfterLastDequeued(delayUs); 458d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (lastDequeueMeta == NULL) { 459d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // this means we don't have enough cushion, try again later 460d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang ALOGV("[%s] up switching failed due to insufficient buffer", 46125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang getNameForStream(stream)); 462d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang return false; 463d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang } 4647c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } else { 465d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // It's okay for lastDequeueMeta to be NULL here, it means the 466d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // decoder hasn't even started dequeueing 4677c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang lastDequeueMeta = source->getLatestDequeuedMeta(); 4687c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 4697c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // Then, trim off packets at beginning of mPacketSources2 that's before 4707c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // the latest dequeued time. These samples are definitely too late. 471d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang firstNewMeta[i] = mPacketSources2.editValueAt(i) 472d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang ->trimBuffersBeforeMeta(lastDequeueMeta); 473d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang 4747c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // Now firstNewMeta[i] is the first sample after the trim. 4757c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // If it's NULL, we failed because dequeue already past all samples 4767c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // in mPacketSource2, we have to try again. 4777c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (firstNewMeta[i] == NULL) { 478d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang HLSTime dequeueTime(lastDequeueMeta); 4797c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGV("[%s] dequeue time (%d, %lld) past start time", 48025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang getNameForStream(stream), 481d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang dequeueTime.mSeq, (long long) dequeueTime.mTimeUs); 4827c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return false; 4837c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 4847c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 4857c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // Otherwise, we check if mPacketSources2 overlaps with what old fetcher 4867c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // already fetched, and see if we need to resumeUntil 4877c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang lastEnqueueMeta = source->getLatestEnqueuedMeta(); 4887c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // lastEnqueueMeta == NULL means old fetcher stopped at a discontinuity 4897c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // boundary, no need to resume as the content will look different anyways 4907c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (lastEnqueueMeta != NULL) { 491d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang HLSTime lastTime(lastEnqueueMeta), startTime(firstNewMeta[i]); 4927c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 4937c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // no need to resume old fetcher if new fetcher started in different 4947c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // discontinuity sequence, as the content will look different. 495d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang *needResumeUntil |= (startTime.mSeq == lastTime.mSeq 496d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang && startTime.mTimeUs - lastTime.mTimeUs > kResumeThresholdUs); 4977c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 498d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // update the stopTime for resumeUntil 499d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang stopParams->setInt32("discontinuitySeq", startTime.mSeq); 500d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang stopParams->setInt64(getKeyForStream(stream), startTime.mTimeUs); 5017c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 5027c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 5037c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 5047c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // if we're here, it means dequeue progress hasn't passed some samples in 5057c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // mPacketSource2, we can trim off the excess in mPacketSource. 5067c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // (old fetcher might still need to resumeUntil the start time of new fetcher) 5077c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang for (size_t i = 0; i < kMaxStreams; ++i) { 5087c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang StreamType stream = indexToType(i); 5097c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (!(mSwapMask & mNewStreamMask & stream) 510d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang || (newUri != mStreams[i].mNewUri) 511d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang || stream == STREAMTYPE_SUBTITLES) { 5127c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang continue; 5137c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 514d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang mPacketSources.valueFor(stream)->trimBuffersAfterMeta(firstNewMeta[i]); 5157c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 5167c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 5177c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // no resumeUntil if already underflow 5187c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang *needResumeUntil &= !mBuffering; 5197c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 5207c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return true; 5217c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang} 5227c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 523a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onMessageReceived(const sp<AMessage> &msg) { 524a44153c1a57202fb538659eb50706e60454d6273Andreas Huber switch (msg->what()) { 525a44153c1a57202fb538659eb50706e60454d6273Andreas Huber case kWhatConnect: 52614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 527a44153c1a57202fb538659eb50706e60454d6273Andreas Huber onConnect(msg); 528a44153c1a57202fb538659eb50706e60454d6273Andreas Huber break; 52914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 530a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 531a44153c1a57202fb538659eb50706e60454d6273Andreas Huber case kWhatDisconnect: 53214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 53314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->senderAwaitsResponse(&mDisconnectReplyID)); 53414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 53514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (mReconfigurationInProgress) { 53614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 53714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 53814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 53914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber finishDisconnect(); 540a44153c1a57202fb538659eb50706e60454d6273Andreas Huber break; 54114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 542a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 54314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case kWhatSeek: 54414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 545a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar if (mReconfigurationInProgress) { 546800599cdd50737de1cde483a34b39923750b0658Robert Shih msg->post(50000); 547a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar break; 548800599cdd50737de1cde483a34b39923750b0658Robert Shih } 549a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar 550a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar CHECK(msg->senderAwaitsResponse(&mSeekReplyID)); 551a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar mSeekReply = new AMessage; 552a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar 553a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar onSeek(msg); 55414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 55514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 55614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 55714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case kWhatFetcherNotify: 55814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 55914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int32_t what; 56014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->findInt32("what", &what)); 56114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 56214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber switch (what) { 56314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case PlaylistFetcher::kWhatStarted: 56414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 56514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case PlaylistFetcher::kWhatPaused: 56614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case PlaylistFetcher::kWhatStopped: 56714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 568a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang AString uri; 569a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang CHECK(msg->findString("uri", &uri)); 570a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang ssize_t index = mFetcherInfos.indexOfKey(uri); 571a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (index < 0) { 572a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // ignore msgs from fetchers that's already gone 573a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang break; 574a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 575a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 57625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("fetcher-%d %s", 57725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang mFetcherInfos[index].mFetcher->getFetcherID(), 57825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang what == PlaylistFetcher::kWhatPaused ? 57925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang "paused" : "stopped"); 58025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 58114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (what == PlaylistFetcher::kWhatStopped) { 582964adb17885185808398507d2de88665fe193ee2Chong Zhang mFetcherLooper->unregisterHandler( 583964adb17885185808398507d2de88665fe193ee2Chong Zhang mFetcherInfos[index].mFetcher->id()); 584964adb17885185808398507d2de88665fe193ee2Chong Zhang mFetcherInfos.removeItemsAt(index); 585a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } else if (what == PlaylistFetcher::kWhatPaused) { 586a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang int32_t seekMode; 587a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang CHECK(msg->findInt32("seekMode", &seekMode)); 588a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang for (size_t i = 0; i < kMaxStreams; ++i) { 589a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (mStreams[i].mUri == uri) { 590a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mStreams[i].mSeekMode = (SeekMode) seekMode; 591a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 592309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 59314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 59414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 59514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (mContinuation != NULL) { 59614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK_GT(mContinuationCounter, 0); 59714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (--mContinuationCounter == 0) { 59814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mContinuation->post(); 59914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 60025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("%zu fetcher(s) left", mContinuationCounter); 60114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 60214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 60314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 60414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 60514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case PlaylistFetcher::kWhatDurationUpdate: 60614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 60714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber AString uri; 60814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->findString("uri", &uri)); 60914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 61014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int64_t durationUs; 61114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->findInt64("durationUs", &durationUs)); 61214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 613964adb17885185808398507d2de88665fe193ee2Chong Zhang ssize_t index = mFetcherInfos.indexOfKey(uri); 614964adb17885185808398507d2de88665fe193ee2Chong Zhang if (index >= 0) { 615964adb17885185808398507d2de88665fe193ee2Chong Zhang FetcherInfo *info = &mFetcherInfos.editValueFor(uri); 616964adb17885185808398507d2de88665fe193ee2Chong Zhang info->mDurationUs = durationUs; 617964adb17885185808398507d2de88665fe193ee2Chong Zhang } 61814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 61914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 62014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 6217c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang case PlaylistFetcher::kWhatTargetDurationUpdate: 6227c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang { 6237c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang int64_t targetDurationUs; 6247c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang CHECK(msg->findInt64("targetDurationUs", &targetDurationUs)); 625d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang mUpSwitchMark = min(kUpSwitchMarkUs, targetDurationUs * 7 / 4); 626765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang mDownSwitchMark = min(kDownSwitchMarkUs, targetDurationUs * 9 / 4); 627765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang mUpSwitchMargin = min(kUpSwitchMarginUs, targetDurationUs); 6287c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang break; 6297c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 6307c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 63114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case PlaylistFetcher::kWhatError: 63214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 63314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber status_t err; 63414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->findInt32("err", &err)); 63514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 63614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGE("XXX Received error %d from PlaylistFetcher.", err); 63714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 63815f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih // handle EOS on subtitle tracks independently 63915f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih AString uri; 64015f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih if (err == ERROR_END_OF_STREAM && msg->findString("uri", &uri)) { 64115f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih ssize_t i = mFetcherInfos.indexOfKey(uri); 64215f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih if (i >= 0) { 64315f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih const sp<PlaylistFetcher> &fetcher = mFetcherInfos.valueAt(i).mFetcher; 64415f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih if (fetcher != NULL) { 64515f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih uint32_t type = fetcher->getStreamTypeMask(); 64615f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih if (type == STREAMTYPE_SUBTITLES) { 64715f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih mPacketSources.valueFor( 64815f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih STREAMTYPE_SUBTITLES)->signalEOS(err);; 64915f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih break; 65015f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih } 65115f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih } 65215f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih } 65315f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih } 65415f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih 65514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (mInPreparationPhase) { 65614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber postPrepared(err); 65714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 65814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 6591543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih cancelBandwidthSwitch(); 6601543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 66114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mPacketSources.valueFor(STREAMTYPE_AUDIO)->signalEOS(err); 66214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 66314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mPacketSources.valueFor(STREAMTYPE_VIDEO)->signalEOS(err); 66414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 66514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mPacketSources.valueFor( 66614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber STREAMTYPE_SUBTITLES)->signalEOS(err); 66714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 6687c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang postError(err); 6697c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang break; 6707c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 6717c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 6727c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang case PlaylistFetcher::kWhatStopReached: 6737c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang { 6747c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGV("kWhatStopReached"); 6757c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 676d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang AString oldUri; 677d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang CHECK(msg->findString("uri", &oldUri)); 6787c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 679d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang ssize_t index = mFetcherInfos.indexOfKey(oldUri); 6807c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (index < 0) { 6817c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang break; 6827c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 6837c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 684d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang tryToFinishBandwidthSwitch(oldUri); 68514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 68614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 68714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 6881543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih case PlaylistFetcher::kWhatStartedAt: 6891543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih { 6901543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih int32_t switchGeneration; 6911543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih CHECK(msg->findInt32("switchGeneration", &switchGeneration)); 6921543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 69325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("kWhatStartedAt: switchGen=%d, mSwitchGen=%d", 69425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang switchGeneration, mSwitchGeneration); 69525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 6961543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih if (switchGeneration != mSwitchGeneration) { 6971543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih break; 6981543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 6991543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 700a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang AString uri; 701a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang CHECK(msg->findString("uri", &uri)); 7027c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 7037c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // mark new fetcher mToBeResumed 704a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang ssize_t index = mFetcherInfos.indexOfKey(uri); 705a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (index >= 0) { 706a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mFetcherInfos.editValueAt(index).mToBeResumed = true; 707a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 708a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 7097c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // temporarily disable packet sources to be swapped to prevent 7107c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // NuPlayerDecoder from dequeuing while we check progress 7117c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang for (size_t i = 0; i < mPacketSources.size(); ++i) { 7127c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if ((mSwapMask & mPacketSources.keyAt(i)) 7137c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang && uri == mStreams[i].mNewUri) { 7147c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mPacketSources.editValueAt(i)->enable(false); 7151543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 7161543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 7177c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang bool switchUp = (mCurBandwidthIndex > mOrigBandwidthIndex); 7187c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // If switching up, require a cushion bigger than kUnderflowMark 7197c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // to avoid buffering immediately after the switch. 7207c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // (If we don't have that cushion we'd rather cancel and try again.) 721765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang int64_t delayUs = switchUp ? (kUnderflowMarkUs + 1000000ll) : 0; 7227c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang bool needResumeUntil = false; 7237c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AMessage> stopParams = msg; 7247c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (checkSwitchProgress(stopParams, delayUs, &needResumeUntil)) { 7257c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // playback time hasn't passed startAt time 7267c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (!needResumeUntil) { 72725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("finish switch"); 7287c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang for (size_t i = 0; i < kMaxStreams; ++i) { 7297c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if ((mSwapMask & indexToType(i)) 7307c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang && uri == mStreams[i].mNewUri) { 7317c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // have to make a copy of mStreams[i].mUri because 7327c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // tryToFinishBandwidthSwitch is modifying mStreams[] 7337c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang AString oldURI = mStreams[i].mUri; 7347c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang tryToFinishBandwidthSwitch(oldURI); 7357c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang break; 7367c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 7377c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 7387c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } else { 7397c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // startAt time is after last enqueue time 7407c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // Resume fetcher for the original variant; the resumed fetcher should 7417c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // continue until the timestamps found in msg, which is stored by the 7427c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // new fetcher to indicate where the new variant has started buffering. 74325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("finish switch with resumeUntilAsync"); 7447c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang for (size_t i = 0; i < mFetcherInfos.size(); i++) { 7457c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang const FetcherInfo &info = mFetcherInfos.valueAt(i); 7467c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (info.mToBeRemoved) { 7477c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang info.mFetcher->resumeUntilAsync(stopParams); 7487c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 7497c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 7507c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 7517c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } else { 7527c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // playback time passed startAt time 7537c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (switchUp) { 7547c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // if switching up, cancel and retry if condition satisfies again 75525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("cancel up switch because we're too late"); 7567c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang cancelBandwidthSwitch(true /* resume */); 7577c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } else { 75825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("retry down switch at next sample"); 7597c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang resumeFetcher(uri, mSwapMask, -1, true /* newUri */); 7607c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 7617c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 7627c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // re-enable all packet sources 7637c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang for (size_t i = 0; i < mPacketSources.size(); ++i) { 7647c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mPacketSources.editValueAt(i)->enable(true); 7657c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 7667c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 7671543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih break; 7681543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 7691543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 7700852843d304006e3ab333081fddda13b07193de8Robert Shih case PlaylistFetcher::kWhatMetadataDetected: 7710852843d304006e3ab333081fddda13b07193de8Robert Shih { 7720852843d304006e3ab333081fddda13b07193de8Robert Shih if (!mHasMetadata) { 7730852843d304006e3ab333081fddda13b07193de8Robert Shih mHasMetadata = true; 7740852843d304006e3ab333081fddda13b07193de8Robert Shih sp<AMessage> notify = mNotify->dup(); 7750852843d304006e3ab333081fddda13b07193de8Robert Shih notify->setInt32("what", kWhatMetadataDetected); 7760852843d304006e3ab333081fddda13b07193de8Robert Shih notify->post(); 7770852843d304006e3ab333081fddda13b07193de8Robert Shih } 7780852843d304006e3ab333081fddda13b07193de8Robert Shih break; 7790852843d304006e3ab333081fddda13b07193de8Robert Shih } 7800852843d304006e3ab333081fddda13b07193de8Robert Shih 78114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber default: 78214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber TRESPASS(); 78314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 78414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 78514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 78614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 78714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 788dcb89b3b505522efde173c105a851c412f947178Chong Zhang case kWhatChangeConfiguration: 789dcb89b3b505522efde173c105a851c412f947178Chong Zhang { 790dcb89b3b505522efde173c105a851c412f947178Chong Zhang onChangeConfiguration(msg); 791dcb89b3b505522efde173c105a851c412f947178Chong Zhang break; 792dcb89b3b505522efde173c105a851c412f947178Chong Zhang } 793dcb89b3b505522efde173c105a851c412f947178Chong Zhang 79414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case kWhatChangeConfiguration2: 79514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 79614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber onChangeConfiguration2(msg); 79714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 79814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 79914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 80014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case kWhatChangeConfiguration3: 80114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 80214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber onChangeConfiguration3(msg); 80314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 80414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 80514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 80614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case kWhatFinishDisconnect2: 80714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 80814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber onFinishDisconnect2(); 809a44153c1a57202fb538659eb50706e60454d6273Andreas Huber break; 81014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 811a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 812964adb17885185808398507d2de88665fe193ee2Chong Zhang case kWhatPollBuffering: 8130ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih { 814964adb17885185808398507d2de88665fe193ee2Chong Zhang int32_t generation; 815964adb17885185808398507d2de88665fe193ee2Chong Zhang CHECK(msg->findInt32("generation", &generation)); 816964adb17885185808398507d2de88665fe193ee2Chong Zhang if (generation == mPollBufferingGeneration) { 817964adb17885185808398507d2de88665fe193ee2Chong Zhang onPollBuffering(); 818964adb17885185808398507d2de88665fe193ee2Chong Zhang } 8190ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih break; 8200ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih } 8210ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih 822a44153c1a57202fb538659eb50706e60454d6273Andreas Huber default: 823a44153c1a57202fb538659eb50706e60454d6273Andreas Huber TRESPASS(); 824a44153c1a57202fb538659eb50706e60454d6273Andreas Huber break; 825a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 826a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 827a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 828a44153c1a57202fb538659eb50706e60454d6273Andreas Huber// static 829a44153c1a57202fb538659eb50706e60454d6273Andreas Huberint LiveSession::SortByBandwidth(const BandwidthItem *a, const BandwidthItem *b) { 830a44153c1a57202fb538659eb50706e60454d6273Andreas Huber if (a->mBandwidth < b->mBandwidth) { 831a44153c1a57202fb538659eb50706e60454d6273Andreas Huber return -1; 832a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } else if (a->mBandwidth == b->mBandwidth) { 833a44153c1a57202fb538659eb50706e60454d6273Andreas Huber return 0; 834a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 835a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 836a44153c1a57202fb538659eb50706e60454d6273Andreas Huber return 1; 837a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 838a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 8398ca002eedc747dd854b61cbe364b52c06869273fRobert Shih// static 8408ca002eedc747dd854b61cbe364b52c06869273fRobert ShihLiveSession::StreamType LiveSession::indexToType(int idx) { 8410852843d304006e3ab333081fddda13b07193de8Robert Shih CHECK(idx >= 0 && idx < kNumSources); 8428ca002eedc747dd854b61cbe364b52c06869273fRobert Shih return (StreamType)(1 << idx); 8438ca002eedc747dd854b61cbe364b52c06869273fRobert Shih} 8448ca002eedc747dd854b61cbe364b52c06869273fRobert Shih 845f69c996864844e8f669308af8412cede043062a2Robert Shih// static 846f69c996864844e8f669308af8412cede043062a2Robert Shihssize_t LiveSession::typeToIndex(int32_t type) { 847f69c996864844e8f669308af8412cede043062a2Robert Shih switch (type) { 848f69c996864844e8f669308af8412cede043062a2Robert Shih case STREAMTYPE_AUDIO: 849f69c996864844e8f669308af8412cede043062a2Robert Shih return 0; 850f69c996864844e8f669308af8412cede043062a2Robert Shih case STREAMTYPE_VIDEO: 851f69c996864844e8f669308af8412cede043062a2Robert Shih return 1; 852f69c996864844e8f669308af8412cede043062a2Robert Shih case STREAMTYPE_SUBTITLES: 853f69c996864844e8f669308af8412cede043062a2Robert Shih return 2; 8540852843d304006e3ab333081fddda13b07193de8Robert Shih case STREAMTYPE_METADATA: 8550852843d304006e3ab333081fddda13b07193de8Robert Shih return 3; 856f69c996864844e8f669308af8412cede043062a2Robert Shih default: 857f69c996864844e8f669308af8412cede043062a2Robert Shih return -1; 858f69c996864844e8f669308af8412cede043062a2Robert Shih }; 859f69c996864844e8f669308af8412cede043062a2Robert Shih return -1; 860f69c996864844e8f669308af8412cede043062a2Robert Shih} 861f69c996864844e8f669308af8412cede043062a2Robert Shih 862a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onConnect(const sp<AMessage> &msg) { 863a44153c1a57202fb538659eb50706e60454d6273Andreas Huber AString url; 864a44153c1a57202fb538659eb50706e60454d6273Andreas Huber CHECK(msg->findString("url", &url)); 865a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 866ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber KeyedVector<String8, String8> *headers = NULL; 867ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber if (!msg->findPointer("headers", (void **)&headers)) { 868ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber mExtraHeaders.clear(); 869ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber } else { 870ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber mExtraHeaders = *headers; 871ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber 872ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber delete headers; 873ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber headers = NULL; 874ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber } 875ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber 876a1df816c0677185534babba6ffc29970b048e52eLajos Molnar // TODO currently we don't know if we are coming here from incognito mode 877a1df816c0677185534babba6ffc29970b048e52eLajos Molnar ALOGI("onConnect %s", uriDebugString(url).c_str()); 878a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 879a44153c1a57202fb538659eb50706e60454d6273Andreas Huber mMasterURL = url; 880a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 8817e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber bool dummy; 88214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mPlaylist = fetchPlaylist(url.c_str(), NULL /* curPlaylistHash */, &dummy); 883ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber 88414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (mPlaylist == NULL) { 885a1df816c0677185534babba6ffc29970b048e52eLajos Molnar ALOGE("unable to fetch master playlist %s.", uriDebugString(url).c_str()); 886ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber 88714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber postPrepared(ERROR_IO); 888ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber return; 889ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber } 890a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 891964adb17885185808398507d2de88665fe193ee2Chong Zhang // create looper for fetchers 892964adb17885185808398507d2de88665fe193ee2Chong Zhang if (mFetcherLooper == NULL) { 893964adb17885185808398507d2de88665fe193ee2Chong Zhang mFetcherLooper = new ALooper(); 894964adb17885185808398507d2de88665fe193ee2Chong Zhang 895964adb17885185808398507d2de88665fe193ee2Chong Zhang mFetcherLooper->setName("Fetcher"); 896964adb17885185808398507d2de88665fe193ee2Chong Zhang mFetcherLooper->start(false, false); 897964adb17885185808398507d2de88665fe193ee2Chong Zhang } 898964adb17885185808398507d2de88665fe193ee2Chong Zhang 89914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // We trust the content provider to make a reasonable choice of preferred 90014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // initial bandwidth by listing it first in the variant playlist. 90114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // At startup we really don't have a good estimate on the available 90214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // network bandwidth since we haven't tranferred any data yet. Once 90314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // we have we can make a better informed choice. 90414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber size_t initialBandwidth = 0; 90514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber size_t initialBandwidthIndex = 0; 90614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 907a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang int32_t maxWidth = 0; 908a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang int32_t maxHeight = 0; 909a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang 91014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (mPlaylist->isVariantPlaylist()) { 911d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang Vector<BandwidthItem> itemsWithVideo; 91214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber for (size_t i = 0; i < mPlaylist->size(); ++i) { 913a44153c1a57202fb538659eb50706e60454d6273Andreas Huber BandwidthItem item; 914a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 91514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber item.mPlaylistIndex = i; 91614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 917a44153c1a57202fb538659eb50706e60454d6273Andreas Huber sp<AMessage> meta; 91814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber AString uri; 91914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mPlaylist->itemAt(i, &uri, &meta); 920a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 921a44153c1a57202fb538659eb50706e60454d6273Andreas Huber CHECK(meta->findInt32("bandwidth", (int32_t *)&item.mBandwidth)); 922a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 923a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang int32_t width, height; 924a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang if (meta->findInt32("width", &width)) { 925a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang maxWidth = max(maxWidth, width); 926a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang } 927a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang if (meta->findInt32("height", &height)) { 928a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang maxHeight = max(maxHeight, height); 929a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang } 930a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang 931a44153c1a57202fb538659eb50706e60454d6273Andreas Huber mBandwidthItems.push(item); 932d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (mPlaylist->hasType(i, "video")) { 933d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang itemsWithVideo.push(item); 934d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang } 935d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang } 936d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // remove the audio-only variants if we have at least one with video 937d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (!itemsWithVideo.empty() 938d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang && itemsWithVideo.size() < mBandwidthItems.size()) { 939d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang mBandwidthItems.clear(); 940d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang for (size_t i = 0; i < itemsWithVideo.size(); ++i) { 941d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang mBandwidthItems.push(itemsWithVideo[i]); 942d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang } 943a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 944a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 945a44153c1a57202fb538659eb50706e60454d6273Andreas Huber CHECK_GT(mBandwidthItems.size(), 0u); 946d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang initialBandwidth = mBandwidthItems[0].mBandwidth; 947a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 948a44153c1a57202fb538659eb50706e60454d6273Andreas Huber mBandwidthItems.sort(SortByBandwidth); 94914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 95014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber for (size_t i = 0; i < mBandwidthItems.size(); ++i) { 95114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (mBandwidthItems.itemAt(i).mBandwidth == initialBandwidth) { 95214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber initialBandwidthIndex = i; 95314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 95414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 95514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 95614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else { 95714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // dummy item. 95814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber BandwidthItem item; 95914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber item.mPlaylistIndex = 0; 96014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber item.mBandwidth = 0; 96114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mBandwidthItems.push(item); 962a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 963a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 964a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang mMaxWidth = maxWidth > 0 ? maxWidth : mMaxWidth; 965a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang mMaxHeight = maxHeight > 0 ? maxHeight : mMaxHeight; 966a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang 967309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mPlaylist->pickRandomMediaItems(); 968dcb89b3b505522efde173c105a851c412f947178Chong Zhang changeConfiguration( 969309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 0ll /* timeUs */, initialBandwidthIndex, false /* pickTrack */); 970a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 971a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 97214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::finishDisconnect() { 973a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang ALOGV("finishDisconnect"); 974a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 97514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // No reconfiguration is currently pending, make sure none will trigger 97614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // during disconnection either. 9771543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih cancelBandwidthSwitch(); 9781543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 979964adb17885185808398507d2de88665fe193ee2Chong Zhang // cancel buffer polling 980964adb17885185808398507d2de88665fe193ee2Chong Zhang cancelPollBuffering(); 9810ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih 98214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber for (size_t i = 0; i < mFetcherInfos.size(); ++i) { 98314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mFetcherInfos.valueAt(i).mFetcher->stopAsync(); 98414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 98514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 9861d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> msg = new AMessage(kWhatFinishDisconnect2, this); 987a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 98814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mContinuationCounter = mFetcherInfos.size(); 98914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mContinuation = msg; 990ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber 99114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (mContinuationCounter == 0) { 99214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber msg->post(); 99314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 99414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 99514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 99614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::onFinishDisconnect2() { 99714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mContinuation.clear(); 99814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 99914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mPacketSources.valueFor(STREAMTYPE_AUDIO)->signalEOS(ERROR_END_OF_STREAM); 100014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mPacketSources.valueFor(STREAMTYPE_VIDEO)->signalEOS(ERROR_END_OF_STREAM); 100114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 100214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mPacketSources.valueFor( 100314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber STREAMTYPE_SUBTITLES)->signalEOS(ERROR_END_OF_STREAM); 100414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 100514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AMessage> response = new AMessage; 100614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber response->setInt32("err", OK); 100714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 100814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber response->postReply(mDisconnectReplyID); 1009c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang mDisconnectReplyID.clear(); 101014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 101114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 101214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubersp<PlaylistFetcher> LiveSession::addFetcher(const char *uri) { 101314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ssize_t index = mFetcherInfos.indexOfKey(uri); 101414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 101514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (index >= 0) { 101614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return NULL; 101714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 101814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 10191d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> notify = new AMessage(kWhatFetcherNotify, this); 102014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->setString("uri", uri); 10211543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih notify->setInt32("switchGeneration", mSwitchGeneration); 102214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 102314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber FetcherInfo info; 102425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang info.mFetcher = new PlaylistFetcher( 102525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang notify, this, uri, mCurBandwidthIndex, mSubtitleGeneration); 102614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber info.mDurationUs = -1ll; 10271543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih info.mToBeRemoved = false; 1028a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang info.mToBeResumed = false; 1029964adb17885185808398507d2de88665fe193ee2Chong Zhang mFetcherLooper->registerHandler(info.mFetcher); 103014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 103114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mFetcherInfos.add(uri, info); 103214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 103314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return info.mFetcher; 1034a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 1035a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 10368dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih/* 10378dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * Illustration of parameters: 10388dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * 10398dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * 0 `range_offset` 10408dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * +------------+-------------------------------------------------------+--+--+ 10418dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * | | | next block to fetch | | | 10428dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * | | `source` handle => `out` buffer | | | | 10438dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * | `url` file |<--------- buffer size --------->|<--- `block_size` -->| | | 10448dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * | |<----------- `range_length` / buffer capacity ----------->| | 10458dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * |<------------------------------ file_size ------------------------------->| 10468dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * 10478dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * Special parameter values: 10488dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * - range_length == -1 means entire file 10498dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * - block_size == 0 means entire range 10508dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * 10518dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih */ 105243ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shihssize_t LiveSession::fetchFile( 10532aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber const char *url, sp<ABuffer> *out, 10548dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih int64_t range_offset, int64_t range_length, 10558dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih uint32_t block_size, /* download block size */ 105697194cdf8d67f362ef8c6dfdf607298c7e102b3bMarco Nelissen sp<DataSource> *source, /* to return and reuse source */ 1057a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang String8 *actualUrl, 1058a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang bool forceConnectHTTP /* force connect HTTP when resuing source */) { 10598dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih off64_t size; 10608dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih sp<DataSource> temp_source; 10618dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih if (source == NULL) { 10628dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih source = &temp_source; 10638dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih } 1064a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1065a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (*source == NULL || forceConnectHTTP) { 10668dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih if (!strncasecmp(url, "file://", 7)) { 10678dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih *source = new FileSource(url + 7); 10688dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih } else if (strncasecmp(url, "http://", 7) 10698dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih && strncasecmp(url, "https://", 8)) { 10708dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih return ERROR_UNSUPPORTED; 10718dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih } else { 10728dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih KeyedVector<String8, String8> headers = mExtraHeaders; 10738dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih if (range_offset > 0 || range_length >= 0) { 10748dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih headers.add( 10758dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih String8("Range"), 10768dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih String8( 1077a1e8944a21e5833b7aadc451776f11797f5f9273Elliott Hughes AStringPrintf( 10788dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih "bytes=%lld-%s", 10798dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih range_offset, 10808dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih range_length < 0 1081a1e8944a21e5833b7aadc451776f11797f5f9273Elliott Hughes ? "" : AStringPrintf("%lld", 10828dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih range_offset + range_length - 1).c_str()).c_str())); 10838dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih } 1084a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1085a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang HTTPBase* httpDataSource = 1086a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang (*source == NULL) ? mHTTPDataSource.get() : (HTTPBase*)source->get(); 1087a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang status_t err = httpDataSource->connect(url, &headers); 1088a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 10898dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih if (err != OK) { 10908dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih return err; 10918dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih } 1092a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1093a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (*source == NULL) { 1094a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang *source = mHTTPDataSource; 1095a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 1096a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1097a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1098a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 10998dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih status_t getSizeErr = (*source)->getSize(&size); 11008dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih if (getSizeErr != OK) { 1101a44153c1a57202fb538659eb50706e60454d6273Andreas Huber size = 65536; 1102a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1103a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 11048dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih sp<ABuffer> buffer = *out != NULL ? *out : new ABuffer(size); 11058dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih if (*out == NULL) { 11068dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih buffer->setRange(0, 0); 11078dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih } 1108a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 110943ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih ssize_t bytesRead = 0; 11108dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih // adjust range_length if only reading partial block 1111b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross if (block_size > 0 && (range_length == -1 || (int64_t)(buffer->size() + block_size) < range_length)) { 11128dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih range_length = buffer->size() + block_size; 11138dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih } 1114a44153c1a57202fb538659eb50706e60454d6273Andreas Huber for (;;) { 11158dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih // Only resize when we don't know the size. 1116a44153c1a57202fb538659eb50706e60454d6273Andreas Huber size_t bufferRemaining = buffer->capacity() - buffer->size(); 11178dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih if (bufferRemaining == 0 && getSizeErr != OK) { 11189aff25fb41f516ac26f9d1983a25402909f1e77aLeena Winterrowd size_t bufferIncrement = buffer->size() / 2; 11199aff25fb41f516ac26f9d1983a25402909f1e77aLeena Winterrowd if (bufferIncrement < 32768) { 11209aff25fb41f516ac26f9d1983a25402909f1e77aLeena Winterrowd bufferIncrement = 32768; 11219aff25fb41f516ac26f9d1983a25402909f1e77aLeena Winterrowd } 11229aff25fb41f516ac26f9d1983a25402909f1e77aLeena Winterrowd bufferRemaining = bufferIncrement; 1123a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1124b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross ALOGV("increasing download buffer to %zu bytes", 1125a44153c1a57202fb538659eb50706e60454d6273Andreas Huber buffer->size() + bufferRemaining); 1126a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1127a44153c1a57202fb538659eb50706e60454d6273Andreas Huber sp<ABuffer> copy = new ABuffer(buffer->size() + bufferRemaining); 1128a44153c1a57202fb538659eb50706e60454d6273Andreas Huber memcpy(copy->data(), buffer->data(), buffer->size()); 1129a44153c1a57202fb538659eb50706e60454d6273Andreas Huber copy->setRange(0, buffer->size()); 1130a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1131a44153c1a57202fb538659eb50706e60454d6273Andreas Huber buffer = copy; 1132a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1133a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 11342aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber size_t maxBytesToRead = bufferRemaining; 11352aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber if (range_length >= 0) { 11362aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber int64_t bytesLeftInRange = range_length - buffer->size(); 1137b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross if (bytesLeftInRange < (int64_t)maxBytesToRead) { 11382aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber maxBytesToRead = bytesLeftInRange; 11392aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber 11402aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber if (bytesLeftInRange == 0) { 11412aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber break; 11422aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber } 11432aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber } 11442aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber } 11452aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber 11468dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih // The DataSource is responsible for informing us of error (n < 0) or eof (n == 0) 11478dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih // to help us break out of the loop. 11488dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih ssize_t n = (*source)->readAt( 1149a44153c1a57202fb538659eb50706e60454d6273Andreas Huber buffer->size(), buffer->data() + buffer->size(), 11502aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber maxBytesToRead); 1151a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1152a44153c1a57202fb538659eb50706e60454d6273Andreas Huber if (n < 0) { 115320ad3a341a96e7746015ccb7369fa567897e11f6Andreas Huber return n; 1154a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1155a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1156a44153c1a57202fb538659eb50706e60454d6273Andreas Huber if (n == 0) { 1157a44153c1a57202fb538659eb50706e60454d6273Andreas Huber break; 1158a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1159a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1160a44153c1a57202fb538659eb50706e60454d6273Andreas Huber buffer->setRange(0, buffer->size() + (size_t)n); 116143ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih bytesRead += n; 1162a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1163a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1164a44153c1a57202fb538659eb50706e60454d6273Andreas Huber *out = buffer; 1165784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo if (actualUrl != NULL) { 116697194cdf8d67f362ef8c6dfdf607298c7e102b3bMarco Nelissen *actualUrl = (*source)->getUri(); 1167784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo if (actualUrl->isEmpty()) { 1168784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo *actualUrl = url; 1169784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo } 1170784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo } 1171a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 117243ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih return bytesRead; 1173a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 1174a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 117514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubersp<M3UParser> LiveSession::fetchPlaylist( 117614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber const char *url, uint8_t *curPlaylistHash, bool *unchanged) { 1177b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber ALOGV("fetchPlaylist '%s'", url); 1178b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber 11797e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber *unchanged = false; 11807e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber 1181a44153c1a57202fb538659eb50706e60454d6273Andreas Huber sp<ABuffer> buffer; 1182784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo String8 actualUrl; 118343ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih ssize_t err = fetchFile(url, &buffer, 0, -1, 0, NULL, &actualUrl); 1184a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1185d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // close off the connection after use 1186d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang mHTTPDataSource->disconnect(); 1187d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang 118843ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih if (err <= 0) { 1189a44153c1a57202fb538659eb50706e60454d6273Andreas Huber return NULL; 1190a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1191a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 11927e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber // MD5 functionality is not available on the simulator, treat all 11937e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber // playlists as changed. 11947e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber 11957e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber#if defined(HAVE_ANDROID_OS) 11967e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber uint8_t hash[16]; 11977e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber 11987e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber MD5_CTX m; 11997e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber MD5_Init(&m); 12007e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber MD5_Update(&m, buffer->data(), buffer->size()); 12017e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber 12027e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber MD5_Final(hash, &m); 12037e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber 120414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (curPlaylistHash != NULL && !memcmp(hash, curPlaylistHash, 16)) { 12057e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber // playlist unchanged 12067e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber *unchanged = true; 12077e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber 12087e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber return NULL; 12097e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber } 12107e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber 121114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (curPlaylistHash != NULL) { 121214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber memcpy(curPlaylistHash, hash, sizeof(hash)); 121314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 12147e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber#endif 12157e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber 1216a44153c1a57202fb538659eb50706e60454d6273Andreas Huber sp<M3UParser> playlist = 1217784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo new M3UParser(actualUrl.string(), buffer->data(), buffer->size()); 1218a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1219a44153c1a57202fb538659eb50706e60454d6273Andreas Huber if (playlist->initCheck() != OK) { 122029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("failed to parse .m3u8 playlist"); 12219067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber 1222a44153c1a57202fb538659eb50706e60454d6273Andreas Huber return NULL; 1223a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1224a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1225a44153c1a57202fb538659eb50706e60454d6273Andreas Huber return playlist; 1226a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 1227a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1228b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe#if 0 1229a44153c1a57202fb538659eb50706e60454d6273Andreas Huberstatic double uniformRand() { 1230a44153c1a57202fb538659eb50706e60454d6273Andreas Huber return (double)rand() / RAND_MAX; 1231a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 1232b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe#endif 1233a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 12340852843d304006e3ab333081fddda13b07193de8Robert Shihbool LiveSession::UriIsSameAsIndex(const AString &uri, int32_t i, bool newUri) { 12350852843d304006e3ab333081fddda13b07193de8Robert Shih ALOGI("[timed_id3] i %d UriIsSameAsIndex newUri %s, %s", i, 12360852843d304006e3ab333081fddda13b07193de8Robert Shih newUri ? "true" : "false", 12370852843d304006e3ab333081fddda13b07193de8Robert Shih newUri ? mStreams[i].mNewUri.c_str() : mStreams[i].mUri.c_str()); 12380852843d304006e3ab333081fddda13b07193de8Robert Shih return i >= 0 12390852843d304006e3ab333081fddda13b07193de8Robert Shih && ((!newUri && uri == mStreams[i].mUri) 12400852843d304006e3ab333081fddda13b07193de8Robert Shih || (newUri && uri == mStreams[i].mNewUri)); 12410852843d304006e3ab333081fddda13b07193de8Robert Shih} 12420852843d304006e3ab333081fddda13b07193de8Robert Shih 12430852843d304006e3ab333081fddda13b07193de8Robert Shihsp<AnotherPacketSource> LiveSession::getPacketSourceForStreamIndex( 12440852843d304006e3ab333081fddda13b07193de8Robert Shih size_t trackIndex, bool newUri) { 12450852843d304006e3ab333081fddda13b07193de8Robert Shih StreamType type = indexToType(trackIndex); 12460852843d304006e3ab333081fddda13b07193de8Robert Shih sp<AnotherPacketSource> source = NULL; 12470852843d304006e3ab333081fddda13b07193de8Robert Shih if (newUri) { 12480852843d304006e3ab333081fddda13b07193de8Robert Shih source = mPacketSources2.valueFor(type); 12490852843d304006e3ab333081fddda13b07193de8Robert Shih source->clear(); 12500852843d304006e3ab333081fddda13b07193de8Robert Shih } else { 12510852843d304006e3ab333081fddda13b07193de8Robert Shih source = mPacketSources.valueFor(type); 12520852843d304006e3ab333081fddda13b07193de8Robert Shih }; 12530852843d304006e3ab333081fddda13b07193de8Robert Shih return source; 12540852843d304006e3ab333081fddda13b07193de8Robert Shih} 12550852843d304006e3ab333081fddda13b07193de8Robert Shih 12560852843d304006e3ab333081fddda13b07193de8Robert Shihsp<AnotherPacketSource> LiveSession::getMetadataSource( 12570852843d304006e3ab333081fddda13b07193de8Robert Shih sp<AnotherPacketSource> sources[kNumSources], uint32_t streamMask, bool newUri) { 12580852843d304006e3ab333081fddda13b07193de8Robert Shih // todo: One case where the following strategy can fail is when audio and video 12590852843d304006e3ab333081fddda13b07193de8Robert Shih // are in separate playlists, both are transport streams, and the metadata 12600852843d304006e3ab333081fddda13b07193de8Robert Shih // is actually contained in the audio stream. 12610852843d304006e3ab333081fddda13b07193de8Robert Shih ALOGV("[timed_id3] getMetadataSourceForUri streamMask %x newUri %s", 12620852843d304006e3ab333081fddda13b07193de8Robert Shih streamMask, newUri ? "true" : "false"); 12630852843d304006e3ab333081fddda13b07193de8Robert Shih 12640852843d304006e3ab333081fddda13b07193de8Robert Shih if ((sources[kVideoIndex] != NULL) // video fetcher; or ... 12650852843d304006e3ab333081fddda13b07193de8Robert Shih || (!(streamMask & STREAMTYPE_VIDEO) && sources[kAudioIndex] != NULL)) { 12660852843d304006e3ab333081fddda13b07193de8Robert Shih // ... audio fetcher for audio only variant 12670852843d304006e3ab333081fddda13b07193de8Robert Shih return getPacketSourceForStreamIndex(kMetaDataIndex, newUri); 12680852843d304006e3ab333081fddda13b07193de8Robert Shih } 12690852843d304006e3ab333081fddda13b07193de8Robert Shih 12700852843d304006e3ab333081fddda13b07193de8Robert Shih return NULL; 12710852843d304006e3ab333081fddda13b07193de8Robert Shih} 12720852843d304006e3ab333081fddda13b07193de8Robert Shih 12737c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangbool LiveSession::resumeFetcher( 12747c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang const AString &uri, uint32_t streamMask, int64_t timeUs, bool newUri) { 12757c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ssize_t index = mFetcherInfos.indexOfKey(uri); 12767c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (index < 0) { 12777c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGE("did not find fetcher for uri: %s", uri.c_str()); 12787c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return false; 12797c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 12807c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 12817c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang bool resume = false; 12820852843d304006e3ab333081fddda13b07193de8Robert Shih sp<AnotherPacketSource> sources[kNumSources]; 12837c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang for (size_t i = 0; i < kMaxStreams; ++i) { 12840852843d304006e3ab333081fddda13b07193de8Robert Shih if ((streamMask & indexToType(i)) && UriIsSameAsIndex(uri, i, newUri)) { 12857c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang resume = true; 12860852843d304006e3ab333081fddda13b07193de8Robert Shih sources[i] = getPacketSourceForStreamIndex(i, newUri); 12877c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 12887c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 12897c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 12907c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (resume) { 129125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang sp<PlaylistFetcher> &fetcher = mFetcherInfos.editValueAt(index).mFetcher; 12927c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang SeekMode seekMode = newUri ? kSeekModeNextSample : kSeekModeExactPosition; 129325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 129425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("resuming fetcher-%d, timeUs=%lld, seekMode=%d", 129525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang fetcher->getFetcherID(), (long long)timeUs, seekMode); 129625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 129725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang fetcher->startAsync( 12987c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sources[kAudioIndex], 12997c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sources[kVideoIndex], 13007c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sources[kSubtitleIndex], 13010852843d304006e3ab333081fddda13b07193de8Robert Shih getMetadataSource(sources, streamMask, newUri), 13027c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang timeUs, -1, -1, seekMode); 13037c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 13047c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 13057c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return resume; 13067c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang} 13077c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 1308a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhangfloat LiveSession::getAbortThreshold( 1309a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang ssize_t currentBWIndex, ssize_t targetBWIndex) const { 1310a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang float abortThreshold = -1.0f; 1311a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (currentBWIndex > 0 && targetBWIndex < currentBWIndex) { 1312a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang /* 1313a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang If we're switching down, we need to decide whether to 1314a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1315a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1) finish last segment of high-bandwidth variant, or 1316a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 2) abort last segment of high-bandwidth variant, and fetch an 1317a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang overlapping portion from low-bandwidth variant. 1318a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1319a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang Here we try to maximize the amount of buffer left when the 1320a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang switch point is met. Given the following parameters: 1321a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1322a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang B: our current buffering level in seconds 1323a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang T: target duration in seconds 1324a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang X: sample duration in seconds remain to fetch in last segment 1325a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang bw0: bandwidth of old variant (as specified in playlist) 1326a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang bw1: bandwidth of new variant (as specified in playlist) 1327a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang bw: measured bandwidth available 1328a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1329a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang If we choose 1), when switch happens at the end of current 1330a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang segment, our buffering will be 1331a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang B + X - X * bw0 / bw 1332a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1333a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang If we choose 2), when switch happens where we aborted current 1334a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang segment, our buffering will be 1335a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang B - (T - X) * bw1 / bw 1336a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1337a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang We should only choose 1) if 1338a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang X/T < bw1 / (bw1 + bw0 - bw) 1339a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang */ 1340a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 13417c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // Taking the measured current bandwidth at 50% face value only, 13427c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // as our bandwidth estimation is a lagging indicator. Being 13437c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // conservative on this, we prefer switching to lower bandwidth 13447c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // unless we're really confident finishing up the last segment 13457c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // of higher bandwidth will be fast. 1346a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang CHECK(mLastBandwidthBps >= 0); 1347a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang abortThreshold = 1348a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang (float)mBandwidthItems.itemAt(targetBWIndex).mBandwidth 1349a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang / ((float)mBandwidthItems.itemAt(targetBWIndex).mBandwidth 1350a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang + (float)mBandwidthItems.itemAt(currentBWIndex).mBandwidth 13517c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang - (float)mLastBandwidthBps * 0.5f); 1352a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (abortThreshold < 0.0f) { 1353a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang abortThreshold = -1.0f; // do not abort 1354a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 1355a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang ALOGV("Switching Down: bps %ld => %ld, measured %d, abort ratio %.2f", 1356a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mBandwidthItems.itemAt(currentBWIndex).mBandwidth, 1357a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mBandwidthItems.itemAt(targetBWIndex).mBandwidth, 1358a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mLastBandwidthBps, 1359a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang abortThreshold); 1360a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 1361a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang return abortThreshold; 1362a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang} 1363a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1364538b6d22a3578c0201d48f8548289aa254d81484Chong Zhangvoid LiveSession::addBandwidthMeasurement(size_t numBytes, int64_t delayUs) { 1365538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mBandwidthEstimator->addBandwidthMeasurement(numBytes, delayUs); 1366538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang} 1367538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 1368538b6d22a3578c0201d48f8548289aa254d81484Chong Zhangsize_t LiveSession::getBandwidthIndex(int32_t bandwidthBps) { 1369538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang if (mBandwidthItems.size() < 2) { 1370538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang // shouldn't be here if we only have 1 bandwidth, check 1371538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang // logic to get rid of redundant bandwidth polling 1372538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang ALOGW("getBandwidthIndex() called for single bandwidth playlist!"); 1373a44153c1a57202fb538659eb50706e60454d6273Andreas Huber return 0; 1374a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1375a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1376a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#if 1 1377a44153c1a57202fb538659eb50706e60454d6273Andreas Huber char value[PROPERTY_VALUE_MAX]; 1378673158582c9589cee1d5e4d7c79622609938b8f8Andreas Huber ssize_t index = -1; 137914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (property_get("media.httplive.bw-index", value, NULL)) { 1380a44153c1a57202fb538659eb50706e60454d6273Andreas Huber char *end; 138114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber index = strtol(value, &end, 10); 138214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(end > value && *end == '\0'); 138314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 138414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (index >= 0 && (size_t)index >= mBandwidthItems.size()) { 138514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber index = mBandwidthItems.size() - 1; 1386a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1387a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1388a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 138914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (index < 0) { 139014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber char value[PROPERTY_VALUE_MAX]; 139114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (property_get("media.httplive.max-bw", value, NULL)) { 139214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber char *end; 139314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber long maxBw = strtoul(value, &end, 10); 139414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (end > value && *end == '\0') { 139514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (maxBw > 0 && bandwidthBps > maxBw) { 139614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGV("bandwidth capped to %ld bps", maxBw); 139714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber bandwidthBps = maxBw; 139814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 139914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 140014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 1401a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 140214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // Pick the highest bandwidth stream below or equal to estimated bandwidth. 140314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 140414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber index = mBandwidthItems.size() - 1; 140500598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih while (index > 0) { 1406538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang // be conservative (70%) to avoid overestimating and immediately 1407538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang // switching down again. 1408538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang size_t adjustedBandwidthBps = bandwidthBps * 7 / 10; 140900598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih if (mBandwidthItems.itemAt(index).mBandwidth <= adjustedBandwidthBps) { 141000598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih break; 141100598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih } 141214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber --index; 141314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 1414a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1415a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0 1416a44153c1a57202fb538659eb50706e60454d6273Andreas Huber // Change bandwidth at random() 1417a44153c1a57202fb538659eb50706e60454d6273Andreas Huber size_t index = uniformRand() * mBandwidthItems.size(); 1418a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0 1419a44153c1a57202fb538659eb50706e60454d6273Andreas Huber // There's a 50% chance to stay on the current bandwidth and 1420a44153c1a57202fb538659eb50706e60454d6273Andreas Huber // a 50% chance to switch to the next higher bandwidth (wrapping around 1421a44153c1a57202fb538659eb50706e60454d6273Andreas Huber // to lowest) 1422a44153c1a57202fb538659eb50706e60454d6273Andreas Huber const size_t kMinIndex = 0; 1423a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1424309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih static ssize_t mCurBandwidthIndex = -1; 142514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 1426a44153c1a57202fb538659eb50706e60454d6273Andreas Huber size_t index; 1427309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (mCurBandwidthIndex < 0) { 1428a44153c1a57202fb538659eb50706e60454d6273Andreas Huber index = kMinIndex; 1429a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } else if (uniformRand() < 0.5) { 1430309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih index = (size_t)mCurBandwidthIndex; 1431a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } else { 1432309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih index = mCurBandwidthIndex + 1; 1433a44153c1a57202fb538659eb50706e60454d6273Andreas Huber if (index == mBandwidthItems.size()) { 1434a44153c1a57202fb538659eb50706e60454d6273Andreas Huber index = kMinIndex; 1435a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1436a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1437309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mCurBandwidthIndex = index; 1438a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0 1439a44153c1a57202fb538659eb50706e60454d6273Andreas Huber // Pick the highest bandwidth stream below or equal to 1.2 Mbit/sec 1440a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1441a44153c1a57202fb538659eb50706e60454d6273Andreas Huber size_t index = mBandwidthItems.size() - 1; 1442a44153c1a57202fb538659eb50706e60454d6273Andreas Huber while (index > 0 && mBandwidthItems.itemAt(index).mBandwidth > 1200000) { 1443a44153c1a57202fb538659eb50706e60454d6273Andreas Huber --index; 1444a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 144514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#elif 1 144614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber char value[PROPERTY_VALUE_MAX]; 144714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber size_t index; 144814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (property_get("media.httplive.bw-index", value, NULL)) { 144914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber char *end; 145014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber index = strtoul(value, &end, 10); 145114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(end > value && *end == '\0'); 145214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 145314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (index >= mBandwidthItems.size()) { 145414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber index = mBandwidthItems.size() - 1; 145514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 145614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else { 145714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber index = 0; 145814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 1459a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#else 1460a44153c1a57202fb538659eb50706e60454d6273Andreas Huber size_t index = mBandwidthItems.size() - 1; // Highest bandwidth stream 1461a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#endif 1462a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 146314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK_GE(index, 0); 146414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 1465a44153c1a57202fb538659eb50706e60454d6273Andreas Huber return index; 1466a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 1467a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1468d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong ZhangHLSTime LiveSession::latestMediaSegmentStartTime() const { 1469d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang HLSTime audioTime(mPacketSources.valueFor( 1470d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang STREAMTYPE_AUDIO)->getLatestDequeuedMeta()); 1471b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih 1472d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang HLSTime videoTime(mPacketSources.valueFor( 1473d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang STREAMTYPE_VIDEO)->getLatestDequeuedMeta()); 1474b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih 1475d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang return audioTime < videoTime ? videoTime : audioTime; 1476b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih} 1477b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih 1478a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnarvoid LiveSession::onSeek(const sp<AMessage> &msg) { 147914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int64_t timeUs; 148014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->findInt64("timeUs", &timeUs)); 1481a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar changeConfiguration(timeUs); 14827e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber} 14837e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber 148414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::getDuration(int64_t *durationUs) const { 1485895651b07fec30b0f9b0d2499599a179d95c9be4Wei Jia int64_t maxDurationUs = -1ll; 148614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber for (size_t i = 0; i < mFetcherInfos.size(); ++i) { 148714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int64_t fetcherDurationUs = mFetcherInfos.valueAt(i).mDurationUs; 1488b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber 1489895651b07fec30b0f9b0d2499599a179d95c9be4Wei Jia if (fetcherDurationUs > maxDurationUs) { 149014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber maxDurationUs = fetcherDurationUs; 1491a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1492a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1493a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 149414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber *durationUs = maxDurationUs; 1495a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 149614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return OK; 149714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 14980f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber 149914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberbool LiveSession::isSeekable() const { 150014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int64_t durationUs; 150114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return getDuration(&durationUs) == OK && durationUs >= 0; 150214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 15030f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber 150414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberbool LiveSession::hasDynamicDuration() const { 150514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return false; 150614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 15070f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber 1508404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhangsize_t LiveSession::getTrackCount() const { 15099d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih if (mPlaylist == NULL) { 15109d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih return 0; 15119d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih } else { 15120852843d304006e3ab333081fddda13b07193de8Robert Shih return mPlaylist->getTrackCount() + (mHasMetadata ? 1 : 0); 15139d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih } 1514404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang} 1515404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang 1516404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhangsp<AMessage> LiveSession::getTrackInfo(size_t trackIndex) const { 15179d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih if (mPlaylist == NULL) { 15189d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih return NULL; 15199d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih } else { 15200852843d304006e3ab333081fddda13b07193de8Robert Shih if (trackIndex == mPlaylist->getTrackCount() && mHasMetadata) { 15210852843d304006e3ab333081fddda13b07193de8Robert Shih sp<AMessage> format = new AMessage(); 15220852843d304006e3ab333081fddda13b07193de8Robert Shih format->setInt32("type", MEDIA_TRACK_TYPE_METADATA); 15230852843d304006e3ab333081fddda13b07193de8Robert Shih format->setString("language", "und"); 15240852843d304006e3ab333081fddda13b07193de8Robert Shih format->setString("mime", MEDIA_MIMETYPE_DATA_METADATA); 15250852843d304006e3ab333081fddda13b07193de8Robert Shih return format; 15260852843d304006e3ab333081fddda13b07193de8Robert Shih } 15279d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih return mPlaylist->getTrackInfo(trackIndex); 15289d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih } 1529dcb89b3b505522efde173c105a851c412f947178Chong Zhang} 1530dcb89b3b505522efde173c105a851c412f947178Chong Zhang 1531dcb89b3b505522efde173c105a851c412f947178Chong Zhangstatus_t LiveSession::selectTrack(size_t index, bool select) { 1532b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih if (mPlaylist == NULL) { 1533b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih return INVALID_OPERATION; 1534b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih } 1535b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih 153625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("selectTrack: index=%zu, select=%d, mSubtitleGen=%d++", 153725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang index, select, mSubtitleGeneration); 153825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 1539b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih ++mSubtitleGeneration; 1540dcb89b3b505522efde173c105a851c412f947178Chong Zhang status_t err = mPlaylist->selectTrack(index, select); 1541dcb89b3b505522efde173c105a851c412f947178Chong Zhang if (err == OK) { 15421d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> msg = new AMessage(kWhatChangeConfiguration, this); 1543309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih msg->setInt32("pickTrack", select); 1544309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih msg->post(); 1545dcb89b3b505522efde173c105a851c412f947178Chong Zhang } 1546dcb89b3b505522efde173c105a851c412f947178Chong Zhang return err; 1547dcb89b3b505522efde173c105a851c412f947178Chong Zhang} 1548dcb89b3b505522efde173c105a851c412f947178Chong Zhang 154989bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shihssize_t LiveSession::getSelectedTrack(media_track_type type) const { 155089bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih if (mPlaylist == NULL) { 155189bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih return -1; 155289bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih } else { 155389bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih return mPlaylist->getSelectedTrack(type); 155489bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih } 155589bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih} 155689bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih 1557dcb89b3b505522efde173c105a851c412f947178Chong Zhangvoid LiveSession::changeConfiguration( 15587c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang int64_t timeUs, ssize_t bandwidthIndex, bool pickTrack) { 155925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("changeConfiguration: timeUs=%lld us, bwIndex=%zd, pickTrack=%d", 156025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang (long long)timeUs, bandwidthIndex, pickTrack); 156125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 15621543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih cancelBandwidthSwitch(); 15631543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 156414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(!mReconfigurationInProgress); 156514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mReconfigurationInProgress = true; 15667c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (bandwidthIndex >= 0) { 15677c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mOrigBandwidthIndex = mCurBandwidthIndex; 15687c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mCurBandwidthIndex = bandwidthIndex; 15698464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang if (mOrigBandwidthIndex != mCurBandwidthIndex) { 15708464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang ALOGI("#### Starting Bandwidth Switch: %zd => %zd", 15718464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang mOrigBandwidthIndex, mCurBandwidthIndex); 15728464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang } 15737c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 15747c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang CHECK_LT(mCurBandwidthIndex, mBandwidthItems.size()); 15757c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang const BandwidthItem &item = mBandwidthItems.itemAt(mCurBandwidthIndex); 1576a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 15771543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih uint32_t streamMask = 0; // streams that should be fetched by the new fetcher 15781543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih uint32_t resumeMask = 0; // streams that should be fetched by the original fetcher 1579a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 15808ca002eedc747dd854b61cbe364b52c06869273fRobert Shih AString URIs[kMaxStreams]; 15818ca002eedc747dd854b61cbe364b52c06869273fRobert Shih for (size_t i = 0; i < kMaxStreams; ++i) { 15828ca002eedc747dd854b61cbe364b52c06869273fRobert Shih if (mPlaylist->getTypeURI(item.mPlaylistIndex, mStreams[i].mType, &URIs[i])) { 15838ca002eedc747dd854b61cbe364b52c06869273fRobert Shih streamMask |= indexToType(i); 15848ca002eedc747dd854b61cbe364b52c06869273fRobert Shih } 158514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 1586aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber 158714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // Step 1, stop and discard fetchers that are no longer needed. 158814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // Pause those that we'll reuse. 158914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber for (size_t i = 0; i < mFetcherInfos.size(); ++i) { 15907c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // skip fetchers that are marked mToBeRemoved, 15917c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // these are done and can't be reused 15927c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (mFetcherInfos[i].mToBeRemoved) { 15937c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang continue; 15947c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 15957c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 159614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber const AString &uri = mFetcherInfos.keyAt(i); 1597d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang sp<PlaylistFetcher> &fetcher = mFetcherInfos.editValueAt(i).mFetcher; 1598aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber 1599d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang bool discardFetcher = true, delayRemoval = false; 1600c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang for (size_t j = 0; j < kMaxStreams; ++j) { 1601c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang StreamType type = indexToType(j); 1602c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang if ((streamMask & type) && uri == URIs[j]) { 1603c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang resumeMask |= type; 1604c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang streamMask &= ~type; 1605c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang discardFetcher = false; 16066801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber } 160714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 1608d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // Delay fetcher removal if not picking tracks, AND old fetcher 1609d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // has stream mask that overlaps new variant. (Okay to discard 1610d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // old fetcher now, if completely no overlap.) 1611d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (discardFetcher && timeUs < 0ll && !pickTrack 1612d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang && (fetcher->getStreamTypeMask() & streamMask)) { 1613d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang discardFetcher = false; 1614d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang delayRemoval = true; 1615d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang } 1616a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 161714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (discardFetcher) { 161825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("discarding fetcher-%d", fetcher->getFetcherID()); 1619d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang fetcher->stopAsync(); 16206801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber } else { 1621a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang float threshold = -1.0f; // always finish fetching by default 1622a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (timeUs >= 0ll) { 1623a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // seeking, no need to finish fetching 1624a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang threshold = 0.0f; 1625d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang } else if (delayRemoval) { 1626a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // adapting, abort if remaining of current segment is over threshold 1627a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang threshold = getAbortThreshold( 16287c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mOrigBandwidthIndex, mCurBandwidthIndex); 1629a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 1630a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 163125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("pausing fetcher-%d, threshold=%.2f", 163225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang fetcher->getFetcherID(), threshold); 1633d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang fetcher->pauseAsync(threshold); 16346801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber } 1635a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1636a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 16371543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih sp<AMessage> msg; 16381543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih if (timeUs < 0ll) { 1639309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih // skip onChangeConfiguration2 (decoder destruction) if not seeking. 16401d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar msg = new AMessage(kWhatChangeConfiguration3, this); 16411543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } else { 16421d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar msg = new AMessage(kWhatChangeConfiguration2, this); 16431543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 164414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber msg->setInt32("streamMask", streamMask); 16451543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih msg->setInt32("resumeMask", resumeMask); 1646309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih msg->setInt32("pickTrack", pickTrack); 164714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber msg->setInt64("timeUs", timeUs); 16488ca002eedc747dd854b61cbe364b52c06869273fRobert Shih for (size_t i = 0; i < kMaxStreams; ++i) { 1649309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if ((streamMask | resumeMask) & indexToType(i)) { 16508ca002eedc747dd854b61cbe364b52c06869273fRobert Shih msg->setString(mStreams[i].uriKey().c_str(), URIs[i].c_str()); 16518ca002eedc747dd854b61cbe364b52c06869273fRobert Shih } 16526e6b1cae2bac1b78205cefab8e4e9e9538982965Andreas Huber } 1653a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 165414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // Every time a fetcher acknowledges the stopAsync or pauseAsync request 165514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // we'll decrement mContinuationCounter, once it reaches zero, i.e. all 165614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // fetchers have completed their asynchronous operation, we'll post 165714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // mContinuation, which then is handled below in onChangeConfiguration2. 165814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mContinuationCounter = mFetcherInfos.size(); 165914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mContinuation = msg; 166088b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber 166114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (mContinuationCounter == 0) { 166214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber msg->post(); 166388b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber } 166414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 1665a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1666dcb89b3b505522efde173c105a851c412f947178Chong Zhangvoid LiveSession::onChangeConfiguration(const sp<AMessage> &msg) { 166725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("onChangeConfiguration"); 166825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 1669dcb89b3b505522efde173c105a851c412f947178Chong Zhang if (!mReconfigurationInProgress) { 16707c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang int32_t pickTrack = 0; 1671309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih msg->findInt32("pickTrack", &pickTrack); 16727c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang changeConfiguration(-1ll /* timeUs */, -1, pickTrack); 1673dcb89b3b505522efde173c105a851c412f947178Chong Zhang } else { 1674dcb89b3b505522efde173c105a851c412f947178Chong Zhang msg->post(1000000ll); // retry in 1 sec 1675dcb89b3b505522efde173c105a851c412f947178Chong Zhang } 1676dcb89b3b505522efde173c105a851c412f947178Chong Zhang} 1677dcb89b3b505522efde173c105a851c412f947178Chong Zhang 167814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::onChangeConfiguration2(const sp<AMessage> &msg) { 167925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("onChangeConfiguration2"); 168025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 168114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mContinuation.clear(); 1682bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber 168314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // All fetchers are either suspended or have been removed now. 1684bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber 1685964adb17885185808398507d2de88665fe193ee2Chong Zhang // If we're seeking, clear all packet sources before we report 1686964adb17885185808398507d2de88665fe193ee2Chong Zhang // seek complete, to prevent decoder from pulling stale data. 1687964adb17885185808398507d2de88665fe193ee2Chong Zhang int64_t timeUs; 1688964adb17885185808398507d2de88665fe193ee2Chong Zhang CHECK(msg->findInt64("timeUs", &timeUs)); 1689964adb17885185808398507d2de88665fe193ee2Chong Zhang 1690964adb17885185808398507d2de88665fe193ee2Chong Zhang if (timeUs >= 0) { 1691964adb17885185808398507d2de88665fe193ee2Chong Zhang mLastSeekTimeUs = timeUs; 16928464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang mLastDequeuedTimeUs = timeUs; 1693964adb17885185808398507d2de88665fe193ee2Chong Zhang 1694964adb17885185808398507d2de88665fe193ee2Chong Zhang for (size_t i = 0; i < mPacketSources.size(); i++) { 1695964adb17885185808398507d2de88665fe193ee2Chong Zhang mPacketSources.editValueAt(i)->clear(); 1696964adb17885185808398507d2de88665fe193ee2Chong Zhang } 1697964adb17885185808398507d2de88665fe193ee2Chong Zhang 16987c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang for (size_t i = 0; i < kMaxStreams; ++i) { 16997c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mStreams[i].mCurDiscontinuitySeq = 0; 17007c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 17017c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 1702964adb17885185808398507d2de88665fe193ee2Chong Zhang mDiscontinuityOffsetTimesUs.clear(); 1703964adb17885185808398507d2de88665fe193ee2Chong Zhang mDiscontinuityAbsStartTimesUs.clear(); 1704964adb17885185808398507d2de88665fe193ee2Chong Zhang 1705c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang if (mSeekReplyID != NULL) { 1706964adb17885185808398507d2de88665fe193ee2Chong Zhang CHECK(mSeekReply != NULL); 1707964adb17885185808398507d2de88665fe193ee2Chong Zhang mSeekReply->setInt32("err", OK); 1708964adb17885185808398507d2de88665fe193ee2Chong Zhang mSeekReply->postReply(mSeekReplyID); 1709c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang mSeekReplyID.clear(); 1710964adb17885185808398507d2de88665fe193ee2Chong Zhang mSeekReply.clear(); 1711964adb17885185808398507d2de88665fe193ee2Chong Zhang } 17127c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 17137c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // restart buffer polling after seek becauese previous 17147c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // buffering position is no longer valid. 17157c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang restartPollBuffering(); 1716964adb17885185808398507d2de88665fe193ee2Chong Zhang } 1717964adb17885185808398507d2de88665fe193ee2Chong Zhang 1718309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih uint32_t streamMask, resumeMask; 171914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->findInt32("streamMask", (int32_t *)&streamMask)); 1720309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih CHECK(msg->findInt32("resumeMask", (int32_t *)&resumeMask)); 1721309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 1722309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih streamMask |= resumeMask; 1723bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber 17248ca002eedc747dd854b61cbe364b52c06869273fRobert Shih AString URIs[kMaxStreams]; 17258ca002eedc747dd854b61cbe364b52c06869273fRobert Shih for (size_t i = 0; i < kMaxStreams; ++i) { 17268ca002eedc747dd854b61cbe364b52c06869273fRobert Shih if (streamMask & indexToType(i)) { 17278ca002eedc747dd854b61cbe364b52c06869273fRobert Shih const AString &uriKey = mStreams[i].uriKey(); 17288ca002eedc747dd854b61cbe364b52c06869273fRobert Shih CHECK(msg->findString(uriKey.c_str(), &URIs[i])); 17298ca002eedc747dd854b61cbe364b52c06869273fRobert Shih ALOGV("%s = '%s'", uriKey.c_str(), URIs[i].c_str()); 17308ca002eedc747dd854b61cbe364b52c06869273fRobert Shih } 173122fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber } 17323831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber 173314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber uint32_t changedMask = 0; 17348ca002eedc747dd854b61cbe364b52c06869273fRobert Shih for (size_t i = 0; i < kMaxStreams && i != kSubtitleIndex; ++i) { 1735c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // stream URI could change even if onChangeConfiguration2 is only 1736c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // used for seek. Seek could happen during a bw switch, in this 1737c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // case bw switch will be cancelled, but the seekTo position will 1738c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // fetch from the new URI. 1739c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang if ((mStreamMask & streamMask & indexToType(i)) 1740c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang && !mStreams[i].mUri.empty() 1741c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang && !(URIs[i] == mStreams[i].mUri)) { 17424604458dfe57b0e91a464aefafea50ae7b9876c1Chong Zhang ALOGV("stream %zu changed: oldURI %s, newURI %s", i, 1743c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang mStreams[i].mUri.c_str(), URIs[i].c_str()); 1744c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang sp<AnotherPacketSource> source = mPacketSources.valueFor(indexToType(i)); 17458464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang if (source->getLatestDequeuedMeta() != NULL) { 17468464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang source->queueDiscontinuity( 17478464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang ATSParser::DISCONTINUITY_FORMATCHANGE, NULL, true); 17488464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang } 1749c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang } 1750c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // Determine which decoders to shutdown on the player side, 1751c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // a decoder has to be shutdown if its streamtype was active 1752c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // before but now longer isn't. 1753c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang if ((mStreamMask & ~streamMask & indexToType(i))) { 17548ca002eedc747dd854b61cbe364b52c06869273fRobert Shih changedMask |= indexToType(i); 17558ca002eedc747dd854b61cbe364b52c06869273fRobert Shih } 1756b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber } 1757b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber 175814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (changedMask == 0) { 175914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // If nothing changed as far as the audio/video decoders 176014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // are concerned we can proceed. 176114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber onChangeConfiguration3(msg); 176214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return; 176314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 176443c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber 176514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // Something changed, inform the player which will shutdown the 176614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // corresponding decoders and will post the reply once that's done. 176714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // Handling the reply will continue executing below in 176814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // onChangeConfiguration3. 176914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AMessage> notify = mNotify->dup(); 177014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->setInt32("what", kWhatStreamsChanged); 177114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->setInt32("changedMask", changedMask); 177220f725ebcef13ded1b4b85c61c8a4b37cd030656Andreas Huber 177314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber msg->setWhat(kWhatChangeConfiguration3); 17741d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar msg->setTarget(this); 1775b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber 177614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->setMessage("reply", msg); 177714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->post(); 177814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 1779b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber 178014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::onChangeConfiguration3(const sp<AMessage> &msg) { 17811543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih mContinuation.clear(); 178214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // All remaining fetchers are still suspended, the player has shutdown 178314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // any decoders that needed it. 1784b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber 17851543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih uint32_t streamMask, resumeMask; 178614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->findInt32("streamMask", (int32_t *)&streamMask)); 17871543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih CHECK(msg->findInt32("resumeMask", (int32_t *)&resumeMask)); 1788a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1789d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang mNewStreamMask = streamMask | resumeMask; 1790d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang 179114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int64_t timeUs; 1792309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih int32_t pickTrack; 17931543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih bool switching = false; 179414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->findInt64("timeUs", &timeUs)); 1795309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih CHECK(msg->findInt32("pickTrack", &pickTrack)); 1796a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 179714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (timeUs < 0ll) { 1798309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (!pickTrack) { 1799d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // mSwapMask contains streams that are in both old and new variant, 1800d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // (in mNewStreamMask & mStreamMask) but with different URIs 1801d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // (not in resumeMask). 1802d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // For example, old variant has video and audio in two separate 1803d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // URIs, and new variant has only audio with unchanged URI. mSwapMask 1804d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // should be 0 as there is nothing to swap. We only need to stop video, 1805d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // and resume audio. 1806d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang mSwapMask = mNewStreamMask & mStreamMask & ~resumeMask; 1807d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang switching = (mSwapMask != 0); 1808309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 1809309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mRealTimeBaseUs = ALooper::GetNowUs() - mLastDequeuedTimeUs; 1810309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } else { 1811309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mRealTimeBaseUs = ALooper::GetNowUs() - timeUs; 181214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 1813a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 181425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("onChangeConfiguration3: timeUs=%lld, switching=%d, pickTrack=%d, " 181525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang "mStreamMask=0x%x, mNewStreamMask=0x%x, mSwapMask=0x%x", 181625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang (long long)timeUs, switching, pickTrack, 181725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang mStreamMask, mNewStreamMask, mSwapMask); 181825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 1819f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih for (size_t i = 0; i < kMaxStreams; ++i) { 1820f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih if (streamMask & indexToType(i)) { 1821f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih if (switching) { 1822f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih CHECK(msg->findString(mStreams[i].uriKey().c_str(), &mStreams[i].mNewUri)); 1823f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } else { 1824f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih CHECK(msg->findString(mStreams[i].uriKey().c_str(), &mStreams[i].mUri)); 1825f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 1826f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 1827f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 1828f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih 18291543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih // Of all existing fetchers: 18301543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih // * Resume fetchers that are still needed and assign them original packet sources. 18311543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih // * Mark otherwise unneeded fetchers for removal. 18321543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih ALOGV("resuming fetchers for mask 0x%08x", resumeMask); 183314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber for (size_t i = 0; i < mFetcherInfos.size(); ++i) { 183414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber const AString &uri = mFetcherInfos.keyAt(i); 18357c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (!resumeFetcher(uri, resumeMask, timeUs)) { 183625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("marking fetcher-%d to be removed", 183725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang mFetcherInfos[i].mFetcher->getFetcherID()); 183825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 18397c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mFetcherInfos.editValueAt(i).mToBeRemoved = true; 18401543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 1841a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1842a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 184314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // streamMask now only contains the types that need a new fetcher created. 184414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (streamMask != 0) { 184514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGV("creating new fetchers for mask 0x%08x", streamMask); 1846a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1847a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 18481543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih // Find out when the original fetchers have buffered up to and start the new fetchers 18491543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih // at a later timestamp. 18508ca002eedc747dd854b61cbe364b52c06869273fRobert Shih for (size_t i = 0; i < kMaxStreams; i++) { 18518ca002eedc747dd854b61cbe364b52c06869273fRobert Shih if (!(indexToType(i) & streamMask)) { 18528ca002eedc747dd854b61cbe364b52c06869273fRobert Shih continue; 18538ca002eedc747dd854b61cbe364b52c06869273fRobert Shih } 18541156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 185514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber AString uri; 1856f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih uri = switching ? mStreams[i].mNewUri : mStreams[i].mUri; 18579b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber 185814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<PlaylistFetcher> fetcher = addFetcher(uri.c_str()); 185914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(fetcher != NULL); 1860a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1861d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang HLSTime startTime; 1862a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang SeekMode seekMode = kSeekModeExactPosition; 18630852843d304006e3ab333081fddda13b07193de8Robert Shih sp<AnotherPacketSource> sources[kNumSources]; 18641543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 1865d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (i == kSubtitleIndex || (!pickTrack && !switching)) { 1866d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang startTime = latestMediaSegmentStartTime(); 1867b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih } 1868b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih 18698ca002eedc747dd854b61cbe364b52c06869273fRobert Shih // TRICKY: looping from i as earlier streams are already removed from streamMask 18708ca002eedc747dd854b61cbe364b52c06869273fRobert Shih for (size_t j = i; j < kMaxStreams; ++j) { 1871f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih const AString &streamUri = switching ? mStreams[j].mNewUri : mStreams[j].mUri; 1872f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih if ((streamMask & indexToType(j)) && uri == streamUri) { 18738ca002eedc747dd854b61cbe364b52c06869273fRobert Shih sources[j] = mPacketSources.valueFor(indexToType(j)); 18741543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 1875309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (timeUs >= 0) { 1876d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang startTime.mTimeUs = timeUs; 18771543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } else { 1878309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih int32_t type; 1879309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih sp<AMessage> meta; 1880d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (!switching) { 1881d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // selecting, or adapting but no swap required 1882309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih meta = sources[j]->getLatestDequeuedMeta(); 1883309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } else { 1884d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // adapting and swap required 1885309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih meta = sources[j]->getLatestEnqueuedMeta(); 18867c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (meta != NULL && mCurBandwidthIndex > mOrigBandwidthIndex) { 18877c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // switching up 18887c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang meta = sources[j]->getMetaAfterLastDequeued(mUpSwitchMargin); 18897c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 1890309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 18911543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 18920852843d304006e3ab333081fddda13b07193de8Robert Shih if ((j == kAudioIndex || j == kVideoIndex) 18930852843d304006e3ab333081fddda13b07193de8Robert Shih && meta != NULL && !meta->findInt32("discontinuity", &type)) { 1894d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang HLSTime tmpTime(meta); 1895d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (startTime < tmpTime) { 1896d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang startTime = tmpTime; 18971543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 18981543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 18991543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 1900d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (!switching) { 1901d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // selecting, or adapting but no swap required 1902309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih sources[j]->clear(); 1903309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (j == kSubtitleIndex) { 1904309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih break; 1905309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 1906964adb17885185808398507d2de88665fe193ee2Chong Zhang 19074604458dfe57b0e91a464aefafea50ae7b9876c1Chong Zhang ALOGV("stream[%zu]: queue format change", j); 1908964adb17885185808398507d2de88665fe193ee2Chong Zhang sources[j]->queueDiscontinuity( 1909a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang ATSParser::DISCONTINUITY_FORMAT_ONLY, NULL, true); 1910309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } else { 1911d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // switching, queue discontinuities after resume 1912309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih sources[j] = mPacketSources2.valueFor(indexToType(j)); 1913309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih sources[j]->clear(); 1914a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // the new fetcher might be providing streams that used to be 1915a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // provided by two different fetchers, if one of the fetcher 1916a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // paused in the middle while the other somehow paused in next 1917a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // seg, we have to start from next seg. 1918a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (seekMode < mStreams[j].mSeekMode) { 1919a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang seekMode = mStreams[j].mSeekMode; 1920309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 19211543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 19221543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 1923a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 19248ca002eedc747dd854b61cbe364b52c06869273fRobert Shih streamMask &= ~indexToType(j); 19258ca002eedc747dd854b61cbe364b52c06869273fRobert Shih } 1926a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 192714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 192825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("[fetcher-%d] startAsync: startTimeUs %lld mLastSeekTimeUs %lld " 192925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang "segmentStartTimeUs %lld seekMode %d", 193025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang fetcher->getFetcherID(), 193125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang (long long)startTime.mTimeUs, 193225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang (long long)mLastSeekTimeUs, 193325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang (long long)startTime.getSegmentTimeUs(true /* midpoint */), 193425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang seekMode); 193525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 1936d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // Set the target segment start time to the middle point of the 1937d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // segment where the last sample was. 1938d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // This gives a better guess if segments of the two variants are not 1939d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // perfectly aligned. (If the corresponding segment in new variant 1940d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // starts slightly later than that in the old variant, we still want 1941d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // to pick that segment, not the one before) 19428ca002eedc747dd854b61cbe364b52c06869273fRobert Shih fetcher->startAsync( 19438ca002eedc747dd854b61cbe364b52c06869273fRobert Shih sources[kAudioIndex], 19448ca002eedc747dd854b61cbe364b52c06869273fRobert Shih sources[kVideoIndex], 19458ca002eedc747dd854b61cbe364b52c06869273fRobert Shih sources[kSubtitleIndex], 19460852843d304006e3ab333081fddda13b07193de8Robert Shih getMetadataSource(sources, mNewStreamMask, switching), 1947d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang startTime.mTimeUs < 0 ? mLastSeekTimeUs : startTime.mTimeUs, 1948d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang startTime.getSegmentTimeUs(true /* midpoint */), 1949d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang startTime.mSeq, 1950a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang seekMode); 1951a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 1952a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 195314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // All fetchers have now been started, the configuration change 195414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // has completed. 1955a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 195614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mReconfigurationInProgress = false; 19571543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih if (switching) { 19581543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih mSwitchInProgress = true; 19591543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } else { 19601543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih mStreamMask = mNewStreamMask; 19618464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang if (mOrigBandwidthIndex != mCurBandwidthIndex) { 19628464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang ALOGV("#### Finished Bandwidth Switch Early: %zd => %zd", 19638464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang mOrigBandwidthIndex, mCurBandwidthIndex); 19648464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang mOrigBandwidthIndex = mCurBandwidthIndex; 19658464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang } 19661543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 1967a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 196825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("onChangeConfiguration3: mSwitchInProgress %d, mStreamMask 0x%x", 196925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang mSwitchInProgress, mStreamMask); 197025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 1971c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang if (mDisconnectReplyID != NULL) { 197214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber finishDisconnect(); 1973a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } 197414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 1975a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 1976a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhangvoid LiveSession::swapPacketSource(StreamType stream) { 197725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("[%s] swapPacketSource", getNameForStream(stream)); 1978a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1979a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // transfer packets from source2 to source 1980a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang sp<AnotherPacketSource> &aps = mPacketSources.editValueFor(stream); 1981a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang sp<AnotherPacketSource> &aps2 = mPacketSources2.editValueFor(stream); 1982a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1983a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // queue discontinuity in mPacketSource 1984a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang aps->queueDiscontinuity(ATSParser::DISCONTINUITY_FORMAT_ONLY, NULL, false); 1985a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1986a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // queue packets in mPacketSource2 to mPacketSource 1987a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang status_t finalResult = OK; 1988a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang sp<ABuffer> accessUnit; 1989a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang while (aps2->hasBufferAvailable(&finalResult) && finalResult == OK && 1990a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang OK == aps2->dequeueAccessUnit(&accessUnit)) { 1991a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang aps->queueAccessUnit(accessUnit); 1992a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 1993a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang aps2->clear(); 1994a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang} 1995a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 19967c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::tryToFinishBandwidthSwitch(const AString &oldUri) { 1997a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (!mSwitchInProgress) { 1998a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang return; 1999a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 2000a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 20017c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ssize_t index = mFetcherInfos.indexOfKey(oldUri); 2002a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (index < 0 || !mFetcherInfos[index].mToBeRemoved) { 20031543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih return; 20041543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 20051543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 2006a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // Swap packet source of streams provided by old variant 2007a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang for (size_t idx = 0; idx < kMaxStreams; idx++) { 20087c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang StreamType stream = indexToType(idx); 20097c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if ((mSwapMask & stream) && (oldUri == mStreams[idx].mUri)) { 2010a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang swapPacketSource(stream); 2011a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 2012a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if ((mNewStreamMask & stream) && mStreams[idx].mNewUri.empty()) { 2013a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang ALOGW("swapping stream type %d %s to empty stream", 2014a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang stream, mStreams[idx].mUri.c_str()); 2015a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 2016a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mStreams[idx].mUri = mStreams[idx].mNewUri; 2017a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mStreams[idx].mNewUri.clear(); 2018a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 2019a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mSwapMask &= ~stream; 2020a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 2021f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 2022f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih 20237c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mFetcherInfos.editValueAt(index).mFetcher->stopAsync(false /* clear */); 2024a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 202525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("tryToFinishBandwidthSwitch: mSwapMask=0x%x", mSwapMask); 2026309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (mSwapMask != 0) { 20271543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih return; 20281543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 20291543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 20301543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih // Check if new variant contains extra streams. 20311543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih uint32_t extraStreams = mNewStreamMask & (~mStreamMask); 20321543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih while (extraStreams) { 2033a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang StreamType stream = (StreamType) (extraStreams & ~(extraStreams - 1)); 2034a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang extraStreams &= ~stream; 2035a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 2036a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang swapPacketSource(stream); 2037f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih 2038a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang ssize_t idx = typeToIndex(stream); 2039f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih CHECK(idx >= 0); 2040f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih if (mStreams[idx].mNewUri.empty()) { 2041f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih ALOGW("swapping extra stream type %d %s to empty stream", 2042a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang stream, mStreams[idx].mUri.c_str()); 2043f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 2044f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih mStreams[idx].mUri = mStreams[idx].mNewUri; 2045f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih mStreams[idx].mNewUri.clear(); 20461543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 20471543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 2048a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // Restart new fetcher (it was paused after the first 47k block) 2049a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // and let it fetch into mPacketSources (not mPacketSources2) 2050a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang for (size_t i = 0; i < mFetcherInfos.size(); ++i) { 2051a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang FetcherInfo &info = mFetcherInfos.editValueAt(i); 2052a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (info.mToBeResumed) { 20537c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang resumeFetcher(mFetcherInfos.keyAt(i), mNewStreamMask); 2054a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang info.mToBeResumed = false; 2055a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 2056a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 2057a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 20587c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGI("#### Finished Bandwidth Switch: %zd => %zd", 20597c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mOrigBandwidthIndex, mCurBandwidthIndex); 20607c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 2061a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mStreamMask = mNewStreamMask; 2062a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mSwitchInProgress = false; 20637c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mOrigBandwidthIndex = mCurBandwidthIndex; 2064a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 20657c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang restartPollBuffering(); 20661543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih} 20671543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 2068964adb17885185808398507d2de88665fe193ee2Chong Zhangvoid LiveSession::schedulePollBuffering() { 2069964adb17885185808398507d2de88665fe193ee2Chong Zhang sp<AMessage> msg = new AMessage(kWhatPollBuffering, this); 2070964adb17885185808398507d2de88665fe193ee2Chong Zhang msg->setInt32("generation", mPollBufferingGeneration); 2071964adb17885185808398507d2de88665fe193ee2Chong Zhang msg->post(1000000ll); 2072964adb17885185808398507d2de88665fe193ee2Chong Zhang} 2073678bcdc852dd8f801f5c46fdc85db587b721d83dApurupa Pattapu 2074964adb17885185808398507d2de88665fe193ee2Chong Zhangvoid LiveSession::cancelPollBuffering() { 2075964adb17885185808398507d2de88665fe193ee2Chong Zhang ++mPollBufferingGeneration; 20767c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mPrevBufferPercentage = -1; 20777c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang} 20787c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 20797c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::restartPollBuffering() { 20807c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang cancelPollBuffering(); 20817c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang onPollBuffering(); 2082964adb17885185808398507d2de88665fe193ee2Chong Zhang} 20830ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih 2084964adb17885185808398507d2de88665fe193ee2Chong Zhangvoid LiveSession::onPollBuffering() { 2085964adb17885185808398507d2de88665fe193ee2Chong Zhang ALOGV("onPollBuffering: mSwitchInProgress %d, mReconfigurationInProgress %d, " 2086a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang "mInPreparationPhase %d, mCurBandwidthIndex %zd, mStreamMask 0x%x", 2087964adb17885185808398507d2de88665fe193ee2Chong Zhang mSwitchInProgress, mReconfigurationInProgress, 2088538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mInPreparationPhase, mCurBandwidthIndex, mStreamMask); 20890ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih 20907c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang bool underflow, ready, down, up; 20917c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (checkBuffering(underflow, ready, down, up)) { 20928464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang if (mInPreparationPhase) { 20938464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang // Allow down switch even if we're still preparing. 20948464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang // 20958464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang // Some streams have a high bandwidth index as default, 20968464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang // when bandwidth is low, it takes a long time to buffer 20978464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang // to ready mark, then it immediately pauses after start 20988464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang // as we have to do a down switch. It's better experience 20998464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang // to restart from a lower index, if we detect low bw. 21008464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang if (!switchBandwidthIfNeeded(false /* up */, down) && ready) { 21018464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang postPrepared(OK); 21028464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang } 21030ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih } 21040ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih 2105538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang if (!mInPreparationPhase) { 21067c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (ready) { 21077c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang stopBufferingIfNecessary(); 21087c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } else if (underflow) { 21097c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang startBufferingIfNecessary(); 21107c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 21117c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang switchBandwidthIfNeeded(up, down); 21128464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang } 21130ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih } 21140ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih 2115964adb17885185808398507d2de88665fe193ee2Chong Zhang schedulePollBuffering(); 21160ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih} 21170ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih 21187c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::cancelBandwidthSwitch(bool resume) { 21197c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGV("cancelBandwidthSwitch: mSwitchGen(%d)++, orig %zd, cur %zd", 21207c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mSwitchGeneration, mOrigBandwidthIndex, mCurBandwidthIndex); 21217c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (!mSwitchInProgress) { 21227c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return; 21237c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 2124f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih 2125f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih for (size_t i = 0; i < mFetcherInfos.size(); ++i) { 2126f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih FetcherInfo& info = mFetcherInfos.editValueAt(i); 2127f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih if (info.mToBeRemoved) { 2128f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih info.mToBeRemoved = false; 21297c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (resume) { 21307c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang resumeFetcher(mFetcherInfos.keyAt(i), mSwapMask); 21317c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 2132f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 2133f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 2134f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih 2135f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih for (size_t i = 0; i < kMaxStreams; ++i) { 21367c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang AString newUri = mStreams[i].mNewUri; 21377c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (!newUri.empty()) { 21387c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // clear all mNewUri matching this newUri 21397c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang for (size_t j = i; j < kMaxStreams; ++j) { 21407c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (mStreams[j].mNewUri == newUri) { 21417c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mStreams[j].mNewUri.clear(); 21427c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 21437c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 21447c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGV("stopping newUri = %s", newUri.c_str()); 21457c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ssize_t index = mFetcherInfos.indexOfKey(newUri); 21467c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (index < 0) { 21477c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGE("did not find fetcher for newUri: %s", newUri.c_str()); 2148f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih continue; 2149f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 21507c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang FetcherInfo &info = mFetcherInfos.editValueAt(index); 21517c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang info.mToBeRemoved = true; 2152f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih info.mFetcher->stopAsync(); 2153f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 2154f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih } 21557c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 21567c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGI("#### Canceled Bandwidth Switch: %zd => %zd", 215725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang mOrigBandwidthIndex, mCurBandwidthIndex); 21587c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 21597c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mSwitchGeneration++; 21607c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mSwitchInProgress = false; 21617c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mCurBandwidthIndex = mOrigBandwidthIndex; 21627c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mSwapMask = 0; 21631543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih} 21641543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 21657c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangbool LiveSession::checkBuffering( 21667c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang bool &underflow, bool &ready, bool &down, bool &up) { 21677c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang underflow = ready = down = up = false; 2168964adb17885185808398507d2de88665fe193ee2Chong Zhang 21697c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (mReconfigurationInProgress) { 2170964adb17885185808398507d2de88665fe193ee2Chong Zhang ALOGV("Switch/Reconfig in progress, defer buffer polling"); 21711543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih return false; 21721543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 21731543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 21747c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang size_t activeCount, underflowCount, readyCount, downCount, upCount; 21757c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang activeCount = underflowCount = readyCount = downCount = upCount =0; 21767c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang int32_t minBufferPercent = -1; 21777c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang int64_t durationUs; 21787c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (getDuration(&durationUs) != OK) { 21797c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang durationUs = -1; 21807c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 2181964adb17885185808398507d2de88665fe193ee2Chong Zhang for (size_t i = 0; i < mPacketSources.size(); ++i) { 2182964adb17885185808398507d2de88665fe193ee2Chong Zhang // we don't check subtitles for buffering level 2183964adb17885185808398507d2de88665fe193ee2Chong Zhang if (!(mStreamMask & mPacketSources.keyAt(i) 2184964adb17885185808398507d2de88665fe193ee2Chong Zhang & (STREAMTYPE_AUDIO | STREAMTYPE_VIDEO))) { 2185964adb17885185808398507d2de88665fe193ee2Chong Zhang continue; 2186964adb17885185808398507d2de88665fe193ee2Chong Zhang } 2187964adb17885185808398507d2de88665fe193ee2Chong Zhang // ignore streams that never had any packet queued. 2188964adb17885185808398507d2de88665fe193ee2Chong Zhang // (it's possible that the variant only has audio or video) 2189964adb17885185808398507d2de88665fe193ee2Chong Zhang sp<AMessage> meta = mPacketSources[i]->getLatestEnqueuedMeta(); 2190964adb17885185808398507d2de88665fe193ee2Chong Zhang if (meta == NULL) { 2191964adb17885185808398507d2de88665fe193ee2Chong Zhang continue; 2192964adb17885185808398507d2de88665fe193ee2Chong Zhang } 2193964adb17885185808398507d2de88665fe193ee2Chong Zhang 2194964adb17885185808398507d2de88665fe193ee2Chong Zhang int64_t bufferedDurationUs = 2195964adb17885185808398507d2de88665fe193ee2Chong Zhang mPacketSources[i]->getEstimatedDurationUs(); 219625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang ALOGV("[%s] buffered %lld us", 219725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang getNameForStream(mPacketSources.keyAt(i)), 219825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang (long long)bufferedDurationUs); 21997c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (durationUs >= 0) { 22007c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang int32_t percent; 22017c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (mPacketSources[i]->isFinished(0 /* duration */)) { 22027c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang percent = 100; 22037c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } else { 22048464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang percent = (int32_t)(100.0 * 22058464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang (mLastDequeuedTimeUs + bufferedDurationUs) / durationUs); 22067c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 22077c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (minBufferPercent < 0 || percent < minBufferPercent) { 22087c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang minBufferPercent = percent; 22097c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 2210964adb17885185808398507d2de88665fe193ee2Chong Zhang } 22117c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 22127c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ++activeCount; 2213765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang int64_t readyMark = mInPreparationPhase ? kPrepareMarkUs : kReadyMarkUs; 22147c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (bufferedDurationUs > readyMark 22157c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang || mPacketSources[i]->isFinished(0)) { 22167c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ++readyCount; 22177c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 22187c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (!mPacketSources[i]->isFinished(0)) { 2219765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang if (bufferedDurationUs < kUnderflowMarkUs) { 22207c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ++underflowCount; 22217c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 22227c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (bufferedDurationUs > mUpSwitchMark) { 22237c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ++upCount; 2224d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang } 2225d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (bufferedDurationUs < mDownSwitchMark) { 22267c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ++downCount; 22277c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 22287c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 22297c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 22307c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 22317c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (minBufferPercent >= 0) { 22327c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notifyBufferingUpdate(minBufferPercent); 223314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 223414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 2235964adb17885185808398507d2de88665fe193ee2Chong Zhang if (activeCount > 0) { 22367c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang up = (upCount == activeCount); 22377c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang down = (downCount > 0); 22387c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ready = (readyCount == activeCount); 22397c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang underflow = (underflowCount > 0); 22401543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih return true; 22411543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 2242964adb17885185808398507d2de88665fe193ee2Chong Zhang 2243964adb17885185808398507d2de88665fe193ee2Chong Zhang return false; 22441543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih} 22451543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 22467c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::startBufferingIfNecessary() { 22477c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGV("startBufferingIfNecessary: mInPreparationPhase=%d, mBuffering=%d", 22487c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mInPreparationPhase, mBuffering); 22497c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (!mBuffering) { 22507c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mBuffering = true; 22517c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 22527c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AMessage> notify = mNotify->dup(); 22537c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->setInt32("what", kWhatBufferingStart); 22547c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->post(); 22557c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 22567c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang} 22577c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 22587c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::stopBufferingIfNecessary() { 22597c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGV("stopBufferingIfNecessary: mInPreparationPhase=%d, mBuffering=%d", 22607c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mInPreparationPhase, mBuffering); 22617c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 22627c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (mBuffering) { 22637c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mBuffering = false; 22647c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 22657c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AMessage> notify = mNotify->dup(); 22667c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->setInt32("what", kWhatBufferingEnd); 22677c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->post(); 22687c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 22697c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang} 22707c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 22717c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::notifyBufferingUpdate(int32_t percentage) { 22727c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (percentage < mPrevBufferPercentage) { 22737c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang percentage = mPrevBufferPercentage; 22747c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } else if (percentage > 100) { 22757c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang percentage = 100; 22767c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 22777c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 22787c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mPrevBufferPercentage = percentage; 22797c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 22807c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGV("notifyBufferingUpdate: percentage=%d%%", percentage); 22817c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 22827c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AMessage> notify = mNotify->dup(); 22837c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->setInt32("what", kWhatBufferingUpdate); 22847c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->setInt32("percentage", percentage); 22857c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->post(); 22867c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang} 22877c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 22888464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang/* 22898464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang * returns true if a bandwidth switch is actually needed (and started), 22908464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang * returns false otherwise 22918464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang */ 22928464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhangbool LiveSession::switchBandwidthIfNeeded(bool bufferHigh, bool bufferLow) { 2293538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang // no need to check bandwidth if we only have 1 bandwidth settings 22947c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (mSwitchInProgress || mBandwidthItems.size() < 2) { 22958464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang return false; 2296538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang } 2297538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 2298538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang int32_t bandwidthBps; 2299538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang if (mBandwidthEstimator->estimateBandwidth(&bandwidthBps)) { 2300538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang ALOGV("bandwidth estimated at %.2f kbps", bandwidthBps / 1024.0f); 2301a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mLastBandwidthBps = bandwidthBps; 2302538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang } else { 2303538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang ALOGV("no bandwidth estimate."); 23048464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang return false; 2305538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang } 2306538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 2307538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang int32_t curBandwidth = mBandwidthItems.itemAt(mCurBandwidthIndex).mBandwidth; 2308d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // canSwithDown and canSwitchUp can't both be true. 2309d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // we only want to switch up when measured bw is 120% higher than current variant, 2310d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // and we only want to switch down when measured bw is below current variant. 2311d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang bool canSwithDown = bufferLow 2312d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang && (bandwidthBps < (int32_t)curBandwidth); 2313d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang bool canSwitchUp = bufferHigh 2314d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang && (bandwidthBps > (int32_t)curBandwidth * 12 / 10); 2315d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang 2316d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (canSwithDown || canSwitchUp) { 2317538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang ssize_t bandwidthIndex = getBandwidthIndex(bandwidthBps); 2318538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 2319d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // it's possible that we're checking for canSwitchUp case, but the returned 2320d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // bandwidthIndex is < mCurBandwidthIndex, as getBandwidthIndex() only uses 70% 2321d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // of measured bw. In that case we don't want to do anything, since we have 2322d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // both enough buffer and enough bw. 23238464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang if ((canSwitchUp && bandwidthIndex > mCurBandwidthIndex) 23248464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang || (canSwithDown && bandwidthIndex < mCurBandwidthIndex)) { 23258464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang // if not yet prepared, just restart again with new bw index. 23268464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang // this is faster and playback experience is cleaner. 23278464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang changeConfiguration( 23288464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang mInPreparationPhase ? 0 : -1ll, bandwidthIndex); 23298464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang return true; 2330538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang } 233114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 23328464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang return false; 2333a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} 2334a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 23357c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::postError(status_t err) { 23367c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // if we reached EOS, notify buffering of 100% 23377c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (err == ERROR_END_OF_STREAM) { 23387c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notifyBufferingUpdate(100); 23397c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 23407c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // we'll stop buffer polling now, before that notify 23417c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // stop buffering to stop the spinning icon 23427c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang stopBufferingIfNecessary(); 23437c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang cancelPollBuffering(); 23447c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 23457c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AMessage> notify = mNotify->dup(); 23467c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->setInt32("what", kWhatError); 23477c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->setInt32("err", err); 23487c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->post(); 23497c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang} 23507c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 235114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::postPrepared(status_t err) { 235214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(mInPreparationPhase); 2353a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 235414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AMessage> notify = mNotify->dup(); 235514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (err == OK || err == ERROR_END_OF_STREAM) { 235614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->setInt32("what", kWhatPrepared); 235714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else { 23587c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang cancelPollBuffering(); 23597c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 236014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->setInt32("what", kWhatPreparationFailed); 236114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->setInt32("err", err); 236214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 2363a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 236414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->post(); 2365a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 236614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mInPreparationPhase = false; 2367b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber} 2368b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber 2369964adb17885185808398507d2de88665fe193ee2Chong Zhang 2370a44153c1a57202fb538659eb50706e60454d6273Andreas Huber} // namespace android 2371a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 2372