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
52538b6d22a3578c0201d48f8548289aa254d81484Chong Zhangstruct LiveSession::BandwidthEstimator : public RefBase {
53538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    BandwidthEstimator();
54538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
55538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    void addBandwidthMeasurement(size_t numBytes, int64_t delayUs);
565ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    bool estimateBandwidth(
575ef659e010e90175eb5282d9642a02f6105189bfChong Zhang            int32_t *bandwidth,
585ef659e010e90175eb5282d9642a02f6105189bfChong Zhang            bool *isStable = NULL,
595ef659e010e90175eb5282d9642a02f6105189bfChong Zhang            int32_t *shortTermBps = NULL);
60538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
61538b6d22a3578c0201d48f8548289aa254d81484Chong Zhangprivate:
62538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    // Bandwidth estimation parameters
635ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    static const int32_t kShortTermBandwidthItems = 3;
6481636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang    static const int32_t kMinBandwidthHistoryItems = 20;
6581636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang    static const int64_t kMinBandwidthHistoryWindowUs = 5000000ll; // 5 sec
6681636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang    static const int64_t kMaxBandwidthHistoryWindowUs = 30000000ll; // 30 sec
675ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    static const int64_t kMaxBandwidthHistoryAgeUs = 60000000ll; // 60 sec
68538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
69538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    struct BandwidthEntry {
705ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        int64_t mTimestampUs;
71538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        int64_t mDelayUs;
72538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        size_t mNumBytes;
73538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    };
74538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
75538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    Mutex mLock;
76538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    List<BandwidthEntry> mBandwidthHistory;
77978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    List<int32_t> mPrevEstimates;
785ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    int32_t mShortTermEstimate;
79978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    bool mHasNewSample;
80978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    bool mIsStable;
81538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    int64_t mTotalTransferTimeUs;
82538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    size_t mTotalTransferBytes;
83538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
84538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    DISALLOW_EVIL_CONSTRUCTORS(BandwidthEstimator);
85538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang};
86538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
87538b6d22a3578c0201d48f8548289aa254d81484Chong ZhangLiveSession::BandwidthEstimator::BandwidthEstimator() :
885ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    mShortTermEstimate(0),
89978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    mHasNewSample(false),
90978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    mIsStable(true),
91538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    mTotalTransferTimeUs(0),
92538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    mTotalTransferBytes(0) {
93538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang}
94538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
95538b6d22a3578c0201d48f8548289aa254d81484Chong Zhangvoid LiveSession::BandwidthEstimator::addBandwidthMeasurement(
96538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        size_t numBytes, int64_t delayUs) {
97538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    AutoMutex autoLock(mLock);
98538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
995ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    int64_t nowUs = ALooper::GetNowUs();
100538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    BandwidthEntry entry;
1015ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    entry.mTimestampUs = nowUs;
102538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    entry.mDelayUs = delayUs;
103538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    entry.mNumBytes = numBytes;
104538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    mTotalTransferTimeUs += delayUs;
105538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    mTotalTransferBytes += numBytes;
106538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    mBandwidthHistory.push_back(entry);
107978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    mHasNewSample = true;
108538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
10981636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang    // Remove no more than 10% of total transfer time at a time
11081636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang    // to avoid sudden jump on bandwidth estimation. There might
11181636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang    // be long blocking reads that takes up signification time,
11281636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang    // we have to keep a longer window in that case.
11381636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang    int64_t bandwidthHistoryWindowUs = mTotalTransferTimeUs * 9 / 10;
11481636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang    if (bandwidthHistoryWindowUs < kMinBandwidthHistoryWindowUs) {
11581636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang        bandwidthHistoryWindowUs = kMinBandwidthHistoryWindowUs;
11681636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang    } else if (bandwidthHistoryWindowUs > kMaxBandwidthHistoryWindowUs) {
11781636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang        bandwidthHistoryWindowUs = kMaxBandwidthHistoryWindowUs;
11881636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang    }
119538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    // trim old samples, keeping at least kMaxBandwidthHistoryItems samples,
120538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    // and total transfer time at least kMaxBandwidthHistoryWindowUs.
12181636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang    while (mBandwidthHistory.size() > kMinBandwidthHistoryItems) {
122538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        List<BandwidthEntry>::iterator it = mBandwidthHistory.begin();
1235ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        // remove sample if either absolute age or total transfer time is
1245ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        // over kMaxBandwidthHistoryWindowUs
1255ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        if (nowUs - it->mTimestampUs < kMaxBandwidthHistoryAgeUs &&
1265ef659e010e90175eb5282d9642a02f6105189bfChong Zhang                mTotalTransferTimeUs - it->mDelayUs < bandwidthHistoryWindowUs) {
127538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang            break;
128538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        }
129538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        mTotalTransferTimeUs -= it->mDelayUs;
130538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        mTotalTransferBytes -= it->mNumBytes;
131538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        mBandwidthHistory.erase(mBandwidthHistory.begin());
132538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    }
133538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang}
134538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
13581636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhangbool LiveSession::BandwidthEstimator::estimateBandwidth(
1365ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        int32_t *bandwidthBps, bool *isStable, int32_t *shortTermBps) {
137538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    AutoMutex autoLock(mLock);
138538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
139538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    if (mBandwidthHistory.size() < 2) {
140538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        return false;
141538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    }
142538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
143978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    if (!mHasNewSample) {
144978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang        *bandwidthBps = *(--mPrevEstimates.end());
145978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang        if (isStable) {
146978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang            *isStable = mIsStable;
147978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang        }
1485ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        if (shortTermBps) {
1495ef659e010e90175eb5282d9642a02f6105189bfChong Zhang            *shortTermBps = mShortTermEstimate;
1505ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        }
151978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang        return true;
152978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    }
153978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang
154538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    *bandwidthBps = ((double)mTotalTransferBytes * 8E6 / mTotalTransferTimeUs);
155978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    mPrevEstimates.push_back(*bandwidthBps);
156978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    while (mPrevEstimates.size() > 3) {
157978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang        mPrevEstimates.erase(mPrevEstimates.begin());
158978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    }
159978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    mHasNewSample = false;
160978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang
1615ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    int64_t totalTimeUs = 0;
1625ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    size_t totalBytes = 0;
1635ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    if (mBandwidthHistory.size() >= kShortTermBandwidthItems) {
1645ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        List<BandwidthEntry>::iterator it = --mBandwidthHistory.end();
1655ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        for (size_t i = 0; i < kShortTermBandwidthItems; i++, it--) {
1665ef659e010e90175eb5282d9642a02f6105189bfChong Zhang            totalTimeUs += it->mDelayUs;
1675ef659e010e90175eb5282d9642a02f6105189bfChong Zhang            totalBytes += it->mNumBytes;
1685ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        }
1695ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    }
1705ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    mShortTermEstimate = totalTimeUs > 0 ?
1715ef659e010e90175eb5282d9642a02f6105189bfChong Zhang            (totalBytes * 8E6 / totalTimeUs) : *bandwidthBps;
1725ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    if (shortTermBps) {
1735ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        *shortTermBps = mShortTermEstimate;
1745ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    }
1755ef659e010e90175eb5282d9642a02f6105189bfChong Zhang
176a6ff3a8a9bd17e8a5a421b409b58b8497842ebefRobert Shih    int64_t minEstimate = -1, maxEstimate = -1;
177978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    List<int32_t>::iterator it;
178978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    for (it = mPrevEstimates.begin(); it != mPrevEstimates.end(); it++) {
179978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang        int32_t estimate = *it;
180978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang        if (minEstimate < 0 || minEstimate > estimate) {
181978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang            minEstimate = estimate;
182978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang        }
183978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang        if (maxEstimate < 0 || maxEstimate < estimate) {
184978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang            maxEstimate = estimate;
185978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang        }
186978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    }
1875ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    // consider it stable if long-term average is not jumping a lot
1885ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    // and short-term average is not much lower than long-term average
1895ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    mIsStable = (maxEstimate <= minEstimate * 4 / 3)
1905ef659e010e90175eb5282d9642a02f6105189bfChong Zhang            && mShortTermEstimate > minEstimate * 7 / 10;
191978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    if (isStable) {
1925ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        *isStable = mIsStable;
193978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    }
1945ef659e010e90175eb5282d9642a02f6105189bfChong Zhang
19581636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang#if 0
19681636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang    {
19781636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang        char dumpStr[1024] = {0};
19881636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang        size_t itemIdx = 0;
19981636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang        size_t histSize = mBandwidthHistory.size();
20081636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang        sprintf(dumpStr, "estimate bps=%d stable=%d history (n=%d): {",
20181636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang            *bandwidthBps, mIsStable, histSize);
20281636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang        List<BandwidthEntry>::iterator it = mBandwidthHistory.begin();
20381636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang        for (; it != mBandwidthHistory.end(); ++it) {
20481636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang            if (itemIdx > 50) {
20581636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang                sprintf(dumpStr + strlen(dumpStr),
20681636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang                        "...(%zd more items)... }", histSize - itemIdx);
20781636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang                break;
20881636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang            }
20981636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang            sprintf(dumpStr + strlen(dumpStr), "%dk/%.3fs%s",
21081636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang                it->mNumBytes / 1024,
21181636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang                (double)it->mDelayUs * 1.0e-6,
21281636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang                (it == (--mBandwidthHistory.end())) ? "}" : ", ");
21381636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang            itemIdx++;
21481636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang        }
21581636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang        ALOGE(dumpStr);
21681636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang    }
21781636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang#endif
218538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    return true;
219538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang}
220538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
2217c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang//static
2227c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangconst char *LiveSession::getKeyForStream(StreamType type) {
2237c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    switch (type) {
2247c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        case STREAMTYPE_VIDEO:
2257c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            return "timeUsVideo";
2267c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        case STREAMTYPE_AUDIO:
2277c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            return "timeUsAudio";
2287c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        case STREAMTYPE_SUBTITLES:
2297c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            return "timeUsSubtitle";
2300852843d304006e3ab333081fddda13b07193de8Robert Shih        case STREAMTYPE_METADATA:
2310852843d304006e3ab333081fddda13b07193de8Robert Shih            return "timeUsMetadata"; // unused
2327c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        default:
2337c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            TRESPASS();
2347c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    }
2357c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    return NULL;
2367c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang}
2377c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
23825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang//static
23925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhangconst char *LiveSession::getNameForStream(StreamType type) {
24025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    switch (type) {
24125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang        case STREAMTYPE_VIDEO:
24225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            return "video";
24325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang        case STREAMTYPE_AUDIO:
24425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            return "audio";
24525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang        case STREAMTYPE_SUBTITLES:
24625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            return "subs";
2470852843d304006e3ab333081fddda13b07193de8Robert Shih        case STREAMTYPE_METADATA:
2480852843d304006e3ab333081fddda13b07193de8Robert Shih            return "metadata";
24925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang        default:
25025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            break;
25125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    }
25225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    return "unknown";
25325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang}
25425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang
2550852843d304006e3ab333081fddda13b07193de8Robert Shih//static
2560852843d304006e3ab333081fddda13b07193de8Robert ShihATSParser::SourceType LiveSession::getSourceTypeForStream(StreamType type) {
2570852843d304006e3ab333081fddda13b07193de8Robert Shih    switch (type) {
2580852843d304006e3ab333081fddda13b07193de8Robert Shih        case STREAMTYPE_VIDEO:
2590852843d304006e3ab333081fddda13b07193de8Robert Shih            return ATSParser::VIDEO;
2600852843d304006e3ab333081fddda13b07193de8Robert Shih        case STREAMTYPE_AUDIO:
2610852843d304006e3ab333081fddda13b07193de8Robert Shih            return ATSParser::AUDIO;
2620852843d304006e3ab333081fddda13b07193de8Robert Shih        case STREAMTYPE_METADATA:
2630852843d304006e3ab333081fddda13b07193de8Robert Shih            return ATSParser::META;
2640852843d304006e3ab333081fddda13b07193de8Robert Shih        case STREAMTYPE_SUBTITLES:
2650852843d304006e3ab333081fddda13b07193de8Robert Shih        default:
2660852843d304006e3ab333081fddda13b07193de8Robert Shih            TRESPASS();
2670852843d304006e3ab333081fddda13b07193de8Robert Shih    }
2680852843d304006e3ab333081fddda13b07193de8Robert Shih    return ATSParser::NUM_SOURCE_TYPES; // should not reach here
2690852843d304006e3ab333081fddda13b07193de8Robert Shih}
2700852843d304006e3ab333081fddda13b07193de8Robert Shih
2710df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas HuberLiveSession::LiveSession(
2721b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        const sp<AMessage> &notify, uint32_t flags,
27381e68448f3361eaf8618930471fdc3c21bdf5cbcAndreas Huber        const sp<IMediaHTTPService> &httpService)
2740df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas Huber    : mNotify(notify),
2750df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas Huber      mFlags(flags),
2761b86fe063badb5f28c467ade39be0f4008688947Andreas Huber      mHTTPService(httpService),
2777c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang      mBuffering(false),
2780df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas Huber      mInPreparationPhase(true),
2797c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang      mPollBufferingGeneration(0),
2807c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang      mPrevBufferPercentage(-1),
281309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih      mCurBandwidthIndex(-1),
2827c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang      mOrigBandwidthIndex(-1),
283a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang      mLastBandwidthBps(-1ll),
2845ef659e010e90175eb5282d9642a02f6105189bfChong Zhang      mLastBandwidthStable(false),
285538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang      mBandwidthEstimator(new BandwidthEstimator()),
286a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang      mMaxWidth(720),
287a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang      mMaxHeight(480),
28814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber      mStreamMask(0),
2891543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih      mNewStreamMask(0),
2901543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih      mSwapMask(0),
2911543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih      mSwitchGeneration(0),
292b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih      mSubtitleGeneration(0),
29314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber      mLastDequeuedTimeUs(0ll),
294dcb89b3b505522efde173c105a851c412f947178Chong Zhang      mRealTimeBaseUs(0ll),
29514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber      mReconfigurationInProgress(false),
2961543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih      mSwitchInProgress(false),
297765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang      mUpSwitchMark(kUpSwitchMarkUs),
298765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang      mDownSwitchMark(kDownSwitchMarkUs),
299765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang      mUpSwitchMargin(kUpSwitchMarginUs),
300309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih      mFirstTimeUsValid(false),
301309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih      mFirstTimeUs(0),
3020852843d304006e3ab333081fddda13b07193de8Robert Shih      mLastSeekTimeUs(0),
3030852843d304006e3ab333081fddda13b07193de8Robert Shih      mHasMetadata(false) {
3048ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    mStreams[kAudioIndex] = StreamItem("audio");
3058ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    mStreams[kVideoIndex] = StreamItem("video");
306e4f25c280a8f1655c31a745978e0fcbc61f91deeRobert Shih    mStreams[kSubtitleIndex] = StreamItem("subtitles");
30714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
3080852843d304006e3ab333081fddda13b07193de8Robert Shih    for (size_t i = 0; i < kNumSources; ++i) {
3098ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        mPacketSources.add(indexToType(i), new AnotherPacketSource(NULL /* meta */));
3101543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        mPacketSources2.add(indexToType(i), new AnotherPacketSource(NULL /* meta */));
3118ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    }
312a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
313a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
314a44153c1a57202fb538659eb50706e60454d6273Andreas HuberLiveSession::~LiveSession() {
315964adb17885185808398507d2de88665fe193ee2Chong Zhang    if (mFetcherLooper != NULL) {
316964adb17885185808398507d2de88665fe193ee2Chong Zhang        mFetcherLooper->stop();
317964adb17885185808398507d2de88665fe193ee2Chong Zhang    }
318a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
319a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
3200852843d304006e3ab333081fddda13b07193de8Robert Shihint64_t LiveSession::calculateMediaTimeUs(
3210852843d304006e3ab333081fddda13b07193de8Robert Shih        int64_t firstTimeUs, int64_t timeUs, int32_t discontinuitySeq) {
3220852843d304006e3ab333081fddda13b07193de8Robert Shih    if (timeUs >= firstTimeUs) {
3230852843d304006e3ab333081fddda13b07193de8Robert Shih        timeUs -= firstTimeUs;
3240852843d304006e3ab333081fddda13b07193de8Robert Shih    } else {
3250852843d304006e3ab333081fddda13b07193de8Robert Shih        timeUs = 0;
3260852843d304006e3ab333081fddda13b07193de8Robert Shih    }
3270852843d304006e3ab333081fddda13b07193de8Robert Shih    timeUs += mLastSeekTimeUs;
3280852843d304006e3ab333081fddda13b07193de8Robert Shih    if (mDiscontinuityOffsetTimesUs.indexOfKey(discontinuitySeq) >= 0) {
3290852843d304006e3ab333081fddda13b07193de8Robert Shih        timeUs += mDiscontinuityOffsetTimesUs.valueFor(discontinuitySeq);
3300852843d304006e3ab333081fddda13b07193de8Robert Shih    }
3310852843d304006e3ab333081fddda13b07193de8Robert Shih    return timeUs;
3320852843d304006e3ab333081fddda13b07193de8Robert Shih}
3330852843d304006e3ab333081fddda13b07193de8Robert Shih
33414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::dequeueAccessUnit(
33514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        StreamType stream, sp<ABuffer> *accessUnit) {
336964adb17885185808398507d2de88665fe193ee2Chong Zhang    status_t finalResult = OK;
33714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AnotherPacketSource> packetSource = mPacketSources.valueFor(stream);
33814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
33925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    ssize_t streamIdx = typeToIndex(stream);
34025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    if (streamIdx < 0) {
3415abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang        return BAD_VALUE;
34225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    }
34325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    const char *streamStr = getNameForStream(stream);
344a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    // Do not let client pull data if we don't have data packets yet.
345a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    // We might only have a format discontinuity queued without data.
346a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    // When NuPlayerDecoder dequeues the format discontinuity, it will
347a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    // immediately try to getFormat. If we return NULL, NuPlayerDecoder
348a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    // thinks it can do seamless change, so will not shutdown decoder.
349a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    // When the actual format arrives, it can't handle it and get stuck.
350a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    if (!packetSource->hasDataBufferAvailable(&finalResult)) {
35125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang        ALOGV("[%s] dequeueAccessUnit: no buffer available (finalResult=%d)",
35225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                streamStr, finalResult);
35325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang
354f69c996864844e8f669308af8412cede043062a2Robert Shih        if (finalResult == OK) {
355f69c996864844e8f669308af8412cede043062a2Robert Shih            return -EAGAIN;
356f69c996864844e8f669308af8412cede043062a2Robert Shih        } else {
357f69c996864844e8f669308af8412cede043062a2Robert Shih            return finalResult;
358f69c996864844e8f669308af8412cede043062a2Robert Shih        }
359f69c996864844e8f669308af8412cede043062a2Robert Shih    }
360f69c996864844e8f669308af8412cede043062a2Robert Shih
361a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    // Let the client dequeue as long as we have buffers available
362a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    // Do not make pause/resume decisions here.
363309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
36414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    status_t err = packetSource->dequeueAccessUnit(accessUnit);
36514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
36614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (err == INFO_DISCONTINUITY) {
367309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        // adaptive streaming, discontinuities in the playlist
36814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        int32_t type;
36914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        CHECK((*accessUnit)->meta()->findInt32("discontinuity", &type));
37014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
37114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        sp<AMessage> extra;
37214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (!(*accessUnit)->meta()->findMessage("extra", &extra)) {
37314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            extra.clear();
37414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
37514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
37614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        ALOGI("[%s] read discontinuity of type %d, extra = %s",
37714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber              streamStr,
37814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber              type,
37914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber              extra == NULL ? "NULL" : extra->debugString().c_str());
38014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    } else if (err == OK) {
381309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
382dcb89b3b505522efde173c105a851c412f947178Chong Zhang        if (stream == STREAMTYPE_AUDIO || stream == STREAMTYPE_VIDEO) {
38325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            int64_t timeUs, originalTimeUs;
384309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            int32_t discontinuitySeq = 0;
3850852843d304006e3ab333081fddda13b07193de8Robert Shih            StreamItem& strm = mStreams[streamIdx];
386dcb89b3b505522efde173c105a851c412f947178Chong Zhang            CHECK((*accessUnit)->meta()->findInt64("timeUs",  &timeUs));
38725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            originalTimeUs = timeUs;
388309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            (*accessUnit)->meta()->findInt32("discontinuitySeq", &discontinuitySeq);
3897c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            if (discontinuitySeq > (int32_t) strm.mCurDiscontinuitySeq) {
3907c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                int64_t offsetTimeUs;
3917c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                if (mDiscontinuityOffsetTimesUs.indexOfKey(strm.mCurDiscontinuitySeq) >= 0) {
3927c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    offsetTimeUs = mDiscontinuityOffsetTimesUs.valueFor(strm.mCurDiscontinuitySeq);
3937c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                } else {
3947c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    offsetTimeUs = 0;
3957c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                }
3967c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
39781636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang                if (mDiscontinuityAbsStartTimesUs.indexOfKey(strm.mCurDiscontinuitySeq) >= 0
39881636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang                        && strm.mLastDequeuedTimeUs >= 0) {
3997c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    int64_t firstTimeUs;
4007c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    firstTimeUs = mDiscontinuityAbsStartTimesUs.valueFor(strm.mCurDiscontinuitySeq);
4017c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    offsetTimeUs += strm.mLastDequeuedTimeUs - firstTimeUs;
4027c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    offsetTimeUs += strm.mLastSampleDurationUs;
4037c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                } else {
4047c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    offsetTimeUs += strm.mLastSampleDurationUs;
4057c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                }
4067c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
4077c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                mDiscontinuityOffsetTimesUs.add(discontinuitySeq, offsetTimeUs);
4087c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                strm.mCurDiscontinuitySeq = discontinuitySeq;
4097c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            }
410309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
411309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            int32_t discard = 0;
412309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            int64_t firstTimeUs;
413309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            if (mDiscontinuityAbsStartTimesUs.indexOfKey(strm.mCurDiscontinuitySeq) >= 0) {
414309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                int64_t durUs; // approximate sample duration
415309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                if (timeUs > strm.mLastDequeuedTimeUs) {
416309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    durUs = timeUs - strm.mLastDequeuedTimeUs;
417309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                } else {
418309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    durUs = strm.mLastDequeuedTimeUs - timeUs;
419309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                }
420309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                strm.mLastSampleDurationUs = durUs;
421309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                firstTimeUs = mDiscontinuityAbsStartTimesUs.valueFor(strm.mCurDiscontinuitySeq);
422309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            } else if ((*accessUnit)->meta()->findInt32("discard", &discard) && discard) {
423309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                firstTimeUs = timeUs;
424309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            } else {
425309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                mDiscontinuityAbsStartTimesUs.add(strm.mCurDiscontinuitySeq, timeUs);
426309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                firstTimeUs = timeUs;
427309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            }
428309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
429309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            strm.mLastDequeuedTimeUs = timeUs;
4300852843d304006e3ab333081fddda13b07193de8Robert Shih            timeUs = calculateMediaTimeUs(firstTimeUs, timeUs, discontinuitySeq);
431dcb89b3b505522efde173c105a851c412f947178Chong Zhang
43225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            ALOGV("[%s] dequeueAccessUnit: time %lld us, original %lld us",
43325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                    streamStr, (long long)timeUs, (long long)originalTimeUs);
434309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            (*accessUnit)->meta()->setInt64("timeUs",  timeUs);
435dcb89b3b505522efde173c105a851c412f947178Chong Zhang            mLastDequeuedTimeUs = timeUs;
436dcb89b3b505522efde173c105a851c412f947178Chong Zhang            mRealTimeBaseUs = ALooper::GetNowUs() - timeUs;
437dcb89b3b505522efde173c105a851c412f947178Chong Zhang        } else if (stream == STREAMTYPE_SUBTITLES) {
438b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih            int32_t subtitleGeneration;
439b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih            if ((*accessUnit)->meta()->findInt32("subtitleGeneration", &subtitleGeneration)
440b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih                    && subtitleGeneration != mSubtitleGeneration) {
441b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih               return -EAGAIN;
442b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih            };
443dcb89b3b505522efde173c105a851c412f947178Chong Zhang            (*accessUnit)->meta()->setInt32(
444dcb89b3b505522efde173c105a851c412f947178Chong Zhang                    "trackIndex", mPlaylist->getSelectedIndex());
445dcb89b3b505522efde173c105a851c412f947178Chong Zhang            (*accessUnit)->meta()->setInt64("baseUs", mRealTimeBaseUs);
4460852843d304006e3ab333081fddda13b07193de8Robert Shih        } else if (stream == STREAMTYPE_METADATA) {
4470852843d304006e3ab333081fddda13b07193de8Robert Shih            HLSTime mdTime((*accessUnit)->meta());
4480852843d304006e3ab333081fddda13b07193de8Robert Shih            if (mDiscontinuityAbsStartTimesUs.indexOfKey(mdTime.mSeq) < 0) {
4490852843d304006e3ab333081fddda13b07193de8Robert Shih                packetSource->requeueAccessUnit((*accessUnit));
4500852843d304006e3ab333081fddda13b07193de8Robert Shih                return -EAGAIN;
4510852843d304006e3ab333081fddda13b07193de8Robert Shih            } else {
4520852843d304006e3ab333081fddda13b07193de8Robert Shih                int64_t firstTimeUs = mDiscontinuityAbsStartTimesUs.valueFor(mdTime.mSeq);
4530852843d304006e3ab333081fddda13b07193de8Robert Shih                int64_t timeUs = calculateMediaTimeUs(firstTimeUs, mdTime.mTimeUs, mdTime.mSeq);
4540852843d304006e3ab333081fddda13b07193de8Robert Shih                (*accessUnit)->meta()->setInt64("timeUs",  timeUs);
4550852843d304006e3ab333081fddda13b07193de8Robert Shih                (*accessUnit)->meta()->setInt64("baseUs", mRealTimeBaseUs);
4560852843d304006e3ab333081fddda13b07193de8Robert Shih            }
457dcb89b3b505522efde173c105a851c412f947178Chong Zhang        }
45814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    } else {
45914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        ALOGI("[%s] encountered error %d", streamStr, err);
46014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
46114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
46214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return err;
46314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
46414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
465a83eebb78c3a7d57a769dac965b17a8aad7c7b8fRobert Shihstatus_t LiveSession::getStreamFormatMeta(StreamType stream, sp<MetaData> *meta) {
46614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (!(mStreamMask & stream)) {
46714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        return UNKNOWN_ERROR;
46814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
46914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
47014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AnotherPacketSource> packetSource = mPacketSources.valueFor(stream);
47114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
472a83eebb78c3a7d57a769dac965b17a8aad7c7b8fRobert Shih    *meta = packetSource->getFormat();
47314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
474a83eebb78c3a7d57a769dac965b17a8aad7c7b8fRobert Shih    if (*meta == NULL) {
4757350b057ca864f5dc9e53d48e34710a8e81133f8Robert Shih        return -EWOULDBLOCK;
47614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
47714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
4787c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    if (stream == STREAMTYPE_AUDIO) {
4797c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // set AAC input buffer size to 32K bytes (256kbps x 1sec)
480a83eebb78c3a7d57a769dac965b17a8aad7c7b8fRobert Shih        (*meta)->setInt32(kKeyMaxInputSize, 32 * 1024);
481a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang    } else if (stream == STREAMTYPE_VIDEO) {
482a83eebb78c3a7d57a769dac965b17a8aad7c7b8fRobert Shih        (*meta)->setInt32(kKeyMaxWidth, mMaxWidth);
483a83eebb78c3a7d57a769dac965b17a8aad7c7b8fRobert Shih        (*meta)->setInt32(kKeyMaxHeight, mMaxHeight);
4847c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    }
4857c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
486a83eebb78c3a7d57a769dac965b17a8aad7c7b8fRobert Shih    return OK;
487a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
488a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
4895abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhangsp<HTTPDownloader> LiveSession::getHTTPDownloader() {
4905abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    return new HTTPDownloader(mHTTPService, mExtraHeaders);
491a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang}
492a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
49348fa06d1e80a872c7495804979256e021e566ae0Wei Jiavoid LiveSession::setBufferingSettings(
49448fa06d1e80a872c7495804979256e021e566ae0Wei Jia        const BufferingSettings &buffering) {
49548fa06d1e80a872c7495804979256e021e566ae0Wei Jia    sp<AMessage> msg = new AMessage(kWhatSetBufferingSettings, this);
49648fa06d1e80a872c7495804979256e021e566ae0Wei Jia    writeToAMessage(msg, buffering);
49748fa06d1e80a872c7495804979256e021e566ae0Wei Jia    msg->post();
49848fa06d1e80a872c7495804979256e021e566ae0Wei Jia}
49948fa06d1e80a872c7495804979256e021e566ae0Wei Jia
50014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::connectAsync(
501ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        const char *url, const KeyedVector<String8, String8> *headers) {
5021d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatConnect, this);
503a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    msg->setString("url", url);
504ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber
505ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    if (headers != NULL) {
506ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        msg->setPointer(
507ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber                "headers",
508ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber                new KeyedVector<String8, String8>(*headers));
509ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    }
510ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber
511a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    msg->post();
512a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
513a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
51414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::disconnect() {
5151d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatDisconnect, this);
516ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
51714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> response;
51814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    status_t err = msg->postAndAwaitResponse(&response);
519ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
52014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return err;
521a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
522a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
523c5de09127e9e0d5df7aa587be317e1487d793245Wei Jiastatus_t LiveSession::seekTo(int64_t timeUs, MediaPlayerSeekMode mode) {
5241d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatSeek, this);
525a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    msg->setInt64("timeUs", timeUs);
526c5de09127e9e0d5df7aa587be317e1487d793245Wei Jia    msg->setInt32("mode", mode);
527a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
52814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> response;
52914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    status_t err = msg->postAndAwaitResponse(&response);
53014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
53114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return err;
532a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
533a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
5347c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangbool LiveSession::checkSwitchProgress(
5357c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        sp<AMessage> &stopParams, int64_t delayUs, bool *needResumeUntil) {
5367c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    AString newUri;
5377c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    CHECK(stopParams->findString("uri", &newUri));
5387c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
5397c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    *needResumeUntil = false;
5407c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    sp<AMessage> firstNewMeta[kMaxStreams];
5417c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    for (size_t i = 0; i < kMaxStreams; ++i) {
5427c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        StreamType stream = indexToType(i);
5437c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        if (!(mSwapMask & mNewStreamMask & stream)
5447c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            || (mStreams[i].mNewUri != newUri)) {
5457c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            continue;
5467c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        }
5477c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        if (stream == STREAMTYPE_SUBTITLES) {
5487c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            continue;
5497c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        }
5507c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        sp<AnotherPacketSource> &source = mPacketSources.editValueAt(i);
5517c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
5527c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // First, get latest dequeued meta, which is where the decoder is at.
5537c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // (when upswitching, we take the meta after a certain delay, so that
5547c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // the decoder is left with some cushion)
5557c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        sp<AMessage> lastDequeueMeta, lastEnqueueMeta;
5567c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        if (delayUs > 0) {
5577c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            lastDequeueMeta = source->getMetaAfterLastDequeued(delayUs);
558d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            if (lastDequeueMeta == NULL) {
559d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                // this means we don't have enough cushion, try again later
560d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                ALOGV("[%s] up switching failed due to insufficient buffer",
56125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                        getNameForStream(stream));
562d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                return false;
563d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            }
5647c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        } else {
565d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            // It's okay for lastDequeueMeta to be NULL here, it means the
566d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            // decoder hasn't even started dequeueing
5677c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            lastDequeueMeta = source->getLatestDequeuedMeta();
5687c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        }
5697c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // Then, trim off packets at beginning of mPacketSources2 that's before
5707c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // the latest dequeued time. These samples are definitely too late.
571d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        firstNewMeta[i] = mPacketSources2.editValueAt(i)
572d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                            ->trimBuffersBeforeMeta(lastDequeueMeta);
573d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang
5747c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // Now firstNewMeta[i] is the first sample after the trim.
5757c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // If it's NULL, we failed because dequeue already past all samples
5767c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // in mPacketSource2, we have to try again.
5777c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        if (firstNewMeta[i] == NULL) {
578d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            HLSTime dequeueTime(lastDequeueMeta);
5797c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            ALOGV("[%s] dequeue time (%d, %lld) past start time",
58025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                    getNameForStream(stream),
581d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                    dequeueTime.mSeq, (long long) dequeueTime.mTimeUs);
5827c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            return false;
5837c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        }
5847c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
5857c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // Otherwise, we check if mPacketSources2 overlaps with what old fetcher
5867c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // already fetched, and see if we need to resumeUntil
5877c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        lastEnqueueMeta = source->getLatestEnqueuedMeta();
5887c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // lastEnqueueMeta == NULL means old fetcher stopped at a discontinuity
5897c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // boundary, no need to resume as the content will look different anyways
5907c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        if (lastEnqueueMeta != NULL) {
591d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            HLSTime lastTime(lastEnqueueMeta), startTime(firstNewMeta[i]);
5927c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
5937c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            // no need to resume old fetcher if new fetcher started in different
5947c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            // discontinuity sequence, as the content will look different.
595d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            *needResumeUntil |= (startTime.mSeq == lastTime.mSeq
596d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                    && startTime.mTimeUs - lastTime.mTimeUs > kResumeThresholdUs);
5977c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
598d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            // update the stopTime for resumeUntil
599d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            stopParams->setInt32("discontinuitySeq", startTime.mSeq);
600d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            stopParams->setInt64(getKeyForStream(stream), startTime.mTimeUs);
6017c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        }
6027c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    }
6037c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
6047c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    // if we're here, it means dequeue progress hasn't passed some samples in
6057c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    // mPacketSource2, we can trim off the excess in mPacketSource.
6067c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    // (old fetcher might still need to resumeUntil the start time of new fetcher)
6077c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    for (size_t i = 0; i < kMaxStreams; ++i) {
6087c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        StreamType stream = indexToType(i);
6097c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        if (!(mSwapMask & mNewStreamMask & stream)
610d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            || (newUri != mStreams[i].mNewUri)
611d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            || stream == STREAMTYPE_SUBTITLES) {
6127c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            continue;
6137c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        }
614d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        mPacketSources.valueFor(stream)->trimBuffersAfterMeta(firstNewMeta[i]);
6157c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    }
6167c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
6177c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    // no resumeUntil if already underflow
6187c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    *needResumeUntil &= !mBuffering;
6197c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
6207c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    return true;
6217c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang}
6227c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
623a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onMessageReceived(const sp<AMessage> &msg) {
624a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    switch (msg->what()) {
62548fa06d1e80a872c7495804979256e021e566ae0Wei Jia        case kWhatSetBufferingSettings:
62648fa06d1e80a872c7495804979256e021e566ae0Wei Jia        {
62748fa06d1e80a872c7495804979256e021e566ae0Wei Jia            readFromAMessage(msg, &mBufferingSettings);
62848fa06d1e80a872c7495804979256e021e566ae0Wei Jia            break;
62948fa06d1e80a872c7495804979256e021e566ae0Wei Jia        }
63048fa06d1e80a872c7495804979256e021e566ae0Wei Jia
631a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        case kWhatConnect:
63214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
633a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            onConnect(msg);
634a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
63514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
636a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
637a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        case kWhatDisconnect:
63814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
63914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            CHECK(msg->senderAwaitsResponse(&mDisconnectReplyID));
64014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
64114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            if (mReconfigurationInProgress) {
64214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                break;
64314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            }
64414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
64514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            finishDisconnect();
646a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
64714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
648a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
64914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case kWhatSeek:
65014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
651a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar            if (mReconfigurationInProgress) {
652800599cdd50737de1cde483a34b39923750b0658Robert Shih                msg->post(50000);
653a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar                break;
654800599cdd50737de1cde483a34b39923750b0658Robert Shih            }
655a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar
656a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar            CHECK(msg->senderAwaitsResponse(&mSeekReplyID));
657a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar            mSeekReply = new AMessage;
658a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar
659a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar            onSeek(msg);
66014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            break;
66114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
66214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
66314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case kWhatFetcherNotify:
66414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
66514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            int32_t what;
66614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            CHECK(msg->findInt32("what", &what));
66714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
66814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            switch (what) {
66914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                case PlaylistFetcher::kWhatStarted:
67014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    break;
67114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                case PlaylistFetcher::kWhatPaused:
67214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                case PlaylistFetcher::kWhatStopped:
67314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                {
674a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                    AString uri;
675a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                    CHECK(msg->findString("uri", &uri));
676a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                    ssize_t index = mFetcherInfos.indexOfKey(uri);
677a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                    if (index < 0) {
678a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                        // ignore msgs from fetchers that's already gone
679a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                        break;
680a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                    }
681a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
68225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                    ALOGV("fetcher-%d %s",
68325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                            mFetcherInfos[index].mFetcher->getFetcherID(),
68425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                            what == PlaylistFetcher::kWhatPaused ?
68525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                                    "paused" : "stopped");
68625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang
68714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    if (what == PlaylistFetcher::kWhatStopped) {
688964adb17885185808398507d2de88665fe193ee2Chong Zhang                        mFetcherLooper->unregisterHandler(
689964adb17885185808398507d2de88665fe193ee2Chong Zhang                                mFetcherInfos[index].mFetcher->id());
690964adb17885185808398507d2de88665fe193ee2Chong Zhang                        mFetcherInfos.removeItemsAt(index);
691a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                    } else if (what == PlaylistFetcher::kWhatPaused) {
692a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                        int32_t seekMode;
693a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                        CHECK(msg->findInt32("seekMode", &seekMode));
694a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                        for (size_t i = 0; i < kMaxStreams; ++i) {
695a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                            if (mStreams[i].mUri == uri) {
696a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                                mStreams[i].mSeekMode = (SeekMode) seekMode;
697a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                            }
698309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        }
69914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    }
70014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
70114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    if (mContinuation != NULL) {
70214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        CHECK_GT(mContinuationCounter, 0);
70314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        if (--mContinuationCounter == 0) {
70414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                            mContinuation->post();
70514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        }
70625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                        ALOGV("%zu fetcher(s) left", mContinuationCounter);
70714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    }
70814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    break;
70914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                }
71014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
71114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                case PlaylistFetcher::kWhatDurationUpdate:
71214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                {
71314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    AString uri;
71414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    CHECK(msg->findString("uri", &uri));
71514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
71614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    int64_t durationUs;
71714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    CHECK(msg->findInt64("durationUs", &durationUs));
71814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
719964adb17885185808398507d2de88665fe193ee2Chong Zhang                    ssize_t index = mFetcherInfos.indexOfKey(uri);
720964adb17885185808398507d2de88665fe193ee2Chong Zhang                    if (index >= 0) {
721964adb17885185808398507d2de88665fe193ee2Chong Zhang                        FetcherInfo *info = &mFetcherInfos.editValueFor(uri);
722964adb17885185808398507d2de88665fe193ee2Chong Zhang                        info->mDurationUs = durationUs;
723964adb17885185808398507d2de88665fe193ee2Chong Zhang                    }
72414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    break;
72514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                }
72614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
7277c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                case PlaylistFetcher::kWhatTargetDurationUpdate:
7287c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                {
7297c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    int64_t targetDurationUs;
7307c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    CHECK(msg->findInt64("targetDurationUs", &targetDurationUs));
731d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                    mUpSwitchMark = min(kUpSwitchMarkUs, targetDurationUs * 7 / 4);
732765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang                    mDownSwitchMark = min(kDownSwitchMarkUs, targetDurationUs * 9 / 4);
733765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang                    mUpSwitchMargin = min(kUpSwitchMarginUs, targetDurationUs);
7347c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    break;
7357c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                }
7367c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
73714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                case PlaylistFetcher::kWhatError:
73814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                {
73914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    status_t err;
74014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    CHECK(msg->findInt32("err", &err));
74114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
74214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    ALOGE("XXX Received error %d from PlaylistFetcher.", err);
74314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
74415f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                    // handle EOS on subtitle tracks independently
74515f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                    AString uri;
74615f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                    if (err == ERROR_END_OF_STREAM && msg->findString("uri", &uri)) {
74715f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                        ssize_t i = mFetcherInfos.indexOfKey(uri);
74815f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                        if (i >= 0) {
74915f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                            const sp<PlaylistFetcher> &fetcher = mFetcherInfos.valueAt(i).mFetcher;
75015f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                            if (fetcher != NULL) {
75115f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                                uint32_t type = fetcher->getStreamTypeMask();
75215f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                                if (type == STREAMTYPE_SUBTITLES) {
75315f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                                    mPacketSources.valueFor(
75415f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                                            STREAMTYPE_SUBTITLES)->signalEOS(err);;
75515f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                                    break;
75615f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                                }
75715f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                            }
75815f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                        }
75915f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                    }
76015f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih
7615ef659e010e90175eb5282d9642a02f6105189bfChong Zhang                    // remember the failure index (as mCurBandwidthIndex will be restored
7625ef659e010e90175eb5282d9642a02f6105189bfChong Zhang                    // after cancelBandwidthSwitch()), and record last fail time
7635ef659e010e90175eb5282d9642a02f6105189bfChong Zhang                    size_t failureIndex = mCurBandwidthIndex;
7645ef659e010e90175eb5282d9642a02f6105189bfChong Zhang                    mBandwidthItems.editItemAt(
7655ef659e010e90175eb5282d9642a02f6105189bfChong Zhang                            failureIndex).mLastFailureUs = ALooper::GetNowUs();
7665ef659e010e90175eb5282d9642a02f6105189bfChong Zhang
7675ef659e010e90175eb5282d9642a02f6105189bfChong Zhang                    if (mSwitchInProgress) {
7685ef659e010e90175eb5282d9642a02f6105189bfChong Zhang                        // if error happened when we switch to a variant, try fallback
7695ef659e010e90175eb5282d9642a02f6105189bfChong Zhang                        // to other variant to save the session
7705ef659e010e90175eb5282d9642a02f6105189bfChong Zhang                        if (tryBandwidthFallback()) {
7715ef659e010e90175eb5282d9642a02f6105189bfChong Zhang                            break;
7725ef659e010e90175eb5282d9642a02f6105189bfChong Zhang                        }
7735ef659e010e90175eb5282d9642a02f6105189bfChong Zhang                    }
7745ef659e010e90175eb5282d9642a02f6105189bfChong Zhang
77514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    if (mInPreparationPhase) {
77614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        postPrepared(err);
77714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    }
77814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
7791543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    cancelBandwidthSwitch();
7801543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
78114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    mPacketSources.valueFor(STREAMTYPE_AUDIO)->signalEOS(err);
78214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
78314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    mPacketSources.valueFor(STREAMTYPE_VIDEO)->signalEOS(err);
78414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
78514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    mPacketSources.valueFor(
78614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                            STREAMTYPE_SUBTITLES)->signalEOS(err);
78714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
7887c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    postError(err);
7897c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    break;
7907c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                }
7917c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
7927c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                case PlaylistFetcher::kWhatStopReached:
7937c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                {
7947c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    ALOGV("kWhatStopReached");
7957c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
796d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                    AString oldUri;
797d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                    CHECK(msg->findString("uri", &oldUri));
7987c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
799d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                    ssize_t index = mFetcherInfos.indexOfKey(oldUri);
8007c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    if (index < 0) {
8017c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                        break;
8027c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    }
8037c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
804d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                    tryToFinishBandwidthSwitch(oldUri);
80514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    break;
80614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                }
80714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
8081543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                case PlaylistFetcher::kWhatStartedAt:
8091543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                {
8101543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    int32_t switchGeneration;
8111543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    CHECK(msg->findInt32("switchGeneration", &switchGeneration));
8121543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
81325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                    ALOGV("kWhatStartedAt: switchGen=%d, mSwitchGen=%d",
81425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                            switchGeneration, mSwitchGeneration);
81525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang
8161543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    if (switchGeneration != mSwitchGeneration) {
8171543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        break;
8181543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    }
8191543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
820a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                    AString uri;
821a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                    CHECK(msg->findString("uri", &uri));
8227c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
8237c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    // mark new fetcher mToBeResumed
824a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                    ssize_t index = mFetcherInfos.indexOfKey(uri);
825a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                    if (index >= 0) {
826a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                        mFetcherInfos.editValueAt(index).mToBeResumed = true;
827a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                    }
828a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
8297c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    // temporarily disable packet sources to be swapped to prevent
8307c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    // NuPlayerDecoder from dequeuing while we check progress
8317c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    for (size_t i = 0; i < mPacketSources.size(); ++i) {
8327c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                        if ((mSwapMask & mPacketSources.keyAt(i))
8337c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                                && uri == mStreams[i].mNewUri) {
8347c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                            mPacketSources.editValueAt(i)->enable(false);
8351543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        }
8361543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    }
8377c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    bool switchUp = (mCurBandwidthIndex > mOrigBandwidthIndex);
8387c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    // If switching up, require a cushion bigger than kUnderflowMark
8397c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    // to avoid buffering immediately after the switch.
8407c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    // (If we don't have that cushion we'd rather cancel and try again.)
84148fa06d1e80a872c7495804979256e021e566ae0Wei Jia                    int64_t delayUs =
84248fa06d1e80a872c7495804979256e021e566ae0Wei Jia                        switchUp ?
84348fa06d1e80a872c7495804979256e021e566ae0Wei Jia                            (mBufferingSettings.mRebufferingWatermarkLowMs * 1000ll + 1000000ll)
84448fa06d1e80a872c7495804979256e021e566ae0Wei Jia                            : 0;
8457c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    bool needResumeUntil = false;
8467c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    sp<AMessage> stopParams = msg;
8477c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    if (checkSwitchProgress(stopParams, delayUs, &needResumeUntil)) {
8487c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                        // playback time hasn't passed startAt time
8497c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                        if (!needResumeUntil) {
85025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                            ALOGV("finish switch");
8517c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                            for (size_t i = 0; i < kMaxStreams; ++i) {
8527c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                                if ((mSwapMask & indexToType(i))
8537c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                                        && uri == mStreams[i].mNewUri) {
8547c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                                    // have to make a copy of mStreams[i].mUri because
8557c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                                    // tryToFinishBandwidthSwitch is modifying mStreams[]
8567c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                                    AString oldURI = mStreams[i].mUri;
8577c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                                    tryToFinishBandwidthSwitch(oldURI);
8587c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                                    break;
8597c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                                }
8607c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                            }
8617c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                        } else {
8627c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                            // startAt time is after last enqueue time
8637c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                            // Resume fetcher for the original variant; the resumed fetcher should
8647c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                            // continue until the timestamps found in msg, which is stored by the
8657c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                            // new fetcher to indicate where the new variant has started buffering.
86625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                            ALOGV("finish switch with resumeUntilAsync");
8677c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                            for (size_t i = 0; i < mFetcherInfos.size(); i++) {
8687c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                                const FetcherInfo &info = mFetcherInfos.valueAt(i);
8697c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                                if (info.mToBeRemoved) {
8707c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                                    info.mFetcher->resumeUntilAsync(stopParams);
8717c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                                }
8727c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                            }
8737c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                        }
8747c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    } else {
8757c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                        // playback time passed startAt time
8767c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                        if (switchUp) {
8777c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                            // if switching up, cancel and retry if condition satisfies again
87825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                            ALOGV("cancel up switch because we're too late");
8797c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                            cancelBandwidthSwitch(true /* resume */);
8807c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                        } else {
88125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                            ALOGV("retry down switch at next sample");
8827c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                            resumeFetcher(uri, mSwapMask, -1, true /* newUri */);
8837c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                        }
8847c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    }
8857c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    // re-enable all packet sources
8867c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    for (size_t i = 0; i < mPacketSources.size(); ++i) {
8877c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                        mPacketSources.editValueAt(i)->enable(true);
8887c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    }
8897c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
8901543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    break;
8911543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                }
8921543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
8935abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang                case PlaylistFetcher::kWhatPlaylistFetched:
8945abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang                {
8955abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang                    onMasterPlaylistFetched(msg);
8965abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang                    break;
8975abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang                }
8985abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang
8990852843d304006e3ab333081fddda13b07193de8Robert Shih                case PlaylistFetcher::kWhatMetadataDetected:
9000852843d304006e3ab333081fddda13b07193de8Robert Shih                {
9010852843d304006e3ab333081fddda13b07193de8Robert Shih                    if (!mHasMetadata) {
9020852843d304006e3ab333081fddda13b07193de8Robert Shih                        mHasMetadata = true;
9030852843d304006e3ab333081fddda13b07193de8Robert Shih                        sp<AMessage> notify = mNotify->dup();
9040852843d304006e3ab333081fddda13b07193de8Robert Shih                        notify->setInt32("what", kWhatMetadataDetected);
9050852843d304006e3ab333081fddda13b07193de8Robert Shih                        notify->post();
9060852843d304006e3ab333081fddda13b07193de8Robert Shih                    }
9070852843d304006e3ab333081fddda13b07193de8Robert Shih                    break;
9080852843d304006e3ab333081fddda13b07193de8Robert Shih                }
9090852843d304006e3ab333081fddda13b07193de8Robert Shih
91014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                default:
91114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    TRESPASS();
91214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            }
91314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
91414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            break;
91514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
91614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
917dcb89b3b505522efde173c105a851c412f947178Chong Zhang        case kWhatChangeConfiguration:
918dcb89b3b505522efde173c105a851c412f947178Chong Zhang        {
919dcb89b3b505522efde173c105a851c412f947178Chong Zhang            onChangeConfiguration(msg);
920dcb89b3b505522efde173c105a851c412f947178Chong Zhang            break;
921dcb89b3b505522efde173c105a851c412f947178Chong Zhang        }
922dcb89b3b505522efde173c105a851c412f947178Chong Zhang
92314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case kWhatChangeConfiguration2:
92414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
92514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            onChangeConfiguration2(msg);
92614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            break;
92714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
92814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
92914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case kWhatChangeConfiguration3:
93014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
93114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            onChangeConfiguration3(msg);
93214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            break;
93314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
93414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
935964adb17885185808398507d2de88665fe193ee2Chong Zhang        case kWhatPollBuffering:
9360ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        {
937964adb17885185808398507d2de88665fe193ee2Chong Zhang            int32_t generation;
938964adb17885185808398507d2de88665fe193ee2Chong Zhang            CHECK(msg->findInt32("generation", &generation));
939964adb17885185808398507d2de88665fe193ee2Chong Zhang            if (generation == mPollBufferingGeneration) {
940964adb17885185808398507d2de88665fe193ee2Chong Zhang                onPollBuffering();
941964adb17885185808398507d2de88665fe193ee2Chong Zhang            }
9420ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih            break;
9430ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        }
9440ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
945a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        default:
946a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            TRESPASS();
947a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
948a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
949a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
950a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
951a44153c1a57202fb538659eb50706e60454d6273Andreas Huber// static
9525ef659e010e90175eb5282d9642a02f6105189bfChong Zhangbool LiveSession::isBandwidthValid(const BandwidthItem &item) {
9535ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    static const int64_t kBlacklistWindowUs = 300 * 1000000ll;
9545ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    return item.mLastFailureUs < 0
9555ef659e010e90175eb5282d9642a02f6105189bfChong Zhang            || ALooper::GetNowUs() - item.mLastFailureUs > kBlacklistWindowUs;
9565ef659e010e90175eb5282d9642a02f6105189bfChong Zhang}
9575ef659e010e90175eb5282d9642a02f6105189bfChong Zhang
9585ef659e010e90175eb5282d9642a02f6105189bfChong Zhang// static
959a44153c1a57202fb538659eb50706e60454d6273Andreas Huberint LiveSession::SortByBandwidth(const BandwidthItem *a, const BandwidthItem *b) {
960a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (a->mBandwidth < b->mBandwidth) {
961a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return -1;
962a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else if (a->mBandwidth == b->mBandwidth) {
963a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return 0;
964a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
965a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
966a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return 1;
967a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
968a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
9698ca002eedc747dd854b61cbe364b52c06869273fRobert Shih// static
9708ca002eedc747dd854b61cbe364b52c06869273fRobert ShihLiveSession::StreamType LiveSession::indexToType(int idx) {
9710852843d304006e3ab333081fddda13b07193de8Robert Shih    CHECK(idx >= 0 && idx < kNumSources);
9728ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    return (StreamType)(1 << idx);
9738ca002eedc747dd854b61cbe364b52c06869273fRobert Shih}
9748ca002eedc747dd854b61cbe364b52c06869273fRobert Shih
975f69c996864844e8f669308af8412cede043062a2Robert Shih// static
976f69c996864844e8f669308af8412cede043062a2Robert Shihssize_t LiveSession::typeToIndex(int32_t type) {
977f69c996864844e8f669308af8412cede043062a2Robert Shih    switch (type) {
978f69c996864844e8f669308af8412cede043062a2Robert Shih        case STREAMTYPE_AUDIO:
979f69c996864844e8f669308af8412cede043062a2Robert Shih            return 0;
980f69c996864844e8f669308af8412cede043062a2Robert Shih        case STREAMTYPE_VIDEO:
981f69c996864844e8f669308af8412cede043062a2Robert Shih            return 1;
982f69c996864844e8f669308af8412cede043062a2Robert Shih        case STREAMTYPE_SUBTITLES:
983f69c996864844e8f669308af8412cede043062a2Robert Shih            return 2;
9840852843d304006e3ab333081fddda13b07193de8Robert Shih        case STREAMTYPE_METADATA:
9850852843d304006e3ab333081fddda13b07193de8Robert Shih            return 3;
986f69c996864844e8f669308af8412cede043062a2Robert Shih        default:
987f69c996864844e8f669308af8412cede043062a2Robert Shih            return -1;
988f69c996864844e8f669308af8412cede043062a2Robert Shih    };
989f69c996864844e8f669308af8412cede043062a2Robert Shih    return -1;
990f69c996864844e8f669308af8412cede043062a2Robert Shih}
991f69c996864844e8f669308af8412cede043062a2Robert Shih
992a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onConnect(const sp<AMessage> &msg) {
9935abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    CHECK(msg->findString("url", &mMasterURL));
9945abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang
9955abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    // TODO currently we don't know if we are coming here from incognito mode
9965abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    ALOGI("onConnect %s", uriDebugString(mMasterURL).c_str());
997a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
998ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    KeyedVector<String8, String8> *headers = NULL;
999ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    if (!msg->findPointer("headers", (void **)&headers)) {
1000ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        mExtraHeaders.clear();
1001ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    } else {
1002ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        mExtraHeaders = *headers;
1003ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber
1004ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        delete headers;
1005ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        headers = NULL;
1006ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    }
1007ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber
1008964adb17885185808398507d2de88665fe193ee2Chong Zhang    // create looper for fetchers
1009964adb17885185808398507d2de88665fe193ee2Chong Zhang    if (mFetcherLooper == NULL) {
1010964adb17885185808398507d2de88665fe193ee2Chong Zhang        mFetcherLooper = new ALooper();
1011964adb17885185808398507d2de88665fe193ee2Chong Zhang
1012964adb17885185808398507d2de88665fe193ee2Chong Zhang        mFetcherLooper->setName("Fetcher");
1013964adb17885185808398507d2de88665fe193ee2Chong Zhang        mFetcherLooper->start(false, false);
1014964adb17885185808398507d2de88665fe193ee2Chong Zhang    }
1015964adb17885185808398507d2de88665fe193ee2Chong Zhang
10165abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    // create fetcher to fetch the master playlist
10175abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    addFetcher(mMasterURL.c_str())->fetchPlaylistAsync();
10185abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang}
10195abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang
10205abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhangvoid LiveSession::onMasterPlaylistFetched(const sp<AMessage> &msg) {
10215abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    AString uri;
10225abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    CHECK(msg->findString("uri", &uri));
10235abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    ssize_t index = mFetcherInfos.indexOfKey(uri);
10245abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    if (index < 0) {
10255abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang        ALOGW("fetcher for master playlist is gone.");
10265abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang        return;
10275abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    }
10285abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang
10295abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    // no longer useful, remove
10305abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    mFetcherLooper->unregisterHandler(mFetcherInfos[index].mFetcher->id());
10315abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    mFetcherInfos.removeItemsAt(index);
10325abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang
10335abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    CHECK(msg->findObject("playlist", (sp<RefBase> *)&mPlaylist));
10345abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    if (mPlaylist == NULL) {
10355abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang        ALOGE("unable to fetch master playlist %s.",
10365abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang                uriDebugString(mMasterURL).c_str());
10375abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang
10385abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang        postPrepared(ERROR_IO);
10395abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang        return;
10405abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    }
104114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // We trust the content provider to make a reasonable choice of preferred
104214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // initial bandwidth by listing it first in the variant playlist.
104314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // At startup we really don't have a good estimate on the available
104414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // network bandwidth since we haven't tranferred any data yet. Once
104514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // we have we can make a better informed choice.
104614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    size_t initialBandwidth = 0;
104714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    size_t initialBandwidthIndex = 0;
104814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
1049a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang    int32_t maxWidth = 0;
1050a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang    int32_t maxHeight = 0;
1051a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang
105214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (mPlaylist->isVariantPlaylist()) {
1053d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        Vector<BandwidthItem> itemsWithVideo;
105414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        for (size_t i = 0; i < mPlaylist->size(); ++i) {
1055a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            BandwidthItem item;
1056a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
105714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            item.mPlaylistIndex = i;
10585ef659e010e90175eb5282d9642a02f6105189bfChong Zhang            item.mLastFailureUs = -1ll;
105914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
1060a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            sp<AMessage> meta;
106114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            AString uri;
106214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            mPlaylist->itemAt(i, &uri, &meta);
1063a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1064a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            CHECK(meta->findInt32("bandwidth", (int32_t *)&item.mBandwidth));
1065a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1066a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang            int32_t width, height;
1067a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang            if (meta->findInt32("width", &width)) {
1068a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang                maxWidth = max(maxWidth, width);
1069a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang            }
1070a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang            if (meta->findInt32("height", &height)) {
1071a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang                maxHeight = max(maxHeight, height);
1072a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang            }
1073a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang
1074a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            mBandwidthItems.push(item);
1075d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            if (mPlaylist->hasType(i, "video")) {
1076d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                itemsWithVideo.push(item);
1077d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            }
1078d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        }
1079d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        // remove the audio-only variants if we have at least one with video
1080d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        if (!itemsWithVideo.empty()
1081d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                && itemsWithVideo.size() < mBandwidthItems.size()) {
1082d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            mBandwidthItems.clear();
1083d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            for (size_t i = 0; i < itemsWithVideo.size(); ++i) {
1084d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                mBandwidthItems.push(itemsWithVideo[i]);
1085d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            }
1086a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
1087a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1088a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        CHECK_GT(mBandwidthItems.size(), 0u);
1089d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        initialBandwidth = mBandwidthItems[0].mBandwidth;
1090a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1091a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        mBandwidthItems.sort(SortByBandwidth);
109214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
109314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        for (size_t i = 0; i < mBandwidthItems.size(); ++i) {
109414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            if (mBandwidthItems.itemAt(i).mBandwidth == initialBandwidth) {
109514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                initialBandwidthIndex = i;
109614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                break;
109714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            }
109814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
109914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    } else {
110014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        // dummy item.
110114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        BandwidthItem item;
110214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        item.mPlaylistIndex = 0;
110314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        item.mBandwidth = 0;
110414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        mBandwidthItems.push(item);
1105a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1106a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1107a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang    mMaxWidth = maxWidth > 0 ? maxWidth : mMaxWidth;
1108a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang    mMaxHeight = maxHeight > 0 ? maxHeight : mMaxHeight;
1109a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang
1110309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    mPlaylist->pickRandomMediaItems();
1111dcb89b3b505522efde173c105a851c412f947178Chong Zhang    changeConfiguration(
1112309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            0ll /* timeUs */, initialBandwidthIndex, false /* pickTrack */);
1113a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
1114a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
111514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::finishDisconnect() {
1116a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    ALOGV("finishDisconnect");
1117a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
111814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // No reconfiguration is currently pending, make sure none will trigger
111914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // during disconnection either.
11201543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    cancelBandwidthSwitch();
11211543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
1122964adb17885185808398507d2de88665fe193ee2Chong Zhang    // cancel buffer polling
1123964adb17885185808398507d2de88665fe193ee2Chong Zhang    cancelPollBuffering();
11240ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
11255abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    // TRICKY: don't wait for all fetcher to be stopped when disconnecting
11265abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    //
11275abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    // Some fetchers might be stuck in connect/getSize at this point. These
11285abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    // operations will eventually timeout (as we have a timeout set in
11295abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    // MediaHTTPConnection), but we don't want to block the main UI thread
11305abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    // until then. Here we just need to make sure we clear all references
11315abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    // to the fetchers, so that when they finally exit from the blocking
11325abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    // operation, they can be destructed.
11335abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    //
11345abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    // There is one very tricky point though. For this scheme to work, the
11355abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    // fecther must hold a reference to LiveSession, so that LiveSession is
11365abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    // destroyed after fetcher. Otherwise LiveSession would get stuck in its
11375abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    // own destructor when it waits for mFetcherLooper to stop, which still
11385abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    // blocks main UI thread.
113914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
114014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        mFetcherInfos.valueAt(i).mFetcher->stopAsync();
11415abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang        mFetcherLooper->unregisterHandler(
11425abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang                mFetcherInfos.valueAt(i).mFetcher->id());
114314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
11445abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    mFetcherInfos.clear();
114514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
114614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mPacketSources.valueFor(STREAMTYPE_AUDIO)->signalEOS(ERROR_END_OF_STREAM);
114714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mPacketSources.valueFor(STREAMTYPE_VIDEO)->signalEOS(ERROR_END_OF_STREAM);
114814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
114914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mPacketSources.valueFor(
115014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            STREAMTYPE_SUBTITLES)->signalEOS(ERROR_END_OF_STREAM);
115114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
115214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> response = new AMessage;
115314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    response->setInt32("err", OK);
115414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
115514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    response->postReply(mDisconnectReplyID);
1156c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang    mDisconnectReplyID.clear();
115714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
115814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
115914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubersp<PlaylistFetcher> LiveSession::addFetcher(const char *uri) {
116014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    ssize_t index = mFetcherInfos.indexOfKey(uri);
116114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
116214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (index >= 0) {
116314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        return NULL;
116414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
116514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
11661d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> notify = new AMessage(kWhatFetcherNotify, this);
116714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->setString("uri", uri);
11681543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    notify->setInt32("switchGeneration", mSwitchGeneration);
116914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
117014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    FetcherInfo info;
117125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    info.mFetcher = new PlaylistFetcher(
117225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            notify, this, uri, mCurBandwidthIndex, mSubtitleGeneration);
117314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    info.mDurationUs = -1ll;
11741543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    info.mToBeRemoved = false;
1175a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    info.mToBeResumed = false;
1176964adb17885185808398507d2de88665fe193ee2Chong Zhang    mFetcherLooper->registerHandler(info.mFetcher);
117714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
117814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mFetcherInfos.add(uri, info);
117914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
118014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return info.mFetcher;
1181a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
1182a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1183b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe#if 0
1184a44153c1a57202fb538659eb50706e60454d6273Andreas Huberstatic double uniformRand() {
1185a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return (double)rand() / RAND_MAX;
1186a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
1187b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe#endif
1188a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
11890852843d304006e3ab333081fddda13b07193de8Robert Shihbool LiveSession::UriIsSameAsIndex(const AString &uri, int32_t i, bool newUri) {
119094e2db71cf1ce90f8a74632895e2766b24a80d7fMichal Piechowski    ALOGV("[timed_id3] i %d UriIsSameAsIndex newUri %s, %s", i,
11910852843d304006e3ab333081fddda13b07193de8Robert Shih            newUri ? "true" : "false",
11920852843d304006e3ab333081fddda13b07193de8Robert Shih            newUri ? mStreams[i].mNewUri.c_str() : mStreams[i].mUri.c_str());
11930852843d304006e3ab333081fddda13b07193de8Robert Shih    return i >= 0
11940852843d304006e3ab333081fddda13b07193de8Robert Shih            && ((!newUri && uri == mStreams[i].mUri)
11950852843d304006e3ab333081fddda13b07193de8Robert Shih            || (newUri && uri == mStreams[i].mNewUri));
11960852843d304006e3ab333081fddda13b07193de8Robert Shih}
11970852843d304006e3ab333081fddda13b07193de8Robert Shih
11980852843d304006e3ab333081fddda13b07193de8Robert Shihsp<AnotherPacketSource> LiveSession::getPacketSourceForStreamIndex(
11990852843d304006e3ab333081fddda13b07193de8Robert Shih        size_t trackIndex, bool newUri) {
12000852843d304006e3ab333081fddda13b07193de8Robert Shih    StreamType type = indexToType(trackIndex);
12010852843d304006e3ab333081fddda13b07193de8Robert Shih    sp<AnotherPacketSource> source = NULL;
12020852843d304006e3ab333081fddda13b07193de8Robert Shih    if (newUri) {
12030852843d304006e3ab333081fddda13b07193de8Robert Shih        source = mPacketSources2.valueFor(type);
12040852843d304006e3ab333081fddda13b07193de8Robert Shih        source->clear();
12050852843d304006e3ab333081fddda13b07193de8Robert Shih    } else {
12060852843d304006e3ab333081fddda13b07193de8Robert Shih        source = mPacketSources.valueFor(type);
12070852843d304006e3ab333081fddda13b07193de8Robert Shih    };
12080852843d304006e3ab333081fddda13b07193de8Robert Shih    return source;
12090852843d304006e3ab333081fddda13b07193de8Robert Shih}
12100852843d304006e3ab333081fddda13b07193de8Robert Shih
12110852843d304006e3ab333081fddda13b07193de8Robert Shihsp<AnotherPacketSource> LiveSession::getMetadataSource(
12120852843d304006e3ab333081fddda13b07193de8Robert Shih        sp<AnotherPacketSource> sources[kNumSources], uint32_t streamMask, bool newUri) {
12130852843d304006e3ab333081fddda13b07193de8Robert Shih    // todo: One case where the following strategy can fail is when audio and video
12140852843d304006e3ab333081fddda13b07193de8Robert Shih    // are in separate playlists, both are transport streams, and the metadata
12150852843d304006e3ab333081fddda13b07193de8Robert Shih    // is actually contained in the audio stream.
12160852843d304006e3ab333081fddda13b07193de8Robert Shih    ALOGV("[timed_id3] getMetadataSourceForUri streamMask %x newUri %s",
12170852843d304006e3ab333081fddda13b07193de8Robert Shih            streamMask, newUri ? "true" : "false");
12180852843d304006e3ab333081fddda13b07193de8Robert Shih
12190852843d304006e3ab333081fddda13b07193de8Robert Shih    if ((sources[kVideoIndex] != NULL) // video fetcher; or ...
12200852843d304006e3ab333081fddda13b07193de8Robert Shih            || (!(streamMask & STREAMTYPE_VIDEO) && sources[kAudioIndex] != NULL)) {
12210852843d304006e3ab333081fddda13b07193de8Robert Shih            // ... audio fetcher for audio only variant
12220852843d304006e3ab333081fddda13b07193de8Robert Shih        return getPacketSourceForStreamIndex(kMetaDataIndex, newUri);
12230852843d304006e3ab333081fddda13b07193de8Robert Shih    }
12240852843d304006e3ab333081fddda13b07193de8Robert Shih
12250852843d304006e3ab333081fddda13b07193de8Robert Shih    return NULL;
12260852843d304006e3ab333081fddda13b07193de8Robert Shih}
12270852843d304006e3ab333081fddda13b07193de8Robert Shih
12287c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangbool LiveSession::resumeFetcher(
12297c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        const AString &uri, uint32_t streamMask, int64_t timeUs, bool newUri) {
12307c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    ssize_t index = mFetcherInfos.indexOfKey(uri);
12317c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    if (index < 0) {
12327c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        ALOGE("did not find fetcher for uri: %s", uri.c_str());
12337c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        return false;
12347c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    }
12357c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
12367c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    bool resume = false;
12370852843d304006e3ab333081fddda13b07193de8Robert Shih    sp<AnotherPacketSource> sources[kNumSources];
12387c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    for (size_t i = 0; i < kMaxStreams; ++i) {
12390852843d304006e3ab333081fddda13b07193de8Robert Shih        if ((streamMask & indexToType(i)) && UriIsSameAsIndex(uri, i, newUri)) {
12407c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            resume = true;
12410852843d304006e3ab333081fddda13b07193de8Robert Shih            sources[i] = getPacketSourceForStreamIndex(i, newUri);
12427c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        }
12437c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    }
12447c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
12457c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    if (resume) {
124625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang        sp<PlaylistFetcher> &fetcher = mFetcherInfos.editValueAt(index).mFetcher;
12477c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        SeekMode seekMode = newUri ? kSeekModeNextSample : kSeekModeExactPosition;
124825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang
124925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang        ALOGV("resuming fetcher-%d, timeUs=%lld, seekMode=%d",
125025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                fetcher->getFetcherID(), (long long)timeUs, seekMode);
125125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang
125225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang        fetcher->startAsync(
12537c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                sources[kAudioIndex],
12547c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                sources[kVideoIndex],
12557c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                sources[kSubtitleIndex],
12560852843d304006e3ab333081fddda13b07193de8Robert Shih                getMetadataSource(sources, streamMask, newUri),
12577c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                timeUs, -1, -1, seekMode);
12587c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    }
12597c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
12607c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    return resume;
12617c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang}
12627c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
1263a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhangfloat LiveSession::getAbortThreshold(
1264a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        ssize_t currentBWIndex, ssize_t targetBWIndex) const {
1265a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    float abortThreshold = -1.0f;
1266a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    if (currentBWIndex > 0 && targetBWIndex < currentBWIndex) {
1267a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        /*
1268a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           If we're switching down, we need to decide whether to
1269a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
1270a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           1) finish last segment of high-bandwidth variant, or
1271a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           2) abort last segment of high-bandwidth variant, and fetch an
1272a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang              overlapping portion from low-bandwidth variant.
1273a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
1274a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           Here we try to maximize the amount of buffer left when the
1275a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           switch point is met. Given the following parameters:
1276a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
1277a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           B: our current buffering level in seconds
1278a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           T: target duration in seconds
1279a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           X: sample duration in seconds remain to fetch in last segment
1280a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           bw0: bandwidth of old variant (as specified in playlist)
1281a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           bw1: bandwidth of new variant (as specified in playlist)
1282a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           bw: measured bandwidth available
1283a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
1284a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           If we choose 1), when switch happens at the end of current
1285a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           segment, our buffering will be
1286a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                  B + X - X * bw0 / bw
1287a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
1288a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           If we choose 2), when switch happens where we aborted current
1289a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           segment, our buffering will be
1290a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                  B - (T - X) * bw1 / bw
1291a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
1292a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           We should only choose 1) if
1293a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                  X/T < bw1 / (bw1 + bw0 - bw)
1294a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        */
1295a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
12965ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        // abort old bandwidth immediately if bandwidth is fluctuating a lot.
12975ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        // our estimate could be far off, and fetching old bandwidth could
12985ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        // take too long.
12995ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        if (!mLastBandwidthStable) {
13005ef659e010e90175eb5282d9642a02f6105189bfChong Zhang            return 0.0f;
13015ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        }
13025ef659e010e90175eb5282d9642a02f6105189bfChong Zhang
13037c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // Taking the measured current bandwidth at 50% face value only,
13047c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // as our bandwidth estimation is a lagging indicator. Being
13057c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // conservative on this, we prefer switching to lower bandwidth
13067c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // unless we're really confident finishing up the last segment
13077c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // of higher bandwidth will be fast.
1308a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        CHECK(mLastBandwidthBps >= 0);
1309a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        abortThreshold =
1310a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                (float)mBandwidthItems.itemAt(targetBWIndex).mBandwidth
1311a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang             / ((float)mBandwidthItems.itemAt(targetBWIndex).mBandwidth
1312a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang              + (float)mBandwidthItems.itemAt(currentBWIndex).mBandwidth
13137c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang              - (float)mLastBandwidthBps * 0.5f);
1314a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        if (abortThreshold < 0.0f) {
1315a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang            abortThreshold = -1.0f; // do not abort
1316a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        }
1317a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        ALOGV("Switching Down: bps %ld => %ld, measured %d, abort ratio %.2f",
1318a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                mBandwidthItems.itemAt(currentBWIndex).mBandwidth,
1319a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                mBandwidthItems.itemAt(targetBWIndex).mBandwidth,
1320a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                mLastBandwidthBps,
1321a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                abortThreshold);
1322a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    }
1323a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    return abortThreshold;
1324a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang}
1325a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
1326538b6d22a3578c0201d48f8548289aa254d81484Chong Zhangvoid LiveSession::addBandwidthMeasurement(size_t numBytes, int64_t delayUs) {
1327538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    mBandwidthEstimator->addBandwidthMeasurement(numBytes, delayUs);
1328538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang}
1329538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
13305ef659e010e90175eb5282d9642a02f6105189bfChong Zhangssize_t LiveSession::getLowestValidBandwidthIndex() const {
13315ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    for (size_t index = 0; index < mBandwidthItems.size(); index++) {
13325ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        if (isBandwidthValid(mBandwidthItems[index])) {
13335ef659e010e90175eb5282d9642a02f6105189bfChong Zhang            return index;
13345ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        }
13355ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    }
13365ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    // if playlists are all blacklisted, return 0 and hope it's alive
13375ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    return 0;
13385ef659e010e90175eb5282d9642a02f6105189bfChong Zhang}
13395ef659e010e90175eb5282d9642a02f6105189bfChong Zhang
1340538b6d22a3578c0201d48f8548289aa254d81484Chong Zhangsize_t LiveSession::getBandwidthIndex(int32_t bandwidthBps) {
1341538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    if (mBandwidthItems.size() < 2) {
1342538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        // shouldn't be here if we only have 1 bandwidth, check
1343538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        // logic to get rid of redundant bandwidth polling
1344538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        ALOGW("getBandwidthIndex() called for single bandwidth playlist!");
1345a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return 0;
1346a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1347a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1348a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#if 1
1349a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    char value[PROPERTY_VALUE_MAX];
1350673158582c9589cee1d5e4d7c79622609938b8f8Andreas Huber    ssize_t index = -1;
135114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (property_get("media.httplive.bw-index", value, NULL)) {
1352a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        char *end;
135314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        index = strtol(value, &end, 10);
135414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        CHECK(end > value && *end == '\0');
135514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
135614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (index >= 0 && (size_t)index >= mBandwidthItems.size()) {
135714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            index = mBandwidthItems.size() - 1;
1358a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
1359a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1360a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
136114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (index < 0) {
136214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        char value[PROPERTY_VALUE_MAX];
136314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (property_get("media.httplive.max-bw", value, NULL)) {
136414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            char *end;
136514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            long maxBw = strtoul(value, &end, 10);
136614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            if (end > value && *end == '\0') {
136714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                if (maxBw > 0 && bandwidthBps > maxBw) {
136814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    ALOGV("bandwidth capped to %ld bps", maxBw);
136914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    bandwidthBps = maxBw;
137014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                }
137114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            }
137214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
1373a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
13745ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        // Pick the highest bandwidth stream that's not currently blacklisted
13755ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        // below or equal to estimated bandwidth.
137614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
137714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        index = mBandwidthItems.size() - 1;
13785ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        ssize_t lowestBandwidth = getLowestValidBandwidthIndex();
13795ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        while (index > lowestBandwidth) {
1380538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang            // be conservative (70%) to avoid overestimating and immediately
1381538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang            // switching down again.
1382538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang            size_t adjustedBandwidthBps = bandwidthBps * 7 / 10;
13835ef659e010e90175eb5282d9642a02f6105189bfChong Zhang            const BandwidthItem &item = mBandwidthItems[index];
13845ef659e010e90175eb5282d9642a02f6105189bfChong Zhang            if (item.mBandwidth <= adjustedBandwidthBps
13855ef659e010e90175eb5282d9642a02f6105189bfChong Zhang                    && isBandwidthValid(item)) {
138600598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih                break;
138700598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih            }
138814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            --index;
138914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
1390a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1391a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0
1392a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // Change bandwidth at random()
1393a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index = uniformRand() * mBandwidthItems.size();
1394a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0
1395a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // There's a 50% chance to stay on the current bandwidth and
1396a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // a 50% chance to switch to the next higher bandwidth (wrapping around
1397a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // to lowest)
1398a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    const size_t kMinIndex = 0;
1399a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1400309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    static ssize_t mCurBandwidthIndex = -1;
140114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
1402a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index;
1403309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    if (mCurBandwidthIndex < 0) {
1404a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        index = kMinIndex;
1405a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else if (uniformRand() < 0.5) {
1406309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        index = (size_t)mCurBandwidthIndex;
1407a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else {
1408309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        index = mCurBandwidthIndex + 1;
1409a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (index == mBandwidthItems.size()) {
1410a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            index = kMinIndex;
1411a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
1412a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1413309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    mCurBandwidthIndex = index;
1414a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0
1415a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // Pick the highest bandwidth stream below or equal to 1.2 Mbit/sec
1416a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1417a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index = mBandwidthItems.size() - 1;
1418a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    while (index > 0 && mBandwidthItems.itemAt(index).mBandwidth > 1200000) {
1419a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        --index;
1420a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
142114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#elif 1
142214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    char value[PROPERTY_VALUE_MAX];
142314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    size_t index;
142414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (property_get("media.httplive.bw-index", value, NULL)) {
142514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        char *end;
142614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        index = strtoul(value, &end, 10);
142714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        CHECK(end > value && *end == '\0');
142814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
142914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (index >= mBandwidthItems.size()) {
143014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            index = mBandwidthItems.size() - 1;
143114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
143214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    } else {
143314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        index = 0;
143414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
1435a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#else
1436a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index = mBandwidthItems.size() - 1;  // Highest bandwidth stream
1437a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#endif
1438a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
143914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK_GE(index, 0);
144014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
1441a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return index;
1442a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
1443a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1444d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong ZhangHLSTime LiveSession::latestMediaSegmentStartTime() const {
1445d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang    HLSTime audioTime(mPacketSources.valueFor(
1446d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                    STREAMTYPE_AUDIO)->getLatestDequeuedMeta());
1447b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih
1448d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang    HLSTime videoTime(mPacketSources.valueFor(
1449d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                    STREAMTYPE_VIDEO)->getLatestDequeuedMeta());
1450b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih
1451d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang    return audioTime < videoTime ? videoTime : audioTime;
1452b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih}
1453b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih
1454a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnarvoid LiveSession::onSeek(const sp<AMessage> &msg) {
145514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    int64_t timeUs;
1456c5de09127e9e0d5df7aa587be317e1487d793245Wei Jia    int32_t mode;
145714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(msg->findInt64("timeUs", &timeUs));
1458c5de09127e9e0d5df7aa587be317e1487d793245Wei Jia    CHECK(msg->findInt32("mode", &mode));
1459c5de09127e9e0d5df7aa587be317e1487d793245Wei Jia    // TODO: add "mode" to changeConfiguration.
1460c5de09127e9e0d5df7aa587be317e1487d793245Wei Jia    changeConfiguration(timeUs/* , (MediaPlayerSeekMode)mode */);
14617e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber}
14627e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
146314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::getDuration(int64_t *durationUs) const {
1464895651b07fec30b0f9b0d2499599a179d95c9be4Wei Jia    int64_t maxDurationUs = -1ll;
146514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
146614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        int64_t fetcherDurationUs = mFetcherInfos.valueAt(i).mDurationUs;
1467b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
1468895651b07fec30b0f9b0d2499599a179d95c9be4Wei Jia        if (fetcherDurationUs > maxDurationUs) {
146914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            maxDurationUs = fetcherDurationUs;
1470a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
1471a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1472a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
147314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    *durationUs = maxDurationUs;
1474a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
147514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return OK;
147614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
14770f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber
147814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberbool LiveSession::isSeekable() const {
147914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    int64_t durationUs;
148014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return getDuration(&durationUs) == OK && durationUs >= 0;
148114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
14820f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber
148314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberbool LiveSession::hasDynamicDuration() const {
148414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return false;
148514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
14860f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber
1487404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhangsize_t LiveSession::getTrackCount() const {
14889d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih    if (mPlaylist == NULL) {
14899d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih        return 0;
14909d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih    } else {
14910852843d304006e3ab333081fddda13b07193de8Robert Shih        return mPlaylist->getTrackCount() + (mHasMetadata ? 1 : 0);
14929d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih    }
1493404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang}
1494404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang
1495404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhangsp<AMessage> LiveSession::getTrackInfo(size_t trackIndex) const {
14969d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih    if (mPlaylist == NULL) {
14979d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih        return NULL;
14989d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih    } else {
14990852843d304006e3ab333081fddda13b07193de8Robert Shih        if (trackIndex == mPlaylist->getTrackCount() && mHasMetadata) {
15000852843d304006e3ab333081fddda13b07193de8Robert Shih            sp<AMessage> format = new AMessage();
15010852843d304006e3ab333081fddda13b07193de8Robert Shih            format->setInt32("type", MEDIA_TRACK_TYPE_METADATA);
15020852843d304006e3ab333081fddda13b07193de8Robert Shih            format->setString("language", "und");
15036f9c5e26c710dbee50e57316f1c460dda4850fa5Robert Shih            format->setString("mime", MEDIA_MIMETYPE_DATA_TIMED_ID3);
15040852843d304006e3ab333081fddda13b07193de8Robert Shih            return format;
15050852843d304006e3ab333081fddda13b07193de8Robert Shih        }
15069d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih        return mPlaylist->getTrackInfo(trackIndex);
15079d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih    }
1508dcb89b3b505522efde173c105a851c412f947178Chong Zhang}
1509dcb89b3b505522efde173c105a851c412f947178Chong Zhang
1510dcb89b3b505522efde173c105a851c412f947178Chong Zhangstatus_t LiveSession::selectTrack(size_t index, bool select) {
1511b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    if (mPlaylist == NULL) {
1512b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih        return INVALID_OPERATION;
1513b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    }
1514b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih
151525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    ALOGV("selectTrack: index=%zu, select=%d, mSubtitleGen=%d++",
151625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            index, select, mSubtitleGeneration);
151725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang
1518b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    ++mSubtitleGeneration;
1519dcb89b3b505522efde173c105a851c412f947178Chong Zhang    status_t err = mPlaylist->selectTrack(index, select);
1520dcb89b3b505522efde173c105a851c412f947178Chong Zhang    if (err == OK) {
15211d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar        sp<AMessage> msg = new AMessage(kWhatChangeConfiguration, this);
1522309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        msg->setInt32("pickTrack", select);
1523309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        msg->post();
1524dcb89b3b505522efde173c105a851c412f947178Chong Zhang    }
1525dcb89b3b505522efde173c105a851c412f947178Chong Zhang    return err;
1526dcb89b3b505522efde173c105a851c412f947178Chong Zhang}
1527dcb89b3b505522efde173c105a851c412f947178Chong Zhang
152889bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shihssize_t LiveSession::getSelectedTrack(media_track_type type) const {
152989bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih    if (mPlaylist == NULL) {
153089bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih        return -1;
153189bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih    } else {
153289bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih        return mPlaylist->getSelectedTrack(type);
153389bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih    }
153489bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih}
153589bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih
1536dcb89b3b505522efde173c105a851c412f947178Chong Zhangvoid LiveSession::changeConfiguration(
15377c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        int64_t timeUs, ssize_t bandwidthIndex, bool pickTrack) {
153825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    ALOGV("changeConfiguration: timeUs=%lld us, bwIndex=%zd, pickTrack=%d",
153925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang          (long long)timeUs, bandwidthIndex, pickTrack);
154025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang
15411543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    cancelBandwidthSwitch();
15421543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
154314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(!mReconfigurationInProgress);
154414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mReconfigurationInProgress = true;
15457c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    if (bandwidthIndex >= 0) {
15467c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        mOrigBandwidthIndex = mCurBandwidthIndex;
15477c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        mCurBandwidthIndex = bandwidthIndex;
15488464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang        if (mOrigBandwidthIndex != mCurBandwidthIndex) {
15498464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            ALOGI("#### Starting Bandwidth Switch: %zd => %zd",
15508464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang                    mOrigBandwidthIndex, mCurBandwidthIndex);
15518464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang        }
15527c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    }
15537c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    CHECK_LT(mCurBandwidthIndex, mBandwidthItems.size());
15547c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    const BandwidthItem &item = mBandwidthItems.itemAt(mCurBandwidthIndex);
1555a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
15561543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    uint32_t streamMask = 0; // streams that should be fetched by the new fetcher
15571543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    uint32_t resumeMask = 0; // streams that should be fetched by the original fetcher
1558a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
15598ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    AString URIs[kMaxStreams];
15608ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
15618ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        if (mPlaylist->getTypeURI(item.mPlaylistIndex, mStreams[i].mType, &URIs[i])) {
15628ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            streamMask |= indexToType(i);
15638ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        }
156414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
1565aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber
156614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Step 1, stop and discard fetchers that are no longer needed.
156714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Pause those that we'll reuse.
156814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
15697c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // skip fetchers that are marked mToBeRemoved,
15707c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // these are done and can't be reused
15717c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        if (mFetcherInfos[i].mToBeRemoved) {
15727c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            continue;
15737c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        }
15747c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
157514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        const AString &uri = mFetcherInfos.keyAt(i);
1576d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        sp<PlaylistFetcher> &fetcher = mFetcherInfos.editValueAt(i).mFetcher;
1577aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber
1578d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        bool discardFetcher = true, delayRemoval = false;
1579c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        for (size_t j = 0; j < kMaxStreams; ++j) {
1580c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang            StreamType type = indexToType(j);
1581c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang            if ((streamMask & type) && uri == URIs[j]) {
1582c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang                resumeMask |= type;
1583c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang                streamMask &= ~type;
1584c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang                discardFetcher = false;
15856801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber            }
158614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
1587d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        // Delay fetcher removal if not picking tracks, AND old fetcher
1588d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        // has stream mask that overlaps new variant. (Okay to discard
1589d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        // old fetcher now, if completely no overlap.)
1590d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        if (discardFetcher && timeUs < 0ll && !pickTrack
1591d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                && (fetcher->getStreamTypeMask() & streamMask)) {
1592d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            discardFetcher = false;
1593d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            delayRemoval = true;
1594d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        }
1595a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
159614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (discardFetcher) {
159725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            ALOGV("discarding fetcher-%d", fetcher->getFetcherID());
1598d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            fetcher->stopAsync();
15996801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber        } else {
16008a048338d9291b2db1b3a325fff58cb1aa69f04dChong Zhang            float threshold = 0.0f; // default to pause after current block (47Kbytes)
16015abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang            bool disconnect = false;
1602a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang            if (timeUs >= 0ll) {
1603a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                // seeking, no need to finish fetching
16045abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang                disconnect = true;
1605d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            } else if (delayRemoval) {
1606a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                // adapting, abort if remaining of current segment is over threshold
1607a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                threshold = getAbortThreshold(
16087c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                        mOrigBandwidthIndex, mCurBandwidthIndex);
1609a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang            }
1610a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
161125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            ALOGV("pausing fetcher-%d, threshold=%.2f",
161225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                    fetcher->getFetcherID(), threshold);
16135abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang            fetcher->pauseAsync(threshold, disconnect);
16146801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber        }
1615a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1616a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
16171543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    sp<AMessage> msg;
16181543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    if (timeUs < 0ll) {
1619309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        // skip onChangeConfiguration2 (decoder destruction) if not seeking.
16201d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar        msg = new AMessage(kWhatChangeConfiguration3, this);
16211543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    } else {
16221d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar        msg = new AMessage(kWhatChangeConfiguration2, this);
16231543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
162414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    msg->setInt32("streamMask", streamMask);
16251543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    msg->setInt32("resumeMask", resumeMask);
1626309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    msg->setInt32("pickTrack", pickTrack);
162714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    msg->setInt64("timeUs", timeUs);
16288ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
1629309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        if ((streamMask | resumeMask) & indexToType(i)) {
16308ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            msg->setString(mStreams[i].uriKey().c_str(), URIs[i].c_str());
16318ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        }
16326e6b1cae2bac1b78205cefab8e4e9e9538982965Andreas Huber    }
1633a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
163414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Every time a fetcher acknowledges the stopAsync or pauseAsync request
163514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // we'll decrement mContinuationCounter, once it reaches zero, i.e. all
163614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // fetchers have completed their asynchronous operation, we'll post
163714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // mContinuation, which then is handled below in onChangeConfiguration2.
163814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mContinuationCounter = mFetcherInfos.size();
163914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mContinuation = msg;
164088b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber
164114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (mContinuationCounter == 0) {
164214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        msg->post();
164388b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber    }
164414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
1645a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1646dcb89b3b505522efde173c105a851c412f947178Chong Zhangvoid LiveSession::onChangeConfiguration(const sp<AMessage> &msg) {
164725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    ALOGV("onChangeConfiguration");
164825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang
1649dcb89b3b505522efde173c105a851c412f947178Chong Zhang    if (!mReconfigurationInProgress) {
16507c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        int32_t pickTrack = 0;
1651309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        msg->findInt32("pickTrack", &pickTrack);
16527c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        changeConfiguration(-1ll /* timeUs */, -1, pickTrack);
1653dcb89b3b505522efde173c105a851c412f947178Chong Zhang    } else {
1654dcb89b3b505522efde173c105a851c412f947178Chong Zhang        msg->post(1000000ll); // retry in 1 sec
1655dcb89b3b505522efde173c105a851c412f947178Chong Zhang    }
1656dcb89b3b505522efde173c105a851c412f947178Chong Zhang}
1657dcb89b3b505522efde173c105a851c412f947178Chong Zhang
165814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::onChangeConfiguration2(const sp<AMessage> &msg) {
165925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    ALOGV("onChangeConfiguration2");
166025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang
166114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mContinuation.clear();
1662bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
166314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // All fetchers are either suspended or have been removed now.
1664bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
1665964adb17885185808398507d2de88665fe193ee2Chong Zhang    // If we're seeking, clear all packet sources before we report
1666964adb17885185808398507d2de88665fe193ee2Chong Zhang    // seek complete, to prevent decoder from pulling stale data.
1667964adb17885185808398507d2de88665fe193ee2Chong Zhang    int64_t timeUs;
1668964adb17885185808398507d2de88665fe193ee2Chong Zhang    CHECK(msg->findInt64("timeUs", &timeUs));
1669964adb17885185808398507d2de88665fe193ee2Chong Zhang
1670964adb17885185808398507d2de88665fe193ee2Chong Zhang    if (timeUs >= 0) {
1671964adb17885185808398507d2de88665fe193ee2Chong Zhang        mLastSeekTimeUs = timeUs;
16728464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang        mLastDequeuedTimeUs = timeUs;
1673964adb17885185808398507d2de88665fe193ee2Chong Zhang
1674964adb17885185808398507d2de88665fe193ee2Chong Zhang        for (size_t i = 0; i < mPacketSources.size(); i++) {
16757f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih            sp<AnotherPacketSource> packetSource = mPacketSources.editValueAt(i);
16767f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih            sp<MetaData> format = packetSource->getFormat();
16777f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih            packetSource->clear();
16787f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih            // Set a tentative format here such that HTTPLiveSource will always have
16797f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih            // a format available when NuPlayer queries. Without an available video
16807f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih            // format when setting a surface NuPlayer might disable video decoding
16817f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih            // altogether. The tentative format will be overwritten by the
16827f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih            // authoritative (and possibly same) format once content from the new
16837f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih            // position is dequeued.
16847f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih            packetSource->setFormat(format);
1685964adb17885185808398507d2de88665fe193ee2Chong Zhang        }
1686964adb17885185808398507d2de88665fe193ee2Chong Zhang
16877c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        for (size_t i = 0; i < kMaxStreams; ++i) {
168881636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang            mStreams[i].reset();
16897c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        }
16907c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
1691964adb17885185808398507d2de88665fe193ee2Chong Zhang        mDiscontinuityOffsetTimesUs.clear();
1692964adb17885185808398507d2de88665fe193ee2Chong Zhang        mDiscontinuityAbsStartTimesUs.clear();
1693964adb17885185808398507d2de88665fe193ee2Chong Zhang
1694c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        if (mSeekReplyID != NULL) {
1695964adb17885185808398507d2de88665fe193ee2Chong Zhang            CHECK(mSeekReply != NULL);
1696964adb17885185808398507d2de88665fe193ee2Chong Zhang            mSeekReply->setInt32("err", OK);
1697964adb17885185808398507d2de88665fe193ee2Chong Zhang            mSeekReply->postReply(mSeekReplyID);
1698c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang            mSeekReplyID.clear();
1699964adb17885185808398507d2de88665fe193ee2Chong Zhang            mSeekReply.clear();
1700964adb17885185808398507d2de88665fe193ee2Chong Zhang        }
17017c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
17027c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // restart buffer polling after seek becauese previous
17037c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // buffering position is no longer valid.
17047c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        restartPollBuffering();
1705964adb17885185808398507d2de88665fe193ee2Chong Zhang    }
1706964adb17885185808398507d2de88665fe193ee2Chong Zhang
1707309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    uint32_t streamMask, resumeMask;
170814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(msg->findInt32("streamMask", (int32_t *)&streamMask));
1709309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    CHECK(msg->findInt32("resumeMask", (int32_t *)&resumeMask));
1710309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
1711309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    streamMask |= resumeMask;
1712bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
17138ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    AString URIs[kMaxStreams];
17148ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
17158ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        if (streamMask & indexToType(i)) {
17168ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            const AString &uriKey = mStreams[i].uriKey();
17178ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            CHECK(msg->findString(uriKey.c_str(), &URIs[i]));
17188ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            ALOGV("%s = '%s'", uriKey.c_str(), URIs[i].c_str());
17198ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        }
172022fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber    }
17213831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber
172214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    uint32_t changedMask = 0;
17238ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams && i != kSubtitleIndex; ++i) {
1724c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        // stream URI could change even if onChangeConfiguration2 is only
1725c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        // used for seek. Seek could happen during a bw switch, in this
1726c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        // case bw switch will be cancelled, but the seekTo position will
1727c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        // fetch from the new URI.
1728c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        if ((mStreamMask & streamMask & indexToType(i))
1729c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang                && !mStreams[i].mUri.empty()
1730c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang                && !(URIs[i] == mStreams[i].mUri)) {
17314604458dfe57b0e91a464aefafea50ae7b9876c1Chong Zhang            ALOGV("stream %zu changed: oldURI %s, newURI %s", i,
1732c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang                    mStreams[i].mUri.c_str(), URIs[i].c_str());
1733c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang            sp<AnotherPacketSource> source = mPacketSources.valueFor(indexToType(i));
17348464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            if (source->getLatestDequeuedMeta() != NULL) {
17358464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang                source->queueDiscontinuity(
17368464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang                        ATSParser::DISCONTINUITY_FORMATCHANGE, NULL, true);
17378464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            }
1738c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        }
1739c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        // Determine which decoders to shutdown on the player side,
1740c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        // a decoder has to be shutdown if its streamtype was active
1741c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        // before but now longer isn't.
1742c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        if ((mStreamMask & ~streamMask & indexToType(i))) {
17438ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            changedMask |= indexToType(i);
17448ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        }
1745b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber    }
1746b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
174714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (changedMask == 0) {
174814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        // If nothing changed as far as the audio/video decoders
174914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        // are concerned we can proceed.
175014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        onChangeConfiguration3(msg);
175114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        return;
175214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
175343c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
175414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Something changed, inform the player which will shutdown the
175514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // corresponding decoders and will post the reply once that's done.
175614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Handling the reply will continue executing below in
175714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // onChangeConfiguration3.
175814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> notify = mNotify->dup();
175914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->setInt32("what", kWhatStreamsChanged);
176014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->setInt32("changedMask", changedMask);
176120f725ebcef13ded1b4b85c61c8a4b37cd030656Andreas Huber
176214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    msg->setWhat(kWhatChangeConfiguration3);
17631d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    msg->setTarget(this);
1764b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
176514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->setMessage("reply", msg);
176614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->post();
176714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
1768b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
176914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::onChangeConfiguration3(const sp<AMessage> &msg) {
17701543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    mContinuation.clear();
177114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // All remaining fetchers are still suspended, the player has shutdown
177214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // any decoders that needed it.
1773b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
17741543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    uint32_t streamMask, resumeMask;
177514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(msg->findInt32("streamMask", (int32_t *)&streamMask));
17761543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    CHECK(msg->findInt32("resumeMask", (int32_t *)&resumeMask));
1777a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1778d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang    mNewStreamMask = streamMask | resumeMask;
1779d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang
178014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    int64_t timeUs;
1781309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    int32_t pickTrack;
17821543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    bool switching = false;
178314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(msg->findInt64("timeUs", &timeUs));
1784309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    CHECK(msg->findInt32("pickTrack", &pickTrack));
1785a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
178614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (timeUs < 0ll) {
1787309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        if (!pickTrack) {
1788d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            // mSwapMask contains streams that are in both old and new variant,
1789d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            // (in mNewStreamMask & mStreamMask) but with different URIs
1790d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            // (not in resumeMask).
1791d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            // For example, old variant has video and audio in two separate
1792d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            // URIs, and new variant has only audio with unchanged URI. mSwapMask
1793d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            // should be 0 as there is nothing to swap. We only need to stop video,
1794d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            // and resume audio.
1795d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            mSwapMask =  mNewStreamMask & mStreamMask & ~resumeMask;
1796d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            switching = (mSwapMask != 0);
1797309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        }
1798309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        mRealTimeBaseUs = ALooper::GetNowUs() - mLastDequeuedTimeUs;
1799309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    } else {
1800309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        mRealTimeBaseUs = ALooper::GetNowUs() - timeUs;
180114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
1802a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
180325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    ALOGV("onChangeConfiguration3: timeUs=%lld, switching=%d, pickTrack=%d, "
180425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            "mStreamMask=0x%x, mNewStreamMask=0x%x, mSwapMask=0x%x",
180525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            (long long)timeUs, switching, pickTrack,
180625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            mStreamMask, mNewStreamMask, mSwapMask);
180725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang
1808f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
1809f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        if (streamMask & indexToType(i)) {
1810f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            if (switching) {
1811f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih                CHECK(msg->findString(mStreams[i].uriKey().c_str(), &mStreams[i].mNewUri));
1812f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            } else {
1813f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih                CHECK(msg->findString(mStreams[i].uriKey().c_str(), &mStreams[i].mUri));
1814f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            }
1815f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        }
1816f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    }
1817f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih
18181543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // Of all existing fetchers:
18191543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // * Resume fetchers that are still needed and assign them original packet sources.
18201543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // * Mark otherwise unneeded fetchers for removal.
18211543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    ALOGV("resuming fetchers for mask 0x%08x", resumeMask);
182214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
182314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        const AString &uri = mFetcherInfos.keyAt(i);
18247c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        if (!resumeFetcher(uri, resumeMask, timeUs)) {
182525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            ALOGV("marking fetcher-%d to be removed",
182625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                    mFetcherInfos[i].mFetcher->getFetcherID());
182725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang
18287c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            mFetcherInfos.editValueAt(i).mToBeRemoved = true;
18291543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        }
1830a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1831a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
183214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // streamMask now only contains the types that need a new fetcher created.
183314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (streamMask != 0) {
183414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        ALOGV("creating new fetchers for mask 0x%08x", streamMask);
1835a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1836a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
18371543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // Find out when the original fetchers have buffered up to and start the new fetchers
18381543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // at a later timestamp.
18398ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams; i++) {
18408ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        if (!(indexToType(i) & streamMask)) {
18418ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            continue;
18428ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        }
18431156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
184414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        AString uri;
1845f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        uri = switching ? mStreams[i].mNewUri : mStreams[i].mUri;
18469b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber
184714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        sp<PlaylistFetcher> fetcher = addFetcher(uri.c_str());
184814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        CHECK(fetcher != NULL);
1849a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1850d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        HLSTime startTime;
1851a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        SeekMode seekMode = kSeekModeExactPosition;
18520852843d304006e3ab333081fddda13b07193de8Robert Shih        sp<AnotherPacketSource> sources[kNumSources];
18531543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
1854d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        if (i == kSubtitleIndex || (!pickTrack && !switching)) {
1855d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            startTime = latestMediaSegmentStartTime();
1856b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih        }
1857b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih
18588ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        // TRICKY: looping from i as earlier streams are already removed from streamMask
18598ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        for (size_t j = i; j < kMaxStreams; ++j) {
1860f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            const AString &streamUri = switching ? mStreams[j].mNewUri : mStreams[j].mUri;
1861f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            if ((streamMask & indexToType(j)) && uri == streamUri) {
18628ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                sources[j] = mPacketSources.valueFor(indexToType(j));
18631543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
1864309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                if (timeUs >= 0) {
1865d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                    startTime.mTimeUs = timeUs;
18661543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                } else {
1867309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    int32_t type;
1868309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    sp<AMessage> meta;
1869d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                    if (!switching) {
1870d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                        // selecting, or adapting but no swap required
1871309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        meta = sources[j]->getLatestDequeuedMeta();
1872309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    } else {
1873d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                        // adapting and swap required
1874309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        meta = sources[j]->getLatestEnqueuedMeta();
18757c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                        if (meta != NULL && mCurBandwidthIndex > mOrigBandwidthIndex) {
18767c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                            // switching up
18777c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                            meta = sources[j]->getMetaAfterLastDequeued(mUpSwitchMargin);
18787c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                        }
1879309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    }
18801543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
18810852843d304006e3ab333081fddda13b07193de8Robert Shih                    if ((j == kAudioIndex || j == kVideoIndex)
18820852843d304006e3ab333081fddda13b07193de8Robert Shih                            && meta != NULL && !meta->findInt32("discontinuity", &type)) {
1883d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                        HLSTime tmpTime(meta);
1884d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                        if (startTime < tmpTime) {
1885d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                            startTime = tmpTime;
18861543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        }
18871543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    }
18881543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
1889d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                    if (!switching) {
1890d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                        // selecting, or adapting but no swap required
1891309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        sources[j]->clear();
1892309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        if (j == kSubtitleIndex) {
1893309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                            break;
1894309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        }
1895964adb17885185808398507d2de88665fe193ee2Chong Zhang
18964604458dfe57b0e91a464aefafea50ae7b9876c1Chong Zhang                        ALOGV("stream[%zu]: queue format change", j);
1897964adb17885185808398507d2de88665fe193ee2Chong Zhang                        sources[j]->queueDiscontinuity(
1898a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                                ATSParser::DISCONTINUITY_FORMAT_ONLY, NULL, true);
1899309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    } else {
1900d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                        // switching, queue discontinuities after resume
1901309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        sources[j] = mPacketSources2.valueFor(indexToType(j));
1902309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        sources[j]->clear();
1903a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                        // the new fetcher might be providing streams that used to be
1904a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                        // provided by two different fetchers,  if one of the fetcher
1905a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                        // paused in the middle while the other somehow paused in next
1906a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                        // seg, we have to start from next seg.
1907a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                        if (seekMode < mStreams[j].mSeekMode) {
1908a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                            seekMode = mStreams[j].mSeekMode;
1909309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        }
19101543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    }
19111543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                }
1912a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
19138ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                streamMask &= ~indexToType(j);
19148ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            }
1915a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
191614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
191725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang        ALOGV("[fetcher-%d] startAsync: startTimeUs %lld mLastSeekTimeUs %lld "
191825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                "segmentStartTimeUs %lld seekMode %d",
191925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                fetcher->getFetcherID(),
192025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                (long long)startTime.mTimeUs,
192125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                (long long)mLastSeekTimeUs,
1922978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang                (long long)startTime.getSegmentTimeUs(),
192325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                seekMode);
192425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang
1925d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        // Set the target segment start time to the middle point of the
1926d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        // segment where the last sample was.
1927d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        // This gives a better guess if segments of the two variants are not
1928d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        // perfectly aligned. (If the corresponding segment in new variant
1929d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        // starts slightly later than that in the old variant, we still want
1930d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        // to pick that segment, not the one before)
19318ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        fetcher->startAsync(
19328ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                sources[kAudioIndex],
19338ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                sources[kVideoIndex],
19348ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                sources[kSubtitleIndex],
19350852843d304006e3ab333081fddda13b07193de8Robert Shih                getMetadataSource(sources, mNewStreamMask, switching),
1936d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                startTime.mTimeUs < 0 ? mLastSeekTimeUs : startTime.mTimeUs,
1937978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang                startTime.getSegmentTimeUs(),
1938d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                startTime.mSeq,
1939a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                seekMode);
1940a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1941a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
194214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // All fetchers have now been started, the configuration change
194314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // has completed.
1944a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
194514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mReconfigurationInProgress = false;
19461543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    if (switching) {
19471543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        mSwitchInProgress = true;
19481543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    } else {
19491543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        mStreamMask = mNewStreamMask;
19508464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang        if (mOrigBandwidthIndex != mCurBandwidthIndex) {
19518464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            ALOGV("#### Finished Bandwidth Switch Early: %zd => %zd",
19528464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang                    mOrigBandwidthIndex, mCurBandwidthIndex);
19538464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            mOrigBandwidthIndex = mCurBandwidthIndex;
19548464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang        }
19551543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
1956a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
195725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    ALOGV("onChangeConfiguration3: mSwitchInProgress %d, mStreamMask 0x%x",
195825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            mSwitchInProgress, mStreamMask);
195925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang
1960c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang    if (mDisconnectReplyID != NULL) {
196114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        finishDisconnect();
1962a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
196314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
1964a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1965a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhangvoid LiveSession::swapPacketSource(StreamType stream) {
196625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    ALOGV("[%s] swapPacketSource", getNameForStream(stream));
1967a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
1968a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    // transfer packets from source2 to source
1969a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    sp<AnotherPacketSource> &aps = mPacketSources.editValueFor(stream);
1970a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    sp<AnotherPacketSource> &aps2 = mPacketSources2.editValueFor(stream);
1971a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
1972a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    // queue discontinuity in mPacketSource
1973a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    aps->queueDiscontinuity(ATSParser::DISCONTINUITY_FORMAT_ONLY, NULL, false);
1974a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
1975a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    // queue packets in mPacketSource2 to mPacketSource
1976a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    status_t finalResult = OK;
1977a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    sp<ABuffer> accessUnit;
1978a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    while (aps2->hasBufferAvailable(&finalResult) && finalResult == OK &&
1979a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang          OK == aps2->dequeueAccessUnit(&accessUnit)) {
1980a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        aps->queueAccessUnit(accessUnit);
1981a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    }
1982a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    aps2->clear();
1983a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang}
1984a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
19857c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::tryToFinishBandwidthSwitch(const AString &oldUri) {
1986a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    if (!mSwitchInProgress) {
1987a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        return;
1988a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    }
1989a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
19907c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    ssize_t index = mFetcherInfos.indexOfKey(oldUri);
1991a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    if (index < 0 || !mFetcherInfos[index].mToBeRemoved) {
19921543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return;
19931543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
19941543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
1995a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    // Swap packet source of streams provided by old variant
1996a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    for (size_t idx = 0; idx < kMaxStreams; idx++) {
19977c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        StreamType stream = indexToType(idx);
19987c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        if ((mSwapMask & stream) && (oldUri == mStreams[idx].mUri)) {
1999a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang            swapPacketSource(stream);
2000a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
2001a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang            if ((mNewStreamMask & stream) && mStreams[idx].mNewUri.empty()) {
2002a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                ALOGW("swapping stream type %d %s to empty stream",
2003a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                        stream, mStreams[idx].mUri.c_str());
2004a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang            }
2005a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang            mStreams[idx].mUri = mStreams[idx].mNewUri;
2006a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang            mStreams[idx].mNewUri.clear();
2007a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
2008a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang            mSwapMask &= ~stream;
2009a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        }
2010f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    }
2011f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih
20127c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    mFetcherInfos.editValueAt(index).mFetcher->stopAsync(false /* clear */);
2013a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
201425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    ALOGV("tryToFinishBandwidthSwitch: mSwapMask=0x%x", mSwapMask);
2015309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    if (mSwapMask != 0) {
20161543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return;
20171543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
20181543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
20191543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // Check if new variant contains extra streams.
20201543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    uint32_t extraStreams = mNewStreamMask & (~mStreamMask);
20211543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    while (extraStreams) {
2022a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        StreamType stream = (StreamType) (extraStreams & ~(extraStreams - 1));
2023a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        extraStreams &= ~stream;
2024a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
2025a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        swapPacketSource(stream);
2026f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih
2027a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        ssize_t idx = typeToIndex(stream);
2028f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        CHECK(idx >= 0);
2029f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        if (mStreams[idx].mNewUri.empty()) {
2030f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            ALOGW("swapping extra stream type %d %s to empty stream",
2031a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                    stream, mStreams[idx].mUri.c_str());
2032f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        }
2033f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        mStreams[idx].mUri = mStreams[idx].mNewUri;
2034f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        mStreams[idx].mNewUri.clear();
20351543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
20361543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
2037a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    // Restart new fetcher (it was paused after the first 47k block)
2038a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    // and let it fetch into mPacketSources (not mPacketSources2)
2039a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
2040a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        FetcherInfo &info = mFetcherInfos.editValueAt(i);
2041a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        if (info.mToBeResumed) {
20427c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            resumeFetcher(mFetcherInfos.keyAt(i), mNewStreamMask);
2043a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang            info.mToBeResumed = false;
2044a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        }
2045a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    }
2046a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
20477c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    ALOGI("#### Finished Bandwidth Switch: %zd => %zd",
20487c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            mOrigBandwidthIndex, mCurBandwidthIndex);
20497c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
2050a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    mStreamMask = mNewStreamMask;
2051a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    mSwitchInProgress = false;
20527c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    mOrigBandwidthIndex = mCurBandwidthIndex;
2053a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
20547c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    restartPollBuffering();
20551543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
20561543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
2057964adb17885185808398507d2de88665fe193ee2Chong Zhangvoid LiveSession::schedulePollBuffering() {
2058964adb17885185808398507d2de88665fe193ee2Chong Zhang    sp<AMessage> msg = new AMessage(kWhatPollBuffering, this);
2059964adb17885185808398507d2de88665fe193ee2Chong Zhang    msg->setInt32("generation", mPollBufferingGeneration);
2060964adb17885185808398507d2de88665fe193ee2Chong Zhang    msg->post(1000000ll);
2061964adb17885185808398507d2de88665fe193ee2Chong Zhang}
2062678bcdc852dd8f801f5c46fdc85db587b721d83dApurupa Pattapu
2063964adb17885185808398507d2de88665fe193ee2Chong Zhangvoid LiveSession::cancelPollBuffering() {
2064964adb17885185808398507d2de88665fe193ee2Chong Zhang    ++mPollBufferingGeneration;
20657c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    mPrevBufferPercentage = -1;
20667c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang}
20677c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
20687c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::restartPollBuffering() {
20697c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    cancelPollBuffering();
20707c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    onPollBuffering();
2071964adb17885185808398507d2de88665fe193ee2Chong Zhang}
20720ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
2073964adb17885185808398507d2de88665fe193ee2Chong Zhangvoid LiveSession::onPollBuffering() {
2074964adb17885185808398507d2de88665fe193ee2Chong Zhang    ALOGV("onPollBuffering: mSwitchInProgress %d, mReconfigurationInProgress %d, "
2075a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang            "mInPreparationPhase %d, mCurBandwidthIndex %zd, mStreamMask 0x%x",
2076964adb17885185808398507d2de88665fe193ee2Chong Zhang        mSwitchInProgress, mReconfigurationInProgress,
2077538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        mInPreparationPhase, mCurBandwidthIndex, mStreamMask);
20780ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
20797c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    bool underflow, ready, down, up;
20807c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    if (checkBuffering(underflow, ready, down, up)) {
20818464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang        if (mInPreparationPhase) {
20828464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            // Allow down switch even if we're still preparing.
20838464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            //
20848464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            // Some streams have a high bandwidth index as default,
20858464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            // when bandwidth is low, it takes a long time to buffer
20868464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            // to ready mark, then it immediately pauses after start
20878464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            // as we have to do a down switch. It's better experience
20888464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            // to restart from a lower index, if we detect low bw.
20898464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            if (!switchBandwidthIfNeeded(false /* up */, down) && ready) {
20908464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang                postPrepared(OK);
20918464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            }
20920ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        }
20930ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
2094538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        if (!mInPreparationPhase) {
20957c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            if (ready) {
20967c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                stopBufferingIfNecessary();
20977c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            } else if (underflow) {
20987c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                startBufferingIfNecessary();
20997c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            }
21007c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            switchBandwidthIfNeeded(up, down);
21018464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang        }
21020ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    }
21030ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
2104964adb17885185808398507d2de88665fe193ee2Chong Zhang    schedulePollBuffering();
21050ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih}
21060ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
21077c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::cancelBandwidthSwitch(bool resume) {
21087c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    ALOGV("cancelBandwidthSwitch: mSwitchGen(%d)++, orig %zd, cur %zd",
21097c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            mSwitchGeneration, mOrigBandwidthIndex, mCurBandwidthIndex);
21107c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    if (!mSwitchInProgress) {
21117c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        return;
21127c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    }
2113f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih
2114f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
2115f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        FetcherInfo& info = mFetcherInfos.editValueAt(i);
2116f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        if (info.mToBeRemoved) {
2117f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            info.mToBeRemoved = false;
21187c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            if (resume) {
21197c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                resumeFetcher(mFetcherInfos.keyAt(i), mSwapMask);
21207c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            }
2121f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        }
2122f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    }
2123f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih
2124f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
21257c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        AString newUri = mStreams[i].mNewUri;
21267c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        if (!newUri.empty()) {
21277c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            // clear all mNewUri matching this newUri
21287c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            for (size_t j = i; j < kMaxStreams; ++j) {
21297c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                if (mStreams[j].mNewUri == newUri) {
21307c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    mStreams[j].mNewUri.clear();
21317c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                }
21327c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            }
21337c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            ALOGV("stopping newUri = %s", newUri.c_str());
21347c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            ssize_t index = mFetcherInfos.indexOfKey(newUri);
21357c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            if (index < 0) {
21367c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                ALOGE("did not find fetcher for newUri: %s", newUri.c_str());
2137f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih                continue;
2138f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            }
21397c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            FetcherInfo &info = mFetcherInfos.editValueAt(index);
21407c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            info.mToBeRemoved = true;
2141f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            info.mFetcher->stopAsync();
2142f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        }
2143f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    }
21447c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
21457c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    ALOGI("#### Canceled Bandwidth Switch: %zd => %zd",
214625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            mOrigBandwidthIndex, mCurBandwidthIndex);
21477c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
21487c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    mSwitchGeneration++;
21497c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    mSwitchInProgress = false;
21507c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    mCurBandwidthIndex = mOrigBandwidthIndex;
21517c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    mSwapMask = 0;
21521543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
21531543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
21547c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangbool LiveSession::checkBuffering(
21557c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        bool &underflow, bool &ready, bool &down, bool &up) {
21567c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    underflow = ready = down = up = false;
2157964adb17885185808398507d2de88665fe193ee2Chong Zhang
21587c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    if (mReconfigurationInProgress) {
2159964adb17885185808398507d2de88665fe193ee2Chong Zhang        ALOGV("Switch/Reconfig in progress, defer buffer polling");
21601543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return false;
21611543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
21621543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
21637c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    size_t activeCount, underflowCount, readyCount, downCount, upCount;
21647c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    activeCount = underflowCount = readyCount = downCount = upCount =0;
21657c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    int32_t minBufferPercent = -1;
21667c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    int64_t durationUs;
21677c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    if (getDuration(&durationUs) != OK) {
21687c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        durationUs = -1;
21697c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    }
2170964adb17885185808398507d2de88665fe193ee2Chong Zhang    for (size_t i = 0; i < mPacketSources.size(); ++i) {
2171964adb17885185808398507d2de88665fe193ee2Chong Zhang        // we don't check subtitles for buffering level
2172964adb17885185808398507d2de88665fe193ee2Chong Zhang        if (!(mStreamMask & mPacketSources.keyAt(i)
2173964adb17885185808398507d2de88665fe193ee2Chong Zhang                & (STREAMTYPE_AUDIO | STREAMTYPE_VIDEO))) {
2174964adb17885185808398507d2de88665fe193ee2Chong Zhang            continue;
2175964adb17885185808398507d2de88665fe193ee2Chong Zhang        }
2176964adb17885185808398507d2de88665fe193ee2Chong Zhang        // ignore streams that never had any packet queued.
2177964adb17885185808398507d2de88665fe193ee2Chong Zhang        // (it's possible that the variant only has audio or video)
2178964adb17885185808398507d2de88665fe193ee2Chong Zhang        sp<AMessage> meta = mPacketSources[i]->getLatestEnqueuedMeta();
2179964adb17885185808398507d2de88665fe193ee2Chong Zhang        if (meta == NULL) {
2180964adb17885185808398507d2de88665fe193ee2Chong Zhang            continue;
2181964adb17885185808398507d2de88665fe193ee2Chong Zhang        }
2182964adb17885185808398507d2de88665fe193ee2Chong Zhang
21830dd229bb306df68b88e7419b3cc11fc6175be1daRobert Shih        status_t finalResult;
2184964adb17885185808398507d2de88665fe193ee2Chong Zhang        int64_t bufferedDurationUs =
21850dd229bb306df68b88e7419b3cc11fc6175be1daRobert Shih                mPacketSources[i]->getBufferedDurationUs(&finalResult);
218625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang        ALOGV("[%s] buffered %lld us",
218725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                getNameForStream(mPacketSources.keyAt(i)),
218825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                (long long)bufferedDurationUs);
21897c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        if (durationUs >= 0) {
21907c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            int32_t percent;
21917c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            if (mPacketSources[i]->isFinished(0 /* duration */)) {
21927c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                percent = 100;
21937c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            } else {
21948464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang                percent = (int32_t)(100.0 *
21958464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang                        (mLastDequeuedTimeUs + bufferedDurationUs) / durationUs);
21967c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            }
21977c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            if (minBufferPercent < 0 || percent < minBufferPercent) {
21987c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                minBufferPercent = percent;
21997c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            }
2200964adb17885185808398507d2de88665fe193ee2Chong Zhang        }
22017c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
22027c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        ++activeCount;
220348fa06d1e80a872c7495804979256e021e566ae0Wei Jia        int64_t readyMarkUs =
220448fa06d1e80a872c7495804979256e021e566ae0Wei Jia            (mInPreparationPhase ?
220548fa06d1e80a872c7495804979256e021e566ae0Wei Jia                mBufferingSettings.mInitialWatermarkMs :
220648fa06d1e80a872c7495804979256e021e566ae0Wei Jia                mBufferingSettings.mRebufferingWatermarkHighMs) * 1000ll;
220748fa06d1e80a872c7495804979256e021e566ae0Wei Jia        if (bufferedDurationUs > readyMarkUs
22087c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                || mPacketSources[i]->isFinished(0)) {
22097c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            ++readyCount;
22107c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        }
22117c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        if (!mPacketSources[i]->isFinished(0)) {
221248fa06d1e80a872c7495804979256e021e566ae0Wei Jia            if (bufferedDurationUs < mBufferingSettings.mRebufferingWatermarkLowMs * 1000ll) {
22137c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                ++underflowCount;
22147c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            }
22157c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            if (bufferedDurationUs > mUpSwitchMark) {
22167c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                ++upCount;
2217d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            }
2218d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            if (bufferedDurationUs < mDownSwitchMark) {
22197c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                ++downCount;
22207c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            }
22217c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        }
22227c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    }
22237c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
22247c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    if (minBufferPercent >= 0) {
22257c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        notifyBufferingUpdate(minBufferPercent);
222614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
222714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
2228964adb17885185808398507d2de88665fe193ee2Chong Zhang    if (activeCount > 0) {
22297c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        up        = (upCount == activeCount);
22307c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        down      = (downCount > 0);
22317c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        ready     = (readyCount == activeCount);
22327c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        underflow = (underflowCount > 0);
22331543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return true;
22341543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
2235964adb17885185808398507d2de88665fe193ee2Chong Zhang
2236964adb17885185808398507d2de88665fe193ee2Chong Zhang    return false;
22371543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
22381543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
22397c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::startBufferingIfNecessary() {
22407c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    ALOGV("startBufferingIfNecessary: mInPreparationPhase=%d, mBuffering=%d",
22417c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            mInPreparationPhase, mBuffering);
22427c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    if (!mBuffering) {
22437c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        mBuffering = true;
22447c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
22457c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        sp<AMessage> notify = mNotify->dup();
22467c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        notify->setInt32("what", kWhatBufferingStart);
22477c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        notify->post();
22487c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    }
22497c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang}
22507c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
22517c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::stopBufferingIfNecessary() {
22527c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    ALOGV("stopBufferingIfNecessary: mInPreparationPhase=%d, mBuffering=%d",
22537c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            mInPreparationPhase, mBuffering);
22547c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
22557c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    if (mBuffering) {
22567c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        mBuffering = false;
22577c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
22587c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        sp<AMessage> notify = mNotify->dup();
22597c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        notify->setInt32("what", kWhatBufferingEnd);
22607c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        notify->post();
22617c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    }
22627c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang}
22637c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
22647c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::notifyBufferingUpdate(int32_t percentage) {
22657c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    if (percentage < mPrevBufferPercentage) {
22667c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        percentage = mPrevBufferPercentage;
22677c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    } else if (percentage > 100) {
22687c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        percentage = 100;
22697c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    }
22707c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
22717c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    mPrevBufferPercentage = percentage;
22727c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
22737c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    ALOGV("notifyBufferingUpdate: percentage=%d%%", percentage);
22747c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
22757c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    sp<AMessage> notify = mNotify->dup();
22767c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    notify->setInt32("what", kWhatBufferingUpdate);
22777c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    notify->setInt32("percentage", percentage);
22787c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    notify->post();
22797c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang}
22807c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
22815ef659e010e90175eb5282d9642a02f6105189bfChong Zhangbool LiveSession::tryBandwidthFallback() {
22825ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    if (mInPreparationPhase || mReconfigurationInProgress) {
22835ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        // Don't try fallback during prepare or reconfig.
22845ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        // If error happens there, it's likely unrecoverable.
22855ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        return false;
22865ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    }
22875ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    if (mCurBandwidthIndex > mOrigBandwidthIndex) {
22885ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        // if we're switching up, simply cancel and resume old variant
22895ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        cancelBandwidthSwitch(true /* resume */);
22905ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        return true;
22915ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    } else {
22925ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        // if we're switching down, we're likely about to underflow (if
22935ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        // not already underflowing). try the lowest viable bandwidth if
22945ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        // not on that variant already.
22955ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        ssize_t lowestValid = getLowestValidBandwidthIndex();
22965ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        if (mCurBandwidthIndex > lowestValid) {
22975ef659e010e90175eb5282d9642a02f6105189bfChong Zhang            cancelBandwidthSwitch();
22985ef659e010e90175eb5282d9642a02f6105189bfChong Zhang            changeConfiguration(-1ll, lowestValid);
22995ef659e010e90175eb5282d9642a02f6105189bfChong Zhang            return true;
23005ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        }
23015ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    }
23025ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    // return false if we couldn't find any fallback
23035ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    return false;
23045ef659e010e90175eb5282d9642a02f6105189bfChong Zhang}
23055ef659e010e90175eb5282d9642a02f6105189bfChong Zhang
23068464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang/*
23078464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang * returns true if a bandwidth switch is actually needed (and started),
23088464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang * returns false otherwise
23098464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang */
23108464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhangbool LiveSession::switchBandwidthIfNeeded(bool bufferHigh, bool bufferLow) {
2311538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    // no need to check bandwidth if we only have 1 bandwidth settings
23125ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    if (mBandwidthItems.size() < 2) {
23135ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        return false;
23145ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    }
23155ef659e010e90175eb5282d9642a02f6105189bfChong Zhang
23165ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    if (mSwitchInProgress) {
23175ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        if (mBuffering) {
23185ef659e010e90175eb5282d9642a02f6105189bfChong Zhang            tryBandwidthFallback();
23195ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        }
23208464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang        return false;
2321538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    }
2322538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
23235ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    int32_t bandwidthBps, shortTermBps;
2324978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    bool isStable;
23255ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    if (mBandwidthEstimator->estimateBandwidth(
23265ef659e010e90175eb5282d9642a02f6105189bfChong Zhang            &bandwidthBps, &isStable, &shortTermBps)) {
23275ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        ALOGV("bandwidth estimated at %.2f kbps, "
23285ef659e010e90175eb5282d9642a02f6105189bfChong Zhang                "stable %d, shortTermBps %.2f kbps",
23295ef659e010e90175eb5282d9642a02f6105189bfChong Zhang                bandwidthBps / 1024.0f, isStable, shortTermBps / 1024.0f);
2330a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        mLastBandwidthBps = bandwidthBps;
23315ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        mLastBandwidthStable = isStable;
2332538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    } else {
2333538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        ALOGV("no bandwidth estimate.");
23348464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang        return false;
2335538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    }
2336538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
2337538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    int32_t curBandwidth = mBandwidthItems.itemAt(mCurBandwidthIndex).mBandwidth;
2338d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang    // canSwithDown and canSwitchUp can't both be true.
2339d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang    // we only want to switch up when measured bw is 120% higher than current variant,
2340d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang    // and we only want to switch down when measured bw is below current variant.
2341978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    bool canSwitchDown = bufferLow
2342d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            && (bandwidthBps < (int32_t)curBandwidth);
2343d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang    bool canSwitchUp = bufferHigh
2344d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            && (bandwidthBps > (int32_t)curBandwidth * 12 / 10);
2345d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang
2346978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    if (canSwitchDown || canSwitchUp) {
2347978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang        // bandwidth estimating has some delay, if we have to downswitch when
23485ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        // it hasn't stabilized, use the short term to guess real bandwidth,
23495ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        // since it may be dropping too fast.
23505ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        // (note this doesn't apply to upswitch, always use longer average there)
2351978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang        if (!isStable && canSwitchDown) {
23525ef659e010e90175eb5282d9642a02f6105189bfChong Zhang            if (shortTermBps < bandwidthBps) {
23535ef659e010e90175eb5282d9642a02f6105189bfChong Zhang                bandwidthBps = shortTermBps;
23545ef659e010e90175eb5282d9642a02f6105189bfChong Zhang            }
2355978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang        }
2356978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang
2357538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        ssize_t bandwidthIndex = getBandwidthIndex(bandwidthBps);
2358538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
2359d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        // it's possible that we're checking for canSwitchUp case, but the returned
2360d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        // bandwidthIndex is < mCurBandwidthIndex, as getBandwidthIndex() only uses 70%
2361d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        // of measured bw. In that case we don't want to do anything, since we have
2362d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        // both enough buffer and enough bw.
23638464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang        if ((canSwitchUp && bandwidthIndex > mCurBandwidthIndex)
2364978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang         || (canSwitchDown && bandwidthIndex < mCurBandwidthIndex)) {
23658464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            // if not yet prepared, just restart again with new bw index.
23668464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            // this is faster and playback experience is cleaner.
23678464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            changeConfiguration(
23688464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang                    mInPreparationPhase ? 0 : -1ll, bandwidthIndex);
23698464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            return true;
2370538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        }
237114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
23728464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang    return false;
2373a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
2374a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
23757c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::postError(status_t err) {
23767c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    // if we reached EOS, notify buffering of 100%
23777c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    if (err == ERROR_END_OF_STREAM) {
23787c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        notifyBufferingUpdate(100);
23797c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    }
23807c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    // we'll stop buffer polling now, before that notify
23817c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    // stop buffering to stop the spinning icon
23827c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    stopBufferingIfNecessary();
23837c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    cancelPollBuffering();
23847c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
23857c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    sp<AMessage> notify = mNotify->dup();
23867c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    notify->setInt32("what", kWhatError);
23877c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    notify->setInt32("err", err);
23887c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    notify->post();
23897c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang}
23907c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
239114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::postPrepared(status_t err) {
239214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(mInPreparationPhase);
2393a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
239414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> notify = mNotify->dup();
239514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (err == OK || err == ERROR_END_OF_STREAM) {
239614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        notify->setInt32("what", kWhatPrepared);
239714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    } else {
23987c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        cancelPollBuffering();
23997c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
240014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        notify->setInt32("what", kWhatPreparationFailed);
240114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        notify->setInt32("err", err);
240214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
2403a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
240414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->post();
2405a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
240614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mInPreparationPhase = false;
2407b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber}
2408b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
2409964adb17885185808398507d2de88665fe193ee2Chong Zhang
2410a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}  // namespace android
2411a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
2412