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