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> &notify, 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