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>
2973feb8cda587e02f1ff68095b17d47e1d6e37c70Wei Jia#include <media/MediaHTTPService.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
529bb3803a80a680ea7a3bc11e07b8a89ccddee003Wei Jia//TODO: redefine this mark to a fair value
539bb3803a80a680ea7a3bc11e07b8a89ccddee003Wei Jia// default buffer underflow mark
549bb3803a80a680ea7a3bc11e07b8a89ccddee003Wei Jiastatic const int kUnderflowMarkMs = 1000;  // 1 second
559bb3803a80a680ea7a3bc11e07b8a89ccddee003Wei Jia
56538b6d22a3578c0201d48f8548289aa254d81484Chong Zhangstruct LiveSession::BandwidthEstimator : public RefBase {
57538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    BandwidthEstimator();
58538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
59538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    void addBandwidthMeasurement(size_t numBytes, int64_t delayUs);
605ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    bool estimateBandwidth(
615ef659e010e90175eb5282d9642a02f6105189bfChong Zhang            int32_t *bandwidth,
625ef659e010e90175eb5282d9642a02f6105189bfChong Zhang            bool *isStable = NULL,
635ef659e010e90175eb5282d9642a02f6105189bfChong Zhang            int32_t *shortTermBps = NULL);
64538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
65538b6d22a3578c0201d48f8548289aa254d81484Chong Zhangprivate:
66538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    // Bandwidth estimation parameters
675ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    static const int32_t kShortTermBandwidthItems = 3;
6881636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang    static const int32_t kMinBandwidthHistoryItems = 20;
6981636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang    static const int64_t kMinBandwidthHistoryWindowUs = 5000000ll; // 5 sec
7081636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang    static const int64_t kMaxBandwidthHistoryWindowUs = 30000000ll; // 30 sec
715ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    static const int64_t kMaxBandwidthHistoryAgeUs = 60000000ll; // 60 sec
72538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
73538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    struct BandwidthEntry {
745ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        int64_t mTimestampUs;
75538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        int64_t mDelayUs;
76538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        size_t mNumBytes;
77538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    };
78538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
79538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    Mutex mLock;
80538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    List<BandwidthEntry> mBandwidthHistory;
81978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    List<int32_t> mPrevEstimates;
825ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    int32_t mShortTermEstimate;
83978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    bool mHasNewSample;
84978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    bool mIsStable;
85538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    int64_t mTotalTransferTimeUs;
86538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    size_t mTotalTransferBytes;
87538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
88538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    DISALLOW_EVIL_CONSTRUCTORS(BandwidthEstimator);
89538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang};
90538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
91538b6d22a3578c0201d48f8548289aa254d81484Chong ZhangLiveSession::BandwidthEstimator::BandwidthEstimator() :
925ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    mShortTermEstimate(0),
93978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    mHasNewSample(false),
94978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    mIsStable(true),
95538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    mTotalTransferTimeUs(0),
96538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    mTotalTransferBytes(0) {
97538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang}
98538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
99538b6d22a3578c0201d48f8548289aa254d81484Chong Zhangvoid LiveSession::BandwidthEstimator::addBandwidthMeasurement(
100538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        size_t numBytes, int64_t delayUs) {
101538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    AutoMutex autoLock(mLock);
102538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
1035ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    int64_t nowUs = ALooper::GetNowUs();
104538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    BandwidthEntry entry;
1055ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    entry.mTimestampUs = nowUs;
106538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    entry.mDelayUs = delayUs;
107538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    entry.mNumBytes = numBytes;
108538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    mTotalTransferTimeUs += delayUs;
109538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    mTotalTransferBytes += numBytes;
110538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    mBandwidthHistory.push_back(entry);
111978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    mHasNewSample = true;
112538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
11381636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang    // Remove no more than 10% of total transfer time at a time
11481636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang    // to avoid sudden jump on bandwidth estimation. There might
11581636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang    // be long blocking reads that takes up signification time,
11681636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang    // we have to keep a longer window in that case.
11781636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang    int64_t bandwidthHistoryWindowUs = mTotalTransferTimeUs * 9 / 10;
11881636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang    if (bandwidthHistoryWindowUs < kMinBandwidthHistoryWindowUs) {
11981636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang        bandwidthHistoryWindowUs = kMinBandwidthHistoryWindowUs;
12081636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang    } else if (bandwidthHistoryWindowUs > kMaxBandwidthHistoryWindowUs) {
12181636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang        bandwidthHistoryWindowUs = kMaxBandwidthHistoryWindowUs;
12281636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang    }
123538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    // trim old samples, keeping at least kMaxBandwidthHistoryItems samples,
124538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    // and total transfer time at least kMaxBandwidthHistoryWindowUs.
12581636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang    while (mBandwidthHistory.size() > kMinBandwidthHistoryItems) {
126538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        List<BandwidthEntry>::iterator it = mBandwidthHistory.begin();
1275ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        // remove sample if either absolute age or total transfer time is
1285ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        // over kMaxBandwidthHistoryWindowUs
1295ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        if (nowUs - it->mTimestampUs < kMaxBandwidthHistoryAgeUs &&
1305ef659e010e90175eb5282d9642a02f6105189bfChong Zhang                mTotalTransferTimeUs - it->mDelayUs < bandwidthHistoryWindowUs) {
131538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang            break;
132538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        }
133538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        mTotalTransferTimeUs -= it->mDelayUs;
134538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        mTotalTransferBytes -= it->mNumBytes;
135538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        mBandwidthHistory.erase(mBandwidthHistory.begin());
136538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    }
137538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang}
138538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
13981636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhangbool LiveSession::BandwidthEstimator::estimateBandwidth(
1405ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        int32_t *bandwidthBps, bool *isStable, int32_t *shortTermBps) {
141538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    AutoMutex autoLock(mLock);
142538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
143538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    if (mBandwidthHistory.size() < 2) {
144538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        return false;
145538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    }
146538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
147978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    if (!mHasNewSample) {
148978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang        *bandwidthBps = *(--mPrevEstimates.end());
149978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang        if (isStable) {
150978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang            *isStable = mIsStable;
151978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang        }
1525ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        if (shortTermBps) {
1535ef659e010e90175eb5282d9642a02f6105189bfChong Zhang            *shortTermBps = mShortTermEstimate;
1545ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        }
155978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang        return true;
156978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    }
157978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang
158538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    *bandwidthBps = ((double)mTotalTransferBytes * 8E6 / mTotalTransferTimeUs);
159978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    mPrevEstimates.push_back(*bandwidthBps);
160978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    while (mPrevEstimates.size() > 3) {
161978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang        mPrevEstimates.erase(mPrevEstimates.begin());
162978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    }
163978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    mHasNewSample = false;
164978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang
1655ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    int64_t totalTimeUs = 0;
1665ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    size_t totalBytes = 0;
1675ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    if (mBandwidthHistory.size() >= kShortTermBandwidthItems) {
1685ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        List<BandwidthEntry>::iterator it = --mBandwidthHistory.end();
1695ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        for (size_t i = 0; i < kShortTermBandwidthItems; i++, it--) {
1705ef659e010e90175eb5282d9642a02f6105189bfChong Zhang            totalTimeUs += it->mDelayUs;
1715ef659e010e90175eb5282d9642a02f6105189bfChong Zhang            totalBytes += it->mNumBytes;
1725ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        }
1735ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    }
1745ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    mShortTermEstimate = totalTimeUs > 0 ?
1755ef659e010e90175eb5282d9642a02f6105189bfChong Zhang            (totalBytes * 8E6 / totalTimeUs) : *bandwidthBps;
1765ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    if (shortTermBps) {
1775ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        *shortTermBps = mShortTermEstimate;
1785ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    }
1795ef659e010e90175eb5282d9642a02f6105189bfChong Zhang
180a6ff3a8a9bd17e8a5a421b409b58b8497842ebefRobert Shih    int64_t minEstimate = -1, maxEstimate = -1;
181978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    List<int32_t>::iterator it;
182978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    for (it = mPrevEstimates.begin(); it != mPrevEstimates.end(); it++) {
183978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang        int32_t estimate = *it;
184978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang        if (minEstimate < 0 || minEstimate > estimate) {
185978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang            minEstimate = estimate;
186978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang        }
187978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang        if (maxEstimate < 0 || maxEstimate < estimate) {
188978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang            maxEstimate = estimate;
189978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang        }
190978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    }
1915ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    // consider it stable if long-term average is not jumping a lot
1925ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    // and short-term average is not much lower than long-term average
1935ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    mIsStable = (maxEstimate <= minEstimate * 4 / 3)
1945ef659e010e90175eb5282d9642a02f6105189bfChong Zhang            && mShortTermEstimate > minEstimate * 7 / 10;
195978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    if (isStable) {
1965ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        *isStable = mIsStable;
197978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    }
1985ef659e010e90175eb5282d9642a02f6105189bfChong Zhang
19981636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang#if 0
20081636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang    {
20181636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang        char dumpStr[1024] = {0};
20281636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang        size_t itemIdx = 0;
20381636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang        size_t histSize = mBandwidthHistory.size();
20481636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang        sprintf(dumpStr, "estimate bps=%d stable=%d history (n=%d): {",
20581636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang            *bandwidthBps, mIsStable, histSize);
20681636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang        List<BandwidthEntry>::iterator it = mBandwidthHistory.begin();
20781636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang        for (; it != mBandwidthHistory.end(); ++it) {
20881636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang            if (itemIdx > 50) {
20981636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang                sprintf(dumpStr + strlen(dumpStr),
21081636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang                        "...(%zd more items)... }", histSize - itemIdx);
21181636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang                break;
21281636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang            }
21381636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang            sprintf(dumpStr + strlen(dumpStr), "%dk/%.3fs%s",
21481636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang                it->mNumBytes / 1024,
21581636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang                (double)it->mDelayUs * 1.0e-6,
21681636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang                (it == (--mBandwidthHistory.end())) ? "}" : ", ");
21781636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang            itemIdx++;
21881636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang        }
21981636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang        ALOGE(dumpStr);
22081636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang    }
22181636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang#endif
222538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    return true;
223538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang}
224538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
2257c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang//static
2267c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangconst char *LiveSession::getKeyForStream(StreamType type) {
2277c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    switch (type) {
2287c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        case STREAMTYPE_VIDEO:
2297c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            return "timeUsVideo";
2307c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        case STREAMTYPE_AUDIO:
2317c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            return "timeUsAudio";
2327c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        case STREAMTYPE_SUBTITLES:
2337c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            return "timeUsSubtitle";
2340852843d304006e3ab333081fddda13b07193de8Robert Shih        case STREAMTYPE_METADATA:
2350852843d304006e3ab333081fddda13b07193de8Robert Shih            return "timeUsMetadata"; // unused
2367c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        default:
2377c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            TRESPASS();
2387c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    }
2397c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    return NULL;
2407c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang}
2417c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
24225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang//static
24325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhangconst char *LiveSession::getNameForStream(StreamType type) {
24425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    switch (type) {
24525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang        case STREAMTYPE_VIDEO:
24625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            return "video";
24725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang        case STREAMTYPE_AUDIO:
24825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            return "audio";
24925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang        case STREAMTYPE_SUBTITLES:
25025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            return "subs";
2510852843d304006e3ab333081fddda13b07193de8Robert Shih        case STREAMTYPE_METADATA:
2520852843d304006e3ab333081fddda13b07193de8Robert Shih            return "metadata";
25325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang        default:
25425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            break;
25525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    }
25625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    return "unknown";
25725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang}
25825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang
2590852843d304006e3ab333081fddda13b07193de8Robert Shih//static
2600852843d304006e3ab333081fddda13b07193de8Robert ShihATSParser::SourceType LiveSession::getSourceTypeForStream(StreamType type) {
2610852843d304006e3ab333081fddda13b07193de8Robert Shih    switch (type) {
2620852843d304006e3ab333081fddda13b07193de8Robert Shih        case STREAMTYPE_VIDEO:
2630852843d304006e3ab333081fddda13b07193de8Robert Shih            return ATSParser::VIDEO;
2640852843d304006e3ab333081fddda13b07193de8Robert Shih        case STREAMTYPE_AUDIO:
2650852843d304006e3ab333081fddda13b07193de8Robert Shih            return ATSParser::AUDIO;
2660852843d304006e3ab333081fddda13b07193de8Robert Shih        case STREAMTYPE_METADATA:
2670852843d304006e3ab333081fddda13b07193de8Robert Shih            return ATSParser::META;
2680852843d304006e3ab333081fddda13b07193de8Robert Shih        case STREAMTYPE_SUBTITLES:
2690852843d304006e3ab333081fddda13b07193de8Robert Shih        default:
2700852843d304006e3ab333081fddda13b07193de8Robert Shih            TRESPASS();
2710852843d304006e3ab333081fddda13b07193de8Robert Shih    }
2720852843d304006e3ab333081fddda13b07193de8Robert Shih    return ATSParser::NUM_SOURCE_TYPES; // should not reach here
2730852843d304006e3ab333081fddda13b07193de8Robert Shih}
2740852843d304006e3ab333081fddda13b07193de8Robert Shih
2750df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas HuberLiveSession::LiveSession(
2761b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        const sp<AMessage> &notify, uint32_t flags,
27773feb8cda587e02f1ff68095b17d47e1d6e37c70Wei Jia        const sp<MediaHTTPService> &httpService)
2780df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas Huber    : mNotify(notify),
2790df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas Huber      mFlags(flags),
2801b86fe063badb5f28c467ade39be0f4008688947Andreas Huber      mHTTPService(httpService),
2817c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang      mBuffering(false),
2820df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas Huber      mInPreparationPhase(true),
2837c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang      mPollBufferingGeneration(0),
2847c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang      mPrevBufferPercentage(-1),
285309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih      mCurBandwidthIndex(-1),
2867c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang      mOrigBandwidthIndex(-1),
287a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang      mLastBandwidthBps(-1ll),
2885ef659e010e90175eb5282d9642a02f6105189bfChong Zhang      mLastBandwidthStable(false),
289538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang      mBandwidthEstimator(new BandwidthEstimator()),
290a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang      mMaxWidth(720),
291a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang      mMaxHeight(480),
29214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber      mStreamMask(0),
2931543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih      mNewStreamMask(0),
2941543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih      mSwapMask(0),
2951543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih      mSwitchGeneration(0),
296b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih      mSubtitleGeneration(0),
29714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber      mLastDequeuedTimeUs(0ll),
298dcb89b3b505522efde173c105a851c412f947178Chong Zhang      mRealTimeBaseUs(0ll),
29914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber      mReconfigurationInProgress(false),
3001543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih      mSwitchInProgress(false),
301765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang      mUpSwitchMark(kUpSwitchMarkUs),
302765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang      mDownSwitchMark(kDownSwitchMarkUs),
303765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang      mUpSwitchMargin(kUpSwitchMarginUs),
304309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih      mFirstTimeUsValid(false),
305309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih      mFirstTimeUs(0),
3060852843d304006e3ab333081fddda13b07193de8Robert Shih      mLastSeekTimeUs(0),
3070852843d304006e3ab333081fddda13b07193de8Robert Shih      mHasMetadata(false) {
3088ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    mStreams[kAudioIndex] = StreamItem("audio");
3098ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    mStreams[kVideoIndex] = StreamItem("video");
310e4f25c280a8f1655c31a745978e0fcbc61f91deeRobert Shih    mStreams[kSubtitleIndex] = StreamItem("subtitles");
31114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
3120852843d304006e3ab333081fddda13b07193de8Robert Shih    for (size_t i = 0; i < kNumSources; ++i) {
3138ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        mPacketSources.add(indexToType(i), new AnotherPacketSource(NULL /* meta */));
3141543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        mPacketSources2.add(indexToType(i), new AnotherPacketSource(NULL /* meta */));
3158ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    }
316a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
317a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
318a44153c1a57202fb538659eb50706e60454d6273Andreas HuberLiveSession::~LiveSession() {
319964adb17885185808398507d2de88665fe193ee2Chong Zhang    if (mFetcherLooper != NULL) {
320964adb17885185808398507d2de88665fe193ee2Chong Zhang        mFetcherLooper->stop();
321964adb17885185808398507d2de88665fe193ee2Chong Zhang    }
322a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
323a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
3240852843d304006e3ab333081fddda13b07193de8Robert Shihint64_t LiveSession::calculateMediaTimeUs(
3250852843d304006e3ab333081fddda13b07193de8Robert Shih        int64_t firstTimeUs, int64_t timeUs, int32_t discontinuitySeq) {
3260852843d304006e3ab333081fddda13b07193de8Robert Shih    if (timeUs >= firstTimeUs) {
3270852843d304006e3ab333081fddda13b07193de8Robert Shih        timeUs -= firstTimeUs;
3280852843d304006e3ab333081fddda13b07193de8Robert Shih    } else {
3290852843d304006e3ab333081fddda13b07193de8Robert Shih        timeUs = 0;
3300852843d304006e3ab333081fddda13b07193de8Robert Shih    }
3310852843d304006e3ab333081fddda13b07193de8Robert Shih    timeUs += mLastSeekTimeUs;
3320852843d304006e3ab333081fddda13b07193de8Robert Shih    if (mDiscontinuityOffsetTimesUs.indexOfKey(discontinuitySeq) >= 0) {
3330852843d304006e3ab333081fddda13b07193de8Robert Shih        timeUs += mDiscontinuityOffsetTimesUs.valueFor(discontinuitySeq);
3340852843d304006e3ab333081fddda13b07193de8Robert Shih    }
3350852843d304006e3ab333081fddda13b07193de8Robert Shih    return timeUs;
3360852843d304006e3ab333081fddda13b07193de8Robert Shih}
3370852843d304006e3ab333081fddda13b07193de8Robert Shih
33814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::dequeueAccessUnit(
33914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        StreamType stream, sp<ABuffer> *accessUnit) {
340964adb17885185808398507d2de88665fe193ee2Chong Zhang    status_t finalResult = OK;
34114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AnotherPacketSource> packetSource = mPacketSources.valueFor(stream);
34214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
34325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    ssize_t streamIdx = typeToIndex(stream);
34425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    if (streamIdx < 0) {
3455abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang        return BAD_VALUE;
34625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    }
34725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    const char *streamStr = getNameForStream(stream);
348a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    // Do not let client pull data if we don't have data packets yet.
349a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    // We might only have a format discontinuity queued without data.
350a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    // When NuPlayerDecoder dequeues the format discontinuity, it will
351a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    // immediately try to getFormat. If we return NULL, NuPlayerDecoder
352a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    // thinks it can do seamless change, so will not shutdown decoder.
353a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    // When the actual format arrives, it can't handle it and get stuck.
354a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    if (!packetSource->hasDataBufferAvailable(&finalResult)) {
35525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang        ALOGV("[%s] dequeueAccessUnit: no buffer available (finalResult=%d)",
35625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                streamStr, finalResult);
35725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang
358f69c996864844e8f669308af8412cede043062a2Robert Shih        if (finalResult == OK) {
359f69c996864844e8f669308af8412cede043062a2Robert Shih            return -EAGAIN;
360f69c996864844e8f669308af8412cede043062a2Robert Shih        } else {
361f69c996864844e8f669308af8412cede043062a2Robert Shih            return finalResult;
362f69c996864844e8f669308af8412cede043062a2Robert Shih        }
363f69c996864844e8f669308af8412cede043062a2Robert Shih    }
364f69c996864844e8f669308af8412cede043062a2Robert Shih
365a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    // Let the client dequeue as long as we have buffers available
366a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    // Do not make pause/resume decisions here.
367309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
36814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    status_t err = packetSource->dequeueAccessUnit(accessUnit);
36914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
37014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (err == INFO_DISCONTINUITY) {
371309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        // adaptive streaming, discontinuities in the playlist
37214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        int32_t type;
37314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        CHECK((*accessUnit)->meta()->findInt32("discontinuity", &type));
37414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
37514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        sp<AMessage> extra;
37614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (!(*accessUnit)->meta()->findMessage("extra", &extra)) {
37714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            extra.clear();
37814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
37914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
38014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        ALOGI("[%s] read discontinuity of type %d, extra = %s",
38114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber              streamStr,
38214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber              type,
38314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber              extra == NULL ? "NULL" : extra->debugString().c_str());
38414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    } else if (err == OK) {
385309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
386dcb89b3b505522efde173c105a851c412f947178Chong Zhang        if (stream == STREAMTYPE_AUDIO || stream == STREAMTYPE_VIDEO) {
38725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            int64_t timeUs, originalTimeUs;
388309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            int32_t discontinuitySeq = 0;
3890852843d304006e3ab333081fddda13b07193de8Robert Shih            StreamItem& strm = mStreams[streamIdx];
390dcb89b3b505522efde173c105a851c412f947178Chong Zhang            CHECK((*accessUnit)->meta()->findInt64("timeUs",  &timeUs));
39125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            originalTimeUs = timeUs;
392309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            (*accessUnit)->meta()->findInt32("discontinuitySeq", &discontinuitySeq);
3937c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            if (discontinuitySeq > (int32_t) strm.mCurDiscontinuitySeq) {
3947c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                int64_t offsetTimeUs;
3957c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                if (mDiscontinuityOffsetTimesUs.indexOfKey(strm.mCurDiscontinuitySeq) >= 0) {
3967c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    offsetTimeUs = mDiscontinuityOffsetTimesUs.valueFor(strm.mCurDiscontinuitySeq);
3977c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                } else {
3987c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    offsetTimeUs = 0;
3997c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                }
4007c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
40181636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang                if (mDiscontinuityAbsStartTimesUs.indexOfKey(strm.mCurDiscontinuitySeq) >= 0
40281636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang                        && strm.mLastDequeuedTimeUs >= 0) {
4037c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    int64_t firstTimeUs;
4047c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    firstTimeUs = mDiscontinuityAbsStartTimesUs.valueFor(strm.mCurDiscontinuitySeq);
4057c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    offsetTimeUs += strm.mLastDequeuedTimeUs - firstTimeUs;
4067c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    offsetTimeUs += strm.mLastSampleDurationUs;
4077c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                } else {
4087c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    offsetTimeUs += strm.mLastSampleDurationUs;
4097c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                }
4107c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
4117c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                mDiscontinuityOffsetTimesUs.add(discontinuitySeq, offsetTimeUs);
4127c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                strm.mCurDiscontinuitySeq = discontinuitySeq;
4137c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            }
414309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
415309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            int32_t discard = 0;
416309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            int64_t firstTimeUs;
417309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            if (mDiscontinuityAbsStartTimesUs.indexOfKey(strm.mCurDiscontinuitySeq) >= 0) {
418309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                int64_t durUs; // approximate sample duration
419309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                if (timeUs > strm.mLastDequeuedTimeUs) {
420309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    durUs = timeUs - strm.mLastDequeuedTimeUs;
421309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                } else {
422309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    durUs = strm.mLastDequeuedTimeUs - timeUs;
423309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                }
424309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                strm.mLastSampleDurationUs = durUs;
425309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                firstTimeUs = mDiscontinuityAbsStartTimesUs.valueFor(strm.mCurDiscontinuitySeq);
426309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            } else if ((*accessUnit)->meta()->findInt32("discard", &discard) && discard) {
427309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                firstTimeUs = timeUs;
428309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            } else {
429309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                mDiscontinuityAbsStartTimesUs.add(strm.mCurDiscontinuitySeq, timeUs);
430309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                firstTimeUs = timeUs;
431309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            }
432309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
433309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            strm.mLastDequeuedTimeUs = timeUs;
4340852843d304006e3ab333081fddda13b07193de8Robert Shih            timeUs = calculateMediaTimeUs(firstTimeUs, timeUs, discontinuitySeq);
435dcb89b3b505522efde173c105a851c412f947178Chong Zhang
43625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            ALOGV("[%s] dequeueAccessUnit: time %lld us, original %lld us",
43725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                    streamStr, (long long)timeUs, (long long)originalTimeUs);
438309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            (*accessUnit)->meta()->setInt64("timeUs",  timeUs);
439dcb89b3b505522efde173c105a851c412f947178Chong Zhang            mLastDequeuedTimeUs = timeUs;
440dcb89b3b505522efde173c105a851c412f947178Chong Zhang            mRealTimeBaseUs = ALooper::GetNowUs() - timeUs;
441dcb89b3b505522efde173c105a851c412f947178Chong Zhang        } else if (stream == STREAMTYPE_SUBTITLES) {
442b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih            int32_t subtitleGeneration;
443b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih            if ((*accessUnit)->meta()->findInt32("subtitleGeneration", &subtitleGeneration)
444b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih                    && subtitleGeneration != mSubtitleGeneration) {
445b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih               return -EAGAIN;
446b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih            };
447dcb89b3b505522efde173c105a851c412f947178Chong Zhang            (*accessUnit)->meta()->setInt32(
448dcb89b3b505522efde173c105a851c412f947178Chong Zhang                    "trackIndex", mPlaylist->getSelectedIndex());
449dcb89b3b505522efde173c105a851c412f947178Chong Zhang            (*accessUnit)->meta()->setInt64("baseUs", mRealTimeBaseUs);
4500852843d304006e3ab333081fddda13b07193de8Robert Shih        } else if (stream == STREAMTYPE_METADATA) {
4510852843d304006e3ab333081fddda13b07193de8Robert Shih            HLSTime mdTime((*accessUnit)->meta());
4520852843d304006e3ab333081fddda13b07193de8Robert Shih            if (mDiscontinuityAbsStartTimesUs.indexOfKey(mdTime.mSeq) < 0) {
4530852843d304006e3ab333081fddda13b07193de8Robert Shih                packetSource->requeueAccessUnit((*accessUnit));
4540852843d304006e3ab333081fddda13b07193de8Robert Shih                return -EAGAIN;
4550852843d304006e3ab333081fddda13b07193de8Robert Shih            } else {
4560852843d304006e3ab333081fddda13b07193de8Robert Shih                int64_t firstTimeUs = mDiscontinuityAbsStartTimesUs.valueFor(mdTime.mSeq);
4570852843d304006e3ab333081fddda13b07193de8Robert Shih                int64_t timeUs = calculateMediaTimeUs(firstTimeUs, mdTime.mTimeUs, mdTime.mSeq);
4580852843d304006e3ab333081fddda13b07193de8Robert Shih                (*accessUnit)->meta()->setInt64("timeUs",  timeUs);
4590852843d304006e3ab333081fddda13b07193de8Robert Shih                (*accessUnit)->meta()->setInt64("baseUs", mRealTimeBaseUs);
4600852843d304006e3ab333081fddda13b07193de8Robert Shih            }
461dcb89b3b505522efde173c105a851c412f947178Chong Zhang        }
46214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    } else {
46314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        ALOGI("[%s] encountered error %d", streamStr, err);
46414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
46514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
46614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return err;
46714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
46814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
469a83eebb78c3a7d57a769dac965b17a8aad7c7b8fRobert Shihstatus_t LiveSession::getStreamFormatMeta(StreamType stream, sp<MetaData> *meta) {
47014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (!(mStreamMask & stream)) {
47114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        return UNKNOWN_ERROR;
47214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
47314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
47414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AnotherPacketSource> packetSource = mPacketSources.valueFor(stream);
47514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
476a83eebb78c3a7d57a769dac965b17a8aad7c7b8fRobert Shih    *meta = packetSource->getFormat();
47714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
478a83eebb78c3a7d57a769dac965b17a8aad7c7b8fRobert Shih    if (*meta == NULL) {
4797350b057ca864f5dc9e53d48e34710a8e81133f8Robert Shih        return -EWOULDBLOCK;
48014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
48114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
4827c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    if (stream == STREAMTYPE_AUDIO) {
4837c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // set AAC input buffer size to 32K bytes (256kbps x 1sec)
484a83eebb78c3a7d57a769dac965b17a8aad7c7b8fRobert Shih        (*meta)->setInt32(kKeyMaxInputSize, 32 * 1024);
485a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang    } else if (stream == STREAMTYPE_VIDEO) {
486a83eebb78c3a7d57a769dac965b17a8aad7c7b8fRobert Shih        (*meta)->setInt32(kKeyMaxWidth, mMaxWidth);
487a83eebb78c3a7d57a769dac965b17a8aad7c7b8fRobert Shih        (*meta)->setInt32(kKeyMaxHeight, mMaxHeight);
4887c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    }
4897c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
490a83eebb78c3a7d57a769dac965b17a8aad7c7b8fRobert Shih    return OK;
491a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
492a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
4935abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhangsp<HTTPDownloader> LiveSession::getHTTPDownloader() {
4945abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    return new HTTPDownloader(mHTTPService, mExtraHeaders);
495a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang}
496a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
49748fa06d1e80a872c7495804979256e021e566ae0Wei Jiavoid LiveSession::setBufferingSettings(
49848fa06d1e80a872c7495804979256e021e566ae0Wei Jia        const BufferingSettings &buffering) {
49948fa06d1e80a872c7495804979256e021e566ae0Wei Jia    sp<AMessage> msg = new AMessage(kWhatSetBufferingSettings, this);
50048fa06d1e80a872c7495804979256e021e566ae0Wei Jia    writeToAMessage(msg, buffering);
50148fa06d1e80a872c7495804979256e021e566ae0Wei Jia    msg->post();
50248fa06d1e80a872c7495804979256e021e566ae0Wei Jia}
50348fa06d1e80a872c7495804979256e021e566ae0Wei Jia
50414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::connectAsync(
505ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        const char *url, const KeyedVector<String8, String8> *headers) {
5061d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatConnect, this);
507a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    msg->setString("url", url);
508ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber
509ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    if (headers != NULL) {
510ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        msg->setPointer(
511ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber                "headers",
512ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber                new KeyedVector<String8, String8>(*headers));
513ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    }
514ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber
515a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    msg->post();
516a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
517a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
51814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::disconnect() {
5191d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatDisconnect, this);
520ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
52114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> response;
52214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    status_t err = msg->postAndAwaitResponse(&response);
523ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
52414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return err;
525a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
526a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
527c5de09127e9e0d5df7aa587be317e1487d793245Wei Jiastatus_t LiveSession::seekTo(int64_t timeUs, MediaPlayerSeekMode mode) {
5281d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatSeek, this);
529a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    msg->setInt64("timeUs", timeUs);
530c5de09127e9e0d5df7aa587be317e1487d793245Wei Jia    msg->setInt32("mode", mode);
531a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
53214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> response;
53314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    status_t err = msg->postAndAwaitResponse(&response);
53414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
53514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return err;
536a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
537a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
5387c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangbool LiveSession::checkSwitchProgress(
5397c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        sp<AMessage> &stopParams, int64_t delayUs, bool *needResumeUntil) {
5407c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    AString newUri;
5417c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    CHECK(stopParams->findString("uri", &newUri));
5427c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
5437c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    *needResumeUntil = false;
5447c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    sp<AMessage> firstNewMeta[kMaxStreams];
5457c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    for (size_t i = 0; i < kMaxStreams; ++i) {
5467c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        StreamType stream = indexToType(i);
5477c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        if (!(mSwapMask & mNewStreamMask & stream)
5487c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            || (mStreams[i].mNewUri != newUri)) {
5497c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            continue;
5507c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        }
5517c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        if (stream == STREAMTYPE_SUBTITLES) {
5527c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            continue;
5537c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        }
5547c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        sp<AnotherPacketSource> &source = mPacketSources.editValueAt(i);
5557c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
5567c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // First, get latest dequeued meta, which is where the decoder is at.
5577c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // (when upswitching, we take the meta after a certain delay, so that
5587c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // the decoder is left with some cushion)
5597c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        sp<AMessage> lastDequeueMeta, lastEnqueueMeta;
5607c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        if (delayUs > 0) {
5617c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            lastDequeueMeta = source->getMetaAfterLastDequeued(delayUs);
562d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            if (lastDequeueMeta == NULL) {
563d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                // this means we don't have enough cushion, try again later
564d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                ALOGV("[%s] up switching failed due to insufficient buffer",
56525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                        getNameForStream(stream));
566d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                return false;
567d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            }
5687c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        } else {
569d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            // It's okay for lastDequeueMeta to be NULL here, it means the
570d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            // decoder hasn't even started dequeueing
5717c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            lastDequeueMeta = source->getLatestDequeuedMeta();
5727c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        }
5737c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // Then, trim off packets at beginning of mPacketSources2 that's before
5747c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // the latest dequeued time. These samples are definitely too late.
575d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        firstNewMeta[i] = mPacketSources2.editValueAt(i)
576d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                            ->trimBuffersBeforeMeta(lastDequeueMeta);
577d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang
5787c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // Now firstNewMeta[i] is the first sample after the trim.
5797c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // If it's NULL, we failed because dequeue already past all samples
5807c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // in mPacketSource2, we have to try again.
5817c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        if (firstNewMeta[i] == NULL) {
582d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            HLSTime dequeueTime(lastDequeueMeta);
5837c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            ALOGV("[%s] dequeue time (%d, %lld) past start time",
58425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                    getNameForStream(stream),
585d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                    dequeueTime.mSeq, (long long) dequeueTime.mTimeUs);
5867c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            return false;
5877c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        }
5887c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
5897c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // Otherwise, we check if mPacketSources2 overlaps with what old fetcher
5907c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // already fetched, and see if we need to resumeUntil
5917c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        lastEnqueueMeta = source->getLatestEnqueuedMeta();
5927c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // lastEnqueueMeta == NULL means old fetcher stopped at a discontinuity
5937c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // boundary, no need to resume as the content will look different anyways
5947c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        if (lastEnqueueMeta != NULL) {
595d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            HLSTime lastTime(lastEnqueueMeta), startTime(firstNewMeta[i]);
5967c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
5977c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            // no need to resume old fetcher if new fetcher started in different
5987c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            // discontinuity sequence, as the content will look different.
599d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            *needResumeUntil |= (startTime.mSeq == lastTime.mSeq
600d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                    && startTime.mTimeUs - lastTime.mTimeUs > kResumeThresholdUs);
6017c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
602d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            // update the stopTime for resumeUntil
603d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            stopParams->setInt32("discontinuitySeq", startTime.mSeq);
604d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            stopParams->setInt64(getKeyForStream(stream), startTime.mTimeUs);
6057c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        }
6067c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    }
6077c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
6087c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    // if we're here, it means dequeue progress hasn't passed some samples in
6097c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    // mPacketSource2, we can trim off the excess in mPacketSource.
6107c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    // (old fetcher might still need to resumeUntil the start time of new fetcher)
6117c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    for (size_t i = 0; i < kMaxStreams; ++i) {
6127c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        StreamType stream = indexToType(i);
6137c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        if (!(mSwapMask & mNewStreamMask & stream)
614d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            || (newUri != mStreams[i].mNewUri)
615d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            || stream == STREAMTYPE_SUBTITLES) {
6167c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            continue;
6177c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        }
618d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        mPacketSources.valueFor(stream)->trimBuffersAfterMeta(firstNewMeta[i]);
6197c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    }
6207c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
6217c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    // no resumeUntil if already underflow
6227c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    *needResumeUntil &= !mBuffering;
6237c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
6247c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    return true;
6257c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang}
6267c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
627a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onMessageReceived(const sp<AMessage> &msg) {
628a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    switch (msg->what()) {
62948fa06d1e80a872c7495804979256e021e566ae0Wei Jia        case kWhatSetBufferingSettings:
63048fa06d1e80a872c7495804979256e021e566ae0Wei Jia        {
63148fa06d1e80a872c7495804979256e021e566ae0Wei Jia            readFromAMessage(msg, &mBufferingSettings);
63248fa06d1e80a872c7495804979256e021e566ae0Wei Jia            break;
63348fa06d1e80a872c7495804979256e021e566ae0Wei Jia        }
63448fa06d1e80a872c7495804979256e021e566ae0Wei Jia
635a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        case kWhatConnect:
63614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
637a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            onConnect(msg);
638a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
63914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
640a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
641a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        case kWhatDisconnect:
64214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
64314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            CHECK(msg->senderAwaitsResponse(&mDisconnectReplyID));
64414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
64514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            if (mReconfigurationInProgress) {
64614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                break;
64714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            }
64814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
64914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            finishDisconnect();
650a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
65114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
652a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
65314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case kWhatSeek:
65414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
655a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar            if (mReconfigurationInProgress) {
656800599cdd50737de1cde483a34b39923750b0658Robert Shih                msg->post(50000);
657a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar                break;
658800599cdd50737de1cde483a34b39923750b0658Robert Shih            }
659a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar
660a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar            CHECK(msg->senderAwaitsResponse(&mSeekReplyID));
661a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar            mSeekReply = new AMessage;
662a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar
663a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar            onSeek(msg);
66414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            break;
66514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
66614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
66714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case kWhatFetcherNotify:
66814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
66914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            int32_t what;
67014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            CHECK(msg->findInt32("what", &what));
67114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
67214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            switch (what) {
67314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                case PlaylistFetcher::kWhatStarted:
67414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    break;
67514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                case PlaylistFetcher::kWhatPaused:
67614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                case PlaylistFetcher::kWhatStopped:
67714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                {
678a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                    AString uri;
679a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                    CHECK(msg->findString("uri", &uri));
680a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                    ssize_t index = mFetcherInfos.indexOfKey(uri);
681a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                    if (index < 0) {
682a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                        // ignore msgs from fetchers that's already gone
683a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                        break;
684a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                    }
685a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
68625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                    ALOGV("fetcher-%d %s",
68725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                            mFetcherInfos[index].mFetcher->getFetcherID(),
68825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                            what == PlaylistFetcher::kWhatPaused ?
68925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                                    "paused" : "stopped");
69025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang
69114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    if (what == PlaylistFetcher::kWhatStopped) {
692964adb17885185808398507d2de88665fe193ee2Chong Zhang                        mFetcherLooper->unregisterHandler(
693964adb17885185808398507d2de88665fe193ee2Chong Zhang                                mFetcherInfos[index].mFetcher->id());
694964adb17885185808398507d2de88665fe193ee2Chong Zhang                        mFetcherInfos.removeItemsAt(index);
695a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                    } else if (what == PlaylistFetcher::kWhatPaused) {
696a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                        int32_t seekMode;
697a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                        CHECK(msg->findInt32("seekMode", &seekMode));
698a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                        for (size_t i = 0; i < kMaxStreams; ++i) {
699a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                            if (mStreams[i].mUri == uri) {
700a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                                mStreams[i].mSeekMode = (SeekMode) seekMode;
701a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                            }
702309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        }
70314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    }
70414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
70514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    if (mContinuation != NULL) {
706b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross                        CHECK_GT(mContinuationCounter, 0u);
70714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        if (--mContinuationCounter == 0) {
70814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                            mContinuation->post();
70914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        }
71025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                        ALOGV("%zu fetcher(s) left", mContinuationCounter);
71114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    }
71214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    break;
71314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                }
71414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
71514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                case PlaylistFetcher::kWhatDurationUpdate:
71614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                {
71714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    AString uri;
71814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    CHECK(msg->findString("uri", &uri));
71914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
72014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    int64_t durationUs;
72114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    CHECK(msg->findInt64("durationUs", &durationUs));
72214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
723964adb17885185808398507d2de88665fe193ee2Chong Zhang                    ssize_t index = mFetcherInfos.indexOfKey(uri);
724964adb17885185808398507d2de88665fe193ee2Chong Zhang                    if (index >= 0) {
725964adb17885185808398507d2de88665fe193ee2Chong Zhang                        FetcherInfo *info = &mFetcherInfos.editValueFor(uri);
726964adb17885185808398507d2de88665fe193ee2Chong Zhang                        info->mDurationUs = durationUs;
727964adb17885185808398507d2de88665fe193ee2Chong Zhang                    }
72814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    break;
72914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                }
73014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
7317c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                case PlaylistFetcher::kWhatTargetDurationUpdate:
7327c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                {
7337c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    int64_t targetDurationUs;
7347c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    CHECK(msg->findInt64("targetDurationUs", &targetDurationUs));
735d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                    mUpSwitchMark = min(kUpSwitchMarkUs, targetDurationUs * 7 / 4);
736765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang                    mDownSwitchMark = min(kDownSwitchMarkUs, targetDurationUs * 9 / 4);
737765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang                    mUpSwitchMargin = min(kUpSwitchMarginUs, targetDurationUs);
7387c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    break;
7397c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                }
7407c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
74114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                case PlaylistFetcher::kWhatError:
74214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                {
74314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    status_t err;
74414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    CHECK(msg->findInt32("err", &err));
74514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
74614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    ALOGE("XXX Received error %d from PlaylistFetcher.", err);
74714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
74815f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                    // handle EOS on subtitle tracks independently
74915f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                    AString uri;
75015f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                    if (err == ERROR_END_OF_STREAM && msg->findString("uri", &uri)) {
75115f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                        ssize_t i = mFetcherInfos.indexOfKey(uri);
75215f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                        if (i >= 0) {
75315f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                            const sp<PlaylistFetcher> &fetcher = mFetcherInfos.valueAt(i).mFetcher;
75415f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                            if (fetcher != NULL) {
75515f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                                uint32_t type = fetcher->getStreamTypeMask();
75615f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                                if (type == STREAMTYPE_SUBTITLES) {
75715f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                                    mPacketSources.valueFor(
75815f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                                            STREAMTYPE_SUBTITLES)->signalEOS(err);;
75915f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                                    break;
76015f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                                }
76115f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                            }
76215f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                        }
76315f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                    }
76415f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih
7655ef659e010e90175eb5282d9642a02f6105189bfChong Zhang                    // remember the failure index (as mCurBandwidthIndex will be restored
7665ef659e010e90175eb5282d9642a02f6105189bfChong Zhang                    // after cancelBandwidthSwitch()), and record last fail time
7675ef659e010e90175eb5282d9642a02f6105189bfChong Zhang                    size_t failureIndex = mCurBandwidthIndex;
7685ef659e010e90175eb5282d9642a02f6105189bfChong Zhang                    mBandwidthItems.editItemAt(
7695ef659e010e90175eb5282d9642a02f6105189bfChong Zhang                            failureIndex).mLastFailureUs = ALooper::GetNowUs();
7705ef659e010e90175eb5282d9642a02f6105189bfChong Zhang
7715ef659e010e90175eb5282d9642a02f6105189bfChong Zhang                    if (mSwitchInProgress) {
7725ef659e010e90175eb5282d9642a02f6105189bfChong Zhang                        // if error happened when we switch to a variant, try fallback
7735ef659e010e90175eb5282d9642a02f6105189bfChong Zhang                        // to other variant to save the session
7745ef659e010e90175eb5282d9642a02f6105189bfChong Zhang                        if (tryBandwidthFallback()) {
7755ef659e010e90175eb5282d9642a02f6105189bfChong Zhang                            break;
7765ef659e010e90175eb5282d9642a02f6105189bfChong Zhang                        }
7775ef659e010e90175eb5282d9642a02f6105189bfChong Zhang                    }
7785ef659e010e90175eb5282d9642a02f6105189bfChong Zhang
77914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    if (mInPreparationPhase) {
78014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        postPrepared(err);
78114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    }
78214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
7831543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    cancelBandwidthSwitch();
7841543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
78514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    mPacketSources.valueFor(STREAMTYPE_AUDIO)->signalEOS(err);
78614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
78714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    mPacketSources.valueFor(STREAMTYPE_VIDEO)->signalEOS(err);
78814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
78914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    mPacketSources.valueFor(
79014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                            STREAMTYPE_SUBTITLES)->signalEOS(err);
79114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
7927c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    postError(err);
7937c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    break;
7947c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                }
7957c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
7967c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                case PlaylistFetcher::kWhatStopReached:
7977c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                {
7987c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    ALOGV("kWhatStopReached");
7997c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
800d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                    AString oldUri;
801d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                    CHECK(msg->findString("uri", &oldUri));
8027c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
803d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                    ssize_t index = mFetcherInfos.indexOfKey(oldUri);
8047c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    if (index < 0) {
8057c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                        break;
8067c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    }
8077c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
808d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                    tryToFinishBandwidthSwitch(oldUri);
80914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    break;
81014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                }
81114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
8121543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                case PlaylistFetcher::kWhatStartedAt:
8131543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                {
8141543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    int32_t switchGeneration;
8151543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    CHECK(msg->findInt32("switchGeneration", &switchGeneration));
8161543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
81725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                    ALOGV("kWhatStartedAt: switchGen=%d, mSwitchGen=%d",
81825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                            switchGeneration, mSwitchGeneration);
81925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang
8201543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    if (switchGeneration != mSwitchGeneration) {
8211543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        break;
8221543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    }
8231543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
824a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                    AString uri;
825a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                    CHECK(msg->findString("uri", &uri));
8267c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
8277c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    // mark new fetcher mToBeResumed
828a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                    ssize_t index = mFetcherInfos.indexOfKey(uri);
829a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                    if (index >= 0) {
830a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                        mFetcherInfos.editValueAt(index).mToBeResumed = true;
831a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                    }
832a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
8337c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    // temporarily disable packet sources to be swapped to prevent
8347c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    // NuPlayerDecoder from dequeuing while we check progress
8357c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    for (size_t i = 0; i < mPacketSources.size(); ++i) {
8367c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                        if ((mSwapMask & mPacketSources.keyAt(i))
8377c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                                && uri == mStreams[i].mNewUri) {
8387c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                            mPacketSources.editValueAt(i)->enable(false);
8391543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        }
8401543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    }
8417c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    bool switchUp = (mCurBandwidthIndex > mOrigBandwidthIndex);
8427c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    // If switching up, require a cushion bigger than kUnderflowMark
8437c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    // to avoid buffering immediately after the switch.
8447c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    // (If we don't have that cushion we'd rather cancel and try again.)
84548fa06d1e80a872c7495804979256e021e566ae0Wei Jia                    int64_t delayUs =
84648fa06d1e80a872c7495804979256e021e566ae0Wei Jia                        switchUp ?
8479bb3803a80a680ea7a3bc11e07b8a89ccddee003Wei Jia                            (kUnderflowMarkMs * 1000ll + 1000000ll)
84848fa06d1e80a872c7495804979256e021e566ae0Wei Jia                            : 0;
8497c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    bool needResumeUntil = false;
8507c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    sp<AMessage> stopParams = msg;
8517c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    if (checkSwitchProgress(stopParams, delayUs, &needResumeUntil)) {
8527c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                        // playback time hasn't passed startAt time
8537c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                        if (!needResumeUntil) {
85425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                            ALOGV("finish switch");
8557c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                            for (size_t i = 0; i < kMaxStreams; ++i) {
8567c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                                if ((mSwapMask & indexToType(i))
8577c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                                        && uri == mStreams[i].mNewUri) {
8587c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                                    // have to make a copy of mStreams[i].mUri because
8597c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                                    // tryToFinishBandwidthSwitch is modifying mStreams[]
8607c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                                    AString oldURI = mStreams[i].mUri;
8617c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                                    tryToFinishBandwidthSwitch(oldURI);
8627c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                                    break;
8637c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                                }
8647c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                            }
8657c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                        } else {
8667c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                            // startAt time is after last enqueue time
8677c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                            // Resume fetcher for the original variant; the resumed fetcher should
8687c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                            // continue until the timestamps found in msg, which is stored by the
8697c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                            // new fetcher to indicate where the new variant has started buffering.
87025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                            ALOGV("finish switch with resumeUntilAsync");
8717c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                            for (size_t i = 0; i < mFetcherInfos.size(); i++) {
8727c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                                const FetcherInfo &info = mFetcherInfos.valueAt(i);
8737c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                                if (info.mToBeRemoved) {
8747c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                                    info.mFetcher->resumeUntilAsync(stopParams);
8757c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                                }
8767c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                            }
8777c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                        }
8787c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    } else {
8797c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                        // playback time passed startAt time
8807c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                        if (switchUp) {
8817c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                            // if switching up, cancel and retry if condition satisfies again
88225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                            ALOGV("cancel up switch because we're too late");
8837c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                            cancelBandwidthSwitch(true /* resume */);
8847c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                        } else {
88525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                            ALOGV("retry down switch at next sample");
8867c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                            resumeFetcher(uri, mSwapMask, -1, true /* newUri */);
8877c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                        }
8887c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    }
8897c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    // re-enable all packet sources
8907c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    for (size_t i = 0; i < mPacketSources.size(); ++i) {
8917c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                        mPacketSources.editValueAt(i)->enable(true);
8927c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    }
8937c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
8941543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    break;
8951543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                }
8961543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
8975abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang                case PlaylistFetcher::kWhatPlaylistFetched:
8985abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang                {
8995abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang                    onMasterPlaylistFetched(msg);
9005abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang                    break;
9015abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang                }
9025abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang
9030852843d304006e3ab333081fddda13b07193de8Robert Shih                case PlaylistFetcher::kWhatMetadataDetected:
9040852843d304006e3ab333081fddda13b07193de8Robert Shih                {
9050852843d304006e3ab333081fddda13b07193de8Robert Shih                    if (!mHasMetadata) {
9060852843d304006e3ab333081fddda13b07193de8Robert Shih                        mHasMetadata = true;
9070852843d304006e3ab333081fddda13b07193de8Robert Shih                        sp<AMessage> notify = mNotify->dup();
9080852843d304006e3ab333081fddda13b07193de8Robert Shih                        notify->setInt32("what", kWhatMetadataDetected);
9090852843d304006e3ab333081fddda13b07193de8Robert Shih                        notify->post();
9100852843d304006e3ab333081fddda13b07193de8Robert Shih                    }
9110852843d304006e3ab333081fddda13b07193de8Robert Shih                    break;
9120852843d304006e3ab333081fddda13b07193de8Robert Shih                }
9130852843d304006e3ab333081fddda13b07193de8Robert Shih
91414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                default:
91514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    TRESPASS();
91614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            }
91714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
91814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            break;
91914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
92014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
921dcb89b3b505522efde173c105a851c412f947178Chong Zhang        case kWhatChangeConfiguration:
922dcb89b3b505522efde173c105a851c412f947178Chong Zhang        {
923dcb89b3b505522efde173c105a851c412f947178Chong Zhang            onChangeConfiguration(msg);
924dcb89b3b505522efde173c105a851c412f947178Chong Zhang            break;
925dcb89b3b505522efde173c105a851c412f947178Chong Zhang        }
926dcb89b3b505522efde173c105a851c412f947178Chong Zhang
92714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case kWhatChangeConfiguration2:
92814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
92914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            onChangeConfiguration2(msg);
93014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            break;
93114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
93214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
93314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case kWhatChangeConfiguration3:
93414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
93514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            onChangeConfiguration3(msg);
93614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            break;
93714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
93814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
939964adb17885185808398507d2de88665fe193ee2Chong Zhang        case kWhatPollBuffering:
9400ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        {
941964adb17885185808398507d2de88665fe193ee2Chong Zhang            int32_t generation;
942964adb17885185808398507d2de88665fe193ee2Chong Zhang            CHECK(msg->findInt32("generation", &generation));
943964adb17885185808398507d2de88665fe193ee2Chong Zhang            if (generation == mPollBufferingGeneration) {
944964adb17885185808398507d2de88665fe193ee2Chong Zhang                onPollBuffering();
945964adb17885185808398507d2de88665fe193ee2Chong Zhang            }
9460ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih            break;
9470ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        }
9480ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
949a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        default:
950a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            TRESPASS();
951a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
952a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
953a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
954a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
955a44153c1a57202fb538659eb50706e60454d6273Andreas Huber// static
9565ef659e010e90175eb5282d9642a02f6105189bfChong Zhangbool LiveSession::isBandwidthValid(const BandwidthItem &item) {
9575ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    static const int64_t kBlacklistWindowUs = 300 * 1000000ll;
9585ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    return item.mLastFailureUs < 0
9595ef659e010e90175eb5282d9642a02f6105189bfChong Zhang            || ALooper::GetNowUs() - item.mLastFailureUs > kBlacklistWindowUs;
9605ef659e010e90175eb5282d9642a02f6105189bfChong Zhang}
9615ef659e010e90175eb5282d9642a02f6105189bfChong Zhang
9625ef659e010e90175eb5282d9642a02f6105189bfChong Zhang// static
963a44153c1a57202fb538659eb50706e60454d6273Andreas Huberint LiveSession::SortByBandwidth(const BandwidthItem *a, const BandwidthItem *b) {
964a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (a->mBandwidth < b->mBandwidth) {
965a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return -1;
966a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else if (a->mBandwidth == b->mBandwidth) {
967a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return 0;
968a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
969a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
970a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return 1;
971a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
972a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
9738ca002eedc747dd854b61cbe364b52c06869273fRobert Shih// static
9748ca002eedc747dd854b61cbe364b52c06869273fRobert ShihLiveSession::StreamType LiveSession::indexToType(int idx) {
9750852843d304006e3ab333081fddda13b07193de8Robert Shih    CHECK(idx >= 0 && idx < kNumSources);
9768ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    return (StreamType)(1 << idx);
9778ca002eedc747dd854b61cbe364b52c06869273fRobert Shih}
9788ca002eedc747dd854b61cbe364b52c06869273fRobert Shih
979f69c996864844e8f669308af8412cede043062a2Robert Shih// static
980f69c996864844e8f669308af8412cede043062a2Robert Shihssize_t LiveSession::typeToIndex(int32_t type) {
981f69c996864844e8f669308af8412cede043062a2Robert Shih    switch (type) {
982f69c996864844e8f669308af8412cede043062a2Robert Shih        case STREAMTYPE_AUDIO:
983f69c996864844e8f669308af8412cede043062a2Robert Shih            return 0;
984f69c996864844e8f669308af8412cede043062a2Robert Shih        case STREAMTYPE_VIDEO:
985f69c996864844e8f669308af8412cede043062a2Robert Shih            return 1;
986f69c996864844e8f669308af8412cede043062a2Robert Shih        case STREAMTYPE_SUBTITLES:
987f69c996864844e8f669308af8412cede043062a2Robert Shih            return 2;
9880852843d304006e3ab333081fddda13b07193de8Robert Shih        case STREAMTYPE_METADATA:
9890852843d304006e3ab333081fddda13b07193de8Robert Shih            return 3;
990f69c996864844e8f669308af8412cede043062a2Robert Shih        default:
991f69c996864844e8f669308af8412cede043062a2Robert Shih            return -1;
992f69c996864844e8f669308af8412cede043062a2Robert Shih    };
993f69c996864844e8f669308af8412cede043062a2Robert Shih    return -1;
994f69c996864844e8f669308af8412cede043062a2Robert Shih}
995f69c996864844e8f669308af8412cede043062a2Robert Shih
996a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onConnect(const sp<AMessage> &msg) {
9975abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    CHECK(msg->findString("url", &mMasterURL));
9985abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang
9995abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    // TODO currently we don't know if we are coming here from incognito mode
10005abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    ALOGI("onConnect %s", uriDebugString(mMasterURL).c_str());
1001a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1002ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    KeyedVector<String8, String8> *headers = NULL;
1003ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    if (!msg->findPointer("headers", (void **)&headers)) {
1004ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        mExtraHeaders.clear();
1005ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    } else {
1006ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        mExtraHeaders = *headers;
1007ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber
1008ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        delete headers;
1009ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        headers = NULL;
1010ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    }
1011ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber
1012964adb17885185808398507d2de88665fe193ee2Chong Zhang    // create looper for fetchers
1013964adb17885185808398507d2de88665fe193ee2Chong Zhang    if (mFetcherLooper == NULL) {
1014964adb17885185808398507d2de88665fe193ee2Chong Zhang        mFetcherLooper = new ALooper();
1015964adb17885185808398507d2de88665fe193ee2Chong Zhang
1016964adb17885185808398507d2de88665fe193ee2Chong Zhang        mFetcherLooper->setName("Fetcher");
10174e69ad15e481883b53ddd37e371ab5f3560dca7aWei Jia        mFetcherLooper->start(false, /* runOnCallingThread */
10184e69ad15e481883b53ddd37e371ab5f3560dca7aWei Jia                              true  /* canCallJava */);
1019964adb17885185808398507d2de88665fe193ee2Chong Zhang    }
1020964adb17885185808398507d2de88665fe193ee2Chong Zhang
10215abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    // create fetcher to fetch the master playlist
10225abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    addFetcher(mMasterURL.c_str())->fetchPlaylistAsync();
10235abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang}
10245abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang
10255abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhangvoid LiveSession::onMasterPlaylistFetched(const sp<AMessage> &msg) {
10265abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    AString uri;
10275abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    CHECK(msg->findString("uri", &uri));
10285abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    ssize_t index = mFetcherInfos.indexOfKey(uri);
10295abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    if (index < 0) {
10305abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang        ALOGW("fetcher for master playlist is gone.");
10315abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang        return;
10325abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    }
10335abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang
10345abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    // no longer useful, remove
10355abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    mFetcherLooper->unregisterHandler(mFetcherInfos[index].mFetcher->id());
10365abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    mFetcherInfos.removeItemsAt(index);
10375abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang
10385abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    CHECK(msg->findObject("playlist", (sp<RefBase> *)&mPlaylist));
10395abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    if (mPlaylist == NULL) {
10405abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang        ALOGE("unable to fetch master playlist %s.",
10415abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang                uriDebugString(mMasterURL).c_str());
10425abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang
10435abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang        postPrepared(ERROR_IO);
10445abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang        return;
10455abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    }
104614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // We trust the content provider to make a reasonable choice of preferred
104714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // initial bandwidth by listing it first in the variant playlist.
104814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // At startup we really don't have a good estimate on the available
104914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // network bandwidth since we haven't tranferred any data yet. Once
105014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // we have we can make a better informed choice.
105114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    size_t initialBandwidth = 0;
105214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    size_t initialBandwidthIndex = 0;
105314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
1054a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang    int32_t maxWidth = 0;
1055a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang    int32_t maxHeight = 0;
1056a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang
105714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (mPlaylist->isVariantPlaylist()) {
1058d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        Vector<BandwidthItem> itemsWithVideo;
105914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        for (size_t i = 0; i < mPlaylist->size(); ++i) {
1060a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            BandwidthItem item;
1061a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
106214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            item.mPlaylistIndex = i;
10635ef659e010e90175eb5282d9642a02f6105189bfChong Zhang            item.mLastFailureUs = -1ll;
106414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
1065a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            sp<AMessage> meta;
106614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            AString uri;
106714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            mPlaylist->itemAt(i, &uri, &meta);
1068a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1069a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            CHECK(meta->findInt32("bandwidth", (int32_t *)&item.mBandwidth));
1070a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1071a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang            int32_t width, height;
1072a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang            if (meta->findInt32("width", &width)) {
1073a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang                maxWidth = max(maxWidth, width);
1074a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang            }
1075a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang            if (meta->findInt32("height", &height)) {
1076a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang                maxHeight = max(maxHeight, height);
1077a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang            }
1078a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang
1079a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            mBandwidthItems.push(item);
1080d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            if (mPlaylist->hasType(i, "video")) {
1081d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                itemsWithVideo.push(item);
1082d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            }
1083d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        }
1084d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        // remove the audio-only variants if we have at least one with video
1085d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        if (!itemsWithVideo.empty()
1086d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                && itemsWithVideo.size() < mBandwidthItems.size()) {
1087d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            mBandwidthItems.clear();
1088d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            for (size_t i = 0; i < itemsWithVideo.size(); ++i) {
1089d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                mBandwidthItems.push(itemsWithVideo[i]);
1090d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            }
1091a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
1092a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1093a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        CHECK_GT(mBandwidthItems.size(), 0u);
1094d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        initialBandwidth = mBandwidthItems[0].mBandwidth;
1095a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1096a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        mBandwidthItems.sort(SortByBandwidth);
109714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
109814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        for (size_t i = 0; i < mBandwidthItems.size(); ++i) {
109914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            if (mBandwidthItems.itemAt(i).mBandwidth == initialBandwidth) {
110014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                initialBandwidthIndex = i;
110114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                break;
110214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            }
110314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
110414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    } else {
110514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        // dummy item.
110614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        BandwidthItem item;
110714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        item.mPlaylistIndex = 0;
110814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        item.mBandwidth = 0;
110914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        mBandwidthItems.push(item);
1110a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1111a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1112a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang    mMaxWidth = maxWidth > 0 ? maxWidth : mMaxWidth;
1113a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang    mMaxHeight = maxHeight > 0 ? maxHeight : mMaxHeight;
1114a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang
1115309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    mPlaylist->pickRandomMediaItems();
1116dcb89b3b505522efde173c105a851c412f947178Chong Zhang    changeConfiguration(
1117309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            0ll /* timeUs */, initialBandwidthIndex, false /* pickTrack */);
1118a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
1119a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
112014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::finishDisconnect() {
1121a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    ALOGV("finishDisconnect");
1122a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
112314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // No reconfiguration is currently pending, make sure none will trigger
112414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // during disconnection either.
11251543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    cancelBandwidthSwitch();
11261543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
1127964adb17885185808398507d2de88665fe193ee2Chong Zhang    // cancel buffer polling
1128964adb17885185808398507d2de88665fe193ee2Chong Zhang    cancelPollBuffering();
11290ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
11305abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    // TRICKY: don't wait for all fetcher to be stopped when disconnecting
11315abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    //
11325abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    // Some fetchers might be stuck in connect/getSize at this point. These
11335abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    // operations will eventually timeout (as we have a timeout set in
11345abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    // MediaHTTPConnection), but we don't want to block the main UI thread
11355abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    // until then. Here we just need to make sure we clear all references
11365abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    // to the fetchers, so that when they finally exit from the blocking
11375abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    // operation, they can be destructed.
11385abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    //
11395abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    // There is one very tricky point though. For this scheme to work, the
11405abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    // fecther must hold a reference to LiveSession, so that LiveSession is
11415abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    // destroyed after fetcher. Otherwise LiveSession would get stuck in its
11425abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    // own destructor when it waits for mFetcherLooper to stop, which still
11435abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    // blocks main UI thread.
114414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
114514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        mFetcherInfos.valueAt(i).mFetcher->stopAsync();
11465abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang        mFetcherLooper->unregisterHandler(
11475abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang                mFetcherInfos.valueAt(i).mFetcher->id());
114814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
11495abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    mFetcherInfos.clear();
115014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
115114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mPacketSources.valueFor(STREAMTYPE_AUDIO)->signalEOS(ERROR_END_OF_STREAM);
115214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mPacketSources.valueFor(STREAMTYPE_VIDEO)->signalEOS(ERROR_END_OF_STREAM);
115314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
115414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mPacketSources.valueFor(
115514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            STREAMTYPE_SUBTITLES)->signalEOS(ERROR_END_OF_STREAM);
115614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
115714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> response = new AMessage;
115814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    response->setInt32("err", OK);
115914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
116014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    response->postReply(mDisconnectReplyID);
1161c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang    mDisconnectReplyID.clear();
116214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
116314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
116414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubersp<PlaylistFetcher> LiveSession::addFetcher(const char *uri) {
116514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    ssize_t index = mFetcherInfos.indexOfKey(uri);
116614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
116714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (index >= 0) {
116814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        return NULL;
116914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
117014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
11711d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> notify = new AMessage(kWhatFetcherNotify, this);
117214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->setString("uri", uri);
11731543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    notify->setInt32("switchGeneration", mSwitchGeneration);
117414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
117514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    FetcherInfo info;
117625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    info.mFetcher = new PlaylistFetcher(
117725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            notify, this, uri, mCurBandwidthIndex, mSubtitleGeneration);
117814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    info.mDurationUs = -1ll;
11791543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    info.mToBeRemoved = false;
1180a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    info.mToBeResumed = false;
1181964adb17885185808398507d2de88665fe193ee2Chong Zhang    mFetcherLooper->registerHandler(info.mFetcher);
118214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
118314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mFetcherInfos.add(uri, info);
118414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
118514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return info.mFetcher;
1186a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
1187a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1188b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe#if 0
1189a44153c1a57202fb538659eb50706e60454d6273Andreas Huberstatic double uniformRand() {
1190a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return (double)rand() / RAND_MAX;
1191a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
1192b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe#endif
1193a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
11940852843d304006e3ab333081fddda13b07193de8Robert Shihbool LiveSession::UriIsSameAsIndex(const AString &uri, int32_t i, bool newUri) {
119594e2db71cf1ce90f8a74632895e2766b24a80d7fMichal Piechowski    ALOGV("[timed_id3] i %d UriIsSameAsIndex newUri %s, %s", i,
11960852843d304006e3ab333081fddda13b07193de8Robert Shih            newUri ? "true" : "false",
11970852843d304006e3ab333081fddda13b07193de8Robert Shih            newUri ? mStreams[i].mNewUri.c_str() : mStreams[i].mUri.c_str());
11980852843d304006e3ab333081fddda13b07193de8Robert Shih    return i >= 0
11990852843d304006e3ab333081fddda13b07193de8Robert Shih            && ((!newUri && uri == mStreams[i].mUri)
12000852843d304006e3ab333081fddda13b07193de8Robert Shih            || (newUri && uri == mStreams[i].mNewUri));
12010852843d304006e3ab333081fddda13b07193de8Robert Shih}
12020852843d304006e3ab333081fddda13b07193de8Robert Shih
12030852843d304006e3ab333081fddda13b07193de8Robert Shihsp<AnotherPacketSource> LiveSession::getPacketSourceForStreamIndex(
12040852843d304006e3ab333081fddda13b07193de8Robert Shih        size_t trackIndex, bool newUri) {
12050852843d304006e3ab333081fddda13b07193de8Robert Shih    StreamType type = indexToType(trackIndex);
12060852843d304006e3ab333081fddda13b07193de8Robert Shih    sp<AnotherPacketSource> source = NULL;
12070852843d304006e3ab333081fddda13b07193de8Robert Shih    if (newUri) {
12080852843d304006e3ab333081fddda13b07193de8Robert Shih        source = mPacketSources2.valueFor(type);
12090852843d304006e3ab333081fddda13b07193de8Robert Shih        source->clear();
12100852843d304006e3ab333081fddda13b07193de8Robert Shih    } else {
12110852843d304006e3ab333081fddda13b07193de8Robert Shih        source = mPacketSources.valueFor(type);
12120852843d304006e3ab333081fddda13b07193de8Robert Shih    };
12130852843d304006e3ab333081fddda13b07193de8Robert Shih    return source;
12140852843d304006e3ab333081fddda13b07193de8Robert Shih}
12150852843d304006e3ab333081fddda13b07193de8Robert Shih
12160852843d304006e3ab333081fddda13b07193de8Robert Shihsp<AnotherPacketSource> LiveSession::getMetadataSource(
12170852843d304006e3ab333081fddda13b07193de8Robert Shih        sp<AnotherPacketSource> sources[kNumSources], uint32_t streamMask, bool newUri) {
12180852843d304006e3ab333081fddda13b07193de8Robert Shih    // todo: One case where the following strategy can fail is when audio and video
12190852843d304006e3ab333081fddda13b07193de8Robert Shih    // are in separate playlists, both are transport streams, and the metadata
12200852843d304006e3ab333081fddda13b07193de8Robert Shih    // is actually contained in the audio stream.
12210852843d304006e3ab333081fddda13b07193de8Robert Shih    ALOGV("[timed_id3] getMetadataSourceForUri streamMask %x newUri %s",
12220852843d304006e3ab333081fddda13b07193de8Robert Shih            streamMask, newUri ? "true" : "false");
12230852843d304006e3ab333081fddda13b07193de8Robert Shih
12240852843d304006e3ab333081fddda13b07193de8Robert Shih    if ((sources[kVideoIndex] != NULL) // video fetcher; or ...
12250852843d304006e3ab333081fddda13b07193de8Robert Shih            || (!(streamMask & STREAMTYPE_VIDEO) && sources[kAudioIndex] != NULL)) {
12260852843d304006e3ab333081fddda13b07193de8Robert Shih            // ... audio fetcher for audio only variant
12270852843d304006e3ab333081fddda13b07193de8Robert Shih        return getPacketSourceForStreamIndex(kMetaDataIndex, newUri);
12280852843d304006e3ab333081fddda13b07193de8Robert Shih    }
12290852843d304006e3ab333081fddda13b07193de8Robert Shih
12300852843d304006e3ab333081fddda13b07193de8Robert Shih    return NULL;
12310852843d304006e3ab333081fddda13b07193de8Robert Shih}
12320852843d304006e3ab333081fddda13b07193de8Robert Shih
12337c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangbool LiveSession::resumeFetcher(
12347c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        const AString &uri, uint32_t streamMask, int64_t timeUs, bool newUri) {
12357c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    ssize_t index = mFetcherInfos.indexOfKey(uri);
12367c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    if (index < 0) {
12377c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        ALOGE("did not find fetcher for uri: %s", uri.c_str());
12387c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        return false;
12397c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    }
12407c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
12417c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    bool resume = false;
12420852843d304006e3ab333081fddda13b07193de8Robert Shih    sp<AnotherPacketSource> sources[kNumSources];
12437c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    for (size_t i = 0; i < kMaxStreams; ++i) {
12440852843d304006e3ab333081fddda13b07193de8Robert Shih        if ((streamMask & indexToType(i)) && UriIsSameAsIndex(uri, i, newUri)) {
12457c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            resume = true;
12460852843d304006e3ab333081fddda13b07193de8Robert Shih            sources[i] = getPacketSourceForStreamIndex(i, newUri);
12477c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        }
12487c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    }
12497c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
12507c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    if (resume) {
125125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang        sp<PlaylistFetcher> &fetcher = mFetcherInfos.editValueAt(index).mFetcher;
12527c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        SeekMode seekMode = newUri ? kSeekModeNextSample : kSeekModeExactPosition;
125325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang
125425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang        ALOGV("resuming fetcher-%d, timeUs=%lld, seekMode=%d",
125525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                fetcher->getFetcherID(), (long long)timeUs, seekMode);
125625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang
125725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang        fetcher->startAsync(
12587c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                sources[kAudioIndex],
12597c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                sources[kVideoIndex],
12607c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                sources[kSubtitleIndex],
12610852843d304006e3ab333081fddda13b07193de8Robert Shih                getMetadataSource(sources, streamMask, newUri),
12627c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                timeUs, -1, -1, seekMode);
12637c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    }
12647c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
12657c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    return resume;
12667c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang}
12677c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
1268a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhangfloat LiveSession::getAbortThreshold(
1269a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        ssize_t currentBWIndex, ssize_t targetBWIndex) const {
1270a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    float abortThreshold = -1.0f;
1271a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    if (currentBWIndex > 0 && targetBWIndex < currentBWIndex) {
1272a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        /*
1273a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           If we're switching down, we need to decide whether to
1274a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
1275a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           1) finish last segment of high-bandwidth variant, or
1276a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           2) abort last segment of high-bandwidth variant, and fetch an
1277a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang              overlapping portion from low-bandwidth variant.
1278a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
1279a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           Here we try to maximize the amount of buffer left when the
1280a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           switch point is met. Given the following parameters:
1281a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
1282a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           B: our current buffering level in seconds
1283a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           T: target duration in seconds
1284a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           X: sample duration in seconds remain to fetch in last segment
1285a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           bw0: bandwidth of old variant (as specified in playlist)
1286a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           bw1: bandwidth of new variant (as specified in playlist)
1287a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           bw: measured bandwidth available
1288a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
1289a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           If we choose 1), when switch happens at the end of current
1290a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           segment, our buffering will be
1291a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                  B + X - X * bw0 / bw
1292a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
1293a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           If we choose 2), when switch happens where we aborted current
1294a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           segment, our buffering will be
1295a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                  B - (T - X) * bw1 / bw
1296a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
1297a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           We should only choose 1) if
1298a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                  X/T < bw1 / (bw1 + bw0 - bw)
1299a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        */
1300a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
13015ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        // abort old bandwidth immediately if bandwidth is fluctuating a lot.
13025ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        // our estimate could be far off, and fetching old bandwidth could
13035ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        // take too long.
13045ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        if (!mLastBandwidthStable) {
13055ef659e010e90175eb5282d9642a02f6105189bfChong Zhang            return 0.0f;
13065ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        }
13075ef659e010e90175eb5282d9642a02f6105189bfChong Zhang
13087c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // Taking the measured current bandwidth at 50% face value only,
13097c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // as our bandwidth estimation is a lagging indicator. Being
13107c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // conservative on this, we prefer switching to lower bandwidth
13117c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // unless we're really confident finishing up the last segment
13127c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // of higher bandwidth will be fast.
1313a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        CHECK(mLastBandwidthBps >= 0);
1314a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        abortThreshold =
1315a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                (float)mBandwidthItems.itemAt(targetBWIndex).mBandwidth
1316a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang             / ((float)mBandwidthItems.itemAt(targetBWIndex).mBandwidth
1317a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang              + (float)mBandwidthItems.itemAt(currentBWIndex).mBandwidth
13187c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang              - (float)mLastBandwidthBps * 0.5f);
1319a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        if (abortThreshold < 0.0f) {
1320a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang            abortThreshold = -1.0f; // do not abort
1321a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        }
1322a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        ALOGV("Switching Down: bps %ld => %ld, measured %d, abort ratio %.2f",
1323a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                mBandwidthItems.itemAt(currentBWIndex).mBandwidth,
1324a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                mBandwidthItems.itemAt(targetBWIndex).mBandwidth,
1325a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                mLastBandwidthBps,
1326a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                abortThreshold);
1327a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    }
1328a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    return abortThreshold;
1329a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang}
1330a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
1331538b6d22a3578c0201d48f8548289aa254d81484Chong Zhangvoid LiveSession::addBandwidthMeasurement(size_t numBytes, int64_t delayUs) {
1332538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    mBandwidthEstimator->addBandwidthMeasurement(numBytes, delayUs);
1333538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang}
1334538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
13355ef659e010e90175eb5282d9642a02f6105189bfChong Zhangssize_t LiveSession::getLowestValidBandwidthIndex() const {
13365ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    for (size_t index = 0; index < mBandwidthItems.size(); index++) {
13375ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        if (isBandwidthValid(mBandwidthItems[index])) {
13385ef659e010e90175eb5282d9642a02f6105189bfChong Zhang            return index;
13395ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        }
13405ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    }
13415ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    // if playlists are all blacklisted, return 0 and hope it's alive
13425ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    return 0;
13435ef659e010e90175eb5282d9642a02f6105189bfChong Zhang}
13445ef659e010e90175eb5282d9642a02f6105189bfChong Zhang
1345538b6d22a3578c0201d48f8548289aa254d81484Chong Zhangsize_t LiveSession::getBandwidthIndex(int32_t bandwidthBps) {
1346538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    if (mBandwidthItems.size() < 2) {
1347538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        // shouldn't be here if we only have 1 bandwidth, check
1348538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        // logic to get rid of redundant bandwidth polling
1349538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        ALOGW("getBandwidthIndex() called for single bandwidth playlist!");
1350a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return 0;
1351a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1352a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1353a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#if 1
1354a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    char value[PROPERTY_VALUE_MAX];
1355673158582c9589cee1d5e4d7c79622609938b8f8Andreas Huber    ssize_t index = -1;
135614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (property_get("media.httplive.bw-index", value, NULL)) {
1357a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        char *end;
135814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        index = strtol(value, &end, 10);
135914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        CHECK(end > value && *end == '\0');
136014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
136114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (index >= 0 && (size_t)index >= mBandwidthItems.size()) {
136214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            index = mBandwidthItems.size() - 1;
1363a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
1364a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1365a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
136614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (index < 0) {
136714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        char value[PROPERTY_VALUE_MAX];
136814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (property_get("media.httplive.max-bw", value, NULL)) {
136914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            char *end;
137014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            long maxBw = strtoul(value, &end, 10);
137114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            if (end > value && *end == '\0') {
137214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                if (maxBw > 0 && bandwidthBps > maxBw) {
137314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    ALOGV("bandwidth capped to %ld bps", maxBw);
137414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    bandwidthBps = maxBw;
137514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                }
137614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            }
137714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
1378a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
13795ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        // Pick the highest bandwidth stream that's not currently blacklisted
13805ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        // below or equal to estimated bandwidth.
138114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
138214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        index = mBandwidthItems.size() - 1;
13835ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        ssize_t lowestBandwidth = getLowestValidBandwidthIndex();
13845ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        while (index > lowestBandwidth) {
1385538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang            // be conservative (70%) to avoid overestimating and immediately
1386538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang            // switching down again.
1387538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang            size_t adjustedBandwidthBps = bandwidthBps * 7 / 10;
13885ef659e010e90175eb5282d9642a02f6105189bfChong Zhang            const BandwidthItem &item = mBandwidthItems[index];
13895ef659e010e90175eb5282d9642a02f6105189bfChong Zhang            if (item.mBandwidth <= adjustedBandwidthBps
13905ef659e010e90175eb5282d9642a02f6105189bfChong Zhang                    && isBandwidthValid(item)) {
139100598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih                break;
139200598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih            }
139314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            --index;
139414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
1395a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1396a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0
1397a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // Change bandwidth at random()
1398a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index = uniformRand() * mBandwidthItems.size();
1399a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0
1400a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // There's a 50% chance to stay on the current bandwidth and
1401a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // a 50% chance to switch to the next higher bandwidth (wrapping around
1402a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // to lowest)
1403a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    const size_t kMinIndex = 0;
1404a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1405309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    static ssize_t mCurBandwidthIndex = -1;
140614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
1407a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index;
1408309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    if (mCurBandwidthIndex < 0) {
1409a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        index = kMinIndex;
1410a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else if (uniformRand() < 0.5) {
1411309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        index = (size_t)mCurBandwidthIndex;
1412a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else {
1413309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        index = mCurBandwidthIndex + 1;
1414a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (index == mBandwidthItems.size()) {
1415a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            index = kMinIndex;
1416a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
1417a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1418309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    mCurBandwidthIndex = index;
1419a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0
1420a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // Pick the highest bandwidth stream below or equal to 1.2 Mbit/sec
1421a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1422a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index = mBandwidthItems.size() - 1;
1423a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    while (index > 0 && mBandwidthItems.itemAt(index).mBandwidth > 1200000) {
1424a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        --index;
1425a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
142614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#elif 1
142714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    char value[PROPERTY_VALUE_MAX];
142814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    size_t index;
142914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (property_get("media.httplive.bw-index", value, NULL)) {
143014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        char *end;
143114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        index = strtoul(value, &end, 10);
143214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        CHECK(end > value && *end == '\0');
143314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
143414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (index >= mBandwidthItems.size()) {
143514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            index = mBandwidthItems.size() - 1;
143614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
143714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    } else {
143814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        index = 0;
143914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
1440a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#else
1441a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index = mBandwidthItems.size() - 1;  // Highest bandwidth stream
1442a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#endif
1443a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
144414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK_GE(index, 0);
144514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
1446a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return index;
1447a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
1448a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1449d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong ZhangHLSTime LiveSession::latestMediaSegmentStartTime() const {
1450d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang    HLSTime audioTime(mPacketSources.valueFor(
1451d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                    STREAMTYPE_AUDIO)->getLatestDequeuedMeta());
1452b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih
1453d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang    HLSTime videoTime(mPacketSources.valueFor(
1454d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                    STREAMTYPE_VIDEO)->getLatestDequeuedMeta());
1455b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih
1456d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang    return audioTime < videoTime ? videoTime : audioTime;
1457b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih}
1458b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih
1459a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnarvoid LiveSession::onSeek(const sp<AMessage> &msg) {
146014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    int64_t timeUs;
1461c5de09127e9e0d5df7aa587be317e1487d793245Wei Jia    int32_t mode;
146214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(msg->findInt64("timeUs", &timeUs));
1463c5de09127e9e0d5df7aa587be317e1487d793245Wei Jia    CHECK(msg->findInt32("mode", &mode));
1464c5de09127e9e0d5df7aa587be317e1487d793245Wei Jia    // TODO: add "mode" to changeConfiguration.
1465c5de09127e9e0d5df7aa587be317e1487d793245Wei Jia    changeConfiguration(timeUs/* , (MediaPlayerSeekMode)mode */);
14667e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber}
14677e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
146814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::getDuration(int64_t *durationUs) const {
1469895651b07fec30b0f9b0d2499599a179d95c9be4Wei Jia    int64_t maxDurationUs = -1ll;
147014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
147114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        int64_t fetcherDurationUs = mFetcherInfos.valueAt(i).mDurationUs;
1472b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
1473895651b07fec30b0f9b0d2499599a179d95c9be4Wei Jia        if (fetcherDurationUs > maxDurationUs) {
147414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            maxDurationUs = fetcherDurationUs;
1475a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
1476a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1477a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
147814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    *durationUs = maxDurationUs;
1479a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
148014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return OK;
148114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
14820f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber
148314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberbool LiveSession::isSeekable() const {
148414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    int64_t durationUs;
148514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return getDuration(&durationUs) == OK && durationUs >= 0;
148614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
14870f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber
148814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberbool LiveSession::hasDynamicDuration() const {
148914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return false;
149014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
14910f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber
1492404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhangsize_t LiveSession::getTrackCount() const {
14939d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih    if (mPlaylist == NULL) {
14949d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih        return 0;
14959d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih    } else {
14960852843d304006e3ab333081fddda13b07193de8Robert Shih        return mPlaylist->getTrackCount() + (mHasMetadata ? 1 : 0);
14979d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih    }
1498404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang}
1499404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang
1500404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhangsp<AMessage> LiveSession::getTrackInfo(size_t trackIndex) const {
15019d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih    if (mPlaylist == NULL) {
15029d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih        return NULL;
15039d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih    } else {
15040852843d304006e3ab333081fddda13b07193de8Robert Shih        if (trackIndex == mPlaylist->getTrackCount() && mHasMetadata) {
15050852843d304006e3ab333081fddda13b07193de8Robert Shih            sp<AMessage> format = new AMessage();
15060852843d304006e3ab333081fddda13b07193de8Robert Shih            format->setInt32("type", MEDIA_TRACK_TYPE_METADATA);
15070852843d304006e3ab333081fddda13b07193de8Robert Shih            format->setString("language", "und");
15086f9c5e26c710dbee50e57316f1c460dda4850fa5Robert Shih            format->setString("mime", MEDIA_MIMETYPE_DATA_TIMED_ID3);
15090852843d304006e3ab333081fddda13b07193de8Robert Shih            return format;
15100852843d304006e3ab333081fddda13b07193de8Robert Shih        }
15119d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih        return mPlaylist->getTrackInfo(trackIndex);
15129d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih    }
1513dcb89b3b505522efde173c105a851c412f947178Chong Zhang}
1514dcb89b3b505522efde173c105a851c412f947178Chong Zhang
1515dcb89b3b505522efde173c105a851c412f947178Chong Zhangstatus_t LiveSession::selectTrack(size_t index, bool select) {
1516b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    if (mPlaylist == NULL) {
1517b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih        return INVALID_OPERATION;
1518b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    }
1519b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih
152025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    ALOGV("selectTrack: index=%zu, select=%d, mSubtitleGen=%d++",
152125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            index, select, mSubtitleGeneration);
152225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang
1523b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    ++mSubtitleGeneration;
1524dcb89b3b505522efde173c105a851c412f947178Chong Zhang    status_t err = mPlaylist->selectTrack(index, select);
1525dcb89b3b505522efde173c105a851c412f947178Chong Zhang    if (err == OK) {
15261d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar        sp<AMessage> msg = new AMessage(kWhatChangeConfiguration, this);
1527309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        msg->setInt32("pickTrack", select);
1528309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        msg->post();
1529dcb89b3b505522efde173c105a851c412f947178Chong Zhang    }
1530dcb89b3b505522efde173c105a851c412f947178Chong Zhang    return err;
1531dcb89b3b505522efde173c105a851c412f947178Chong Zhang}
1532dcb89b3b505522efde173c105a851c412f947178Chong Zhang
153389bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shihssize_t LiveSession::getSelectedTrack(media_track_type type) const {
153489bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih    if (mPlaylist == NULL) {
153589bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih        return -1;
153689bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih    } else {
153789bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih        return mPlaylist->getSelectedTrack(type);
153889bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih    }
153989bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih}
154089bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih
1541dcb89b3b505522efde173c105a851c412f947178Chong Zhangvoid LiveSession::changeConfiguration(
15427c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        int64_t timeUs, ssize_t bandwidthIndex, bool pickTrack) {
154325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    ALOGV("changeConfiguration: timeUs=%lld us, bwIndex=%zd, pickTrack=%d",
154425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang          (long long)timeUs, bandwidthIndex, pickTrack);
154525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang
15461543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    cancelBandwidthSwitch();
15471543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
154814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(!mReconfigurationInProgress);
154914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mReconfigurationInProgress = true;
15507c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    if (bandwidthIndex >= 0) {
15517c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        mOrigBandwidthIndex = mCurBandwidthIndex;
15527c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        mCurBandwidthIndex = bandwidthIndex;
15538464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang        if (mOrigBandwidthIndex != mCurBandwidthIndex) {
15548464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            ALOGI("#### Starting Bandwidth Switch: %zd => %zd",
15558464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang                    mOrigBandwidthIndex, mCurBandwidthIndex);
15568464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang        }
15577c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    }
15586f51c153ea5e4187a313e47ac8bad9a1a999d4e1Colin Cross    CHECK_LT((size_t)mCurBandwidthIndex, mBandwidthItems.size());
15597c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    const BandwidthItem &item = mBandwidthItems.itemAt(mCurBandwidthIndex);
1560a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
15611543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    uint32_t streamMask = 0; // streams that should be fetched by the new fetcher
15621543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    uint32_t resumeMask = 0; // streams that should be fetched by the original fetcher
1563a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
15648ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    AString URIs[kMaxStreams];
15658ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
15668ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        if (mPlaylist->getTypeURI(item.mPlaylistIndex, mStreams[i].mType, &URIs[i])) {
15678ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            streamMask |= indexToType(i);
15688ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        }
156914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
1570aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber
157114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Step 1, stop and discard fetchers that are no longer needed.
157214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Pause those that we'll reuse.
157314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
15747c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // skip fetchers that are marked mToBeRemoved,
15757c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // these are done and can't be reused
15767c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        if (mFetcherInfos[i].mToBeRemoved) {
15777c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            continue;
15787c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        }
15797c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
158014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        const AString &uri = mFetcherInfos.keyAt(i);
1581d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        sp<PlaylistFetcher> &fetcher = mFetcherInfos.editValueAt(i).mFetcher;
1582aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber
1583d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        bool discardFetcher = true, delayRemoval = false;
1584c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        for (size_t j = 0; j < kMaxStreams; ++j) {
1585c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang            StreamType type = indexToType(j);
1586c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang            if ((streamMask & type) && uri == URIs[j]) {
1587c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang                resumeMask |= type;
1588c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang                streamMask &= ~type;
1589c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang                discardFetcher = false;
15906801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber            }
159114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
1592d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        // Delay fetcher removal if not picking tracks, AND old fetcher
1593d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        // has stream mask that overlaps new variant. (Okay to discard
1594d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        // old fetcher now, if completely no overlap.)
1595d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        if (discardFetcher && timeUs < 0ll && !pickTrack
1596d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                && (fetcher->getStreamTypeMask() & streamMask)) {
1597d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            discardFetcher = false;
1598d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            delayRemoval = true;
1599d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        }
1600a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
160114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (discardFetcher) {
160225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            ALOGV("discarding fetcher-%d", fetcher->getFetcherID());
1603d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            fetcher->stopAsync();
16046801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber        } else {
16058a048338d9291b2db1b3a325fff58cb1aa69f04dChong Zhang            float threshold = 0.0f; // default to pause after current block (47Kbytes)
16065abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang            bool disconnect = false;
1607a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang            if (timeUs >= 0ll) {
1608a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                // seeking, no need to finish fetching
16095abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang                disconnect = true;
1610d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            } else if (delayRemoval) {
1611a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                // adapting, abort if remaining of current segment is over threshold
1612a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                threshold = getAbortThreshold(
16137c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                        mOrigBandwidthIndex, mCurBandwidthIndex);
1614a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang            }
1615a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
161625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            ALOGV("pausing fetcher-%d, threshold=%.2f",
161725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                    fetcher->getFetcherID(), threshold);
16185abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang            fetcher->pauseAsync(threshold, disconnect);
16196801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber        }
1620a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1621a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
16221543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    sp<AMessage> msg;
16231543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    if (timeUs < 0ll) {
1624309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        // skip onChangeConfiguration2 (decoder destruction) if not seeking.
16251d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar        msg = new AMessage(kWhatChangeConfiguration3, this);
16261543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    } else {
16271d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar        msg = new AMessage(kWhatChangeConfiguration2, this);
16281543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
162914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    msg->setInt32("streamMask", streamMask);
16301543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    msg->setInt32("resumeMask", resumeMask);
1631309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    msg->setInt32("pickTrack", pickTrack);
163214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    msg->setInt64("timeUs", timeUs);
16338ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
1634309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        if ((streamMask | resumeMask) & indexToType(i)) {
16358ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            msg->setString(mStreams[i].uriKey().c_str(), URIs[i].c_str());
16368ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        }
16376e6b1cae2bac1b78205cefab8e4e9e9538982965Andreas Huber    }
1638a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
163914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Every time a fetcher acknowledges the stopAsync or pauseAsync request
164014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // we'll decrement mContinuationCounter, once it reaches zero, i.e. all
164114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // fetchers have completed their asynchronous operation, we'll post
164214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // mContinuation, which then is handled below in onChangeConfiguration2.
164314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mContinuationCounter = mFetcherInfos.size();
164414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mContinuation = msg;
164588b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber
164614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (mContinuationCounter == 0) {
164714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        msg->post();
164888b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber    }
164914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
1650a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1651dcb89b3b505522efde173c105a851c412f947178Chong Zhangvoid LiveSession::onChangeConfiguration(const sp<AMessage> &msg) {
165225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    ALOGV("onChangeConfiguration");
165325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang
1654dcb89b3b505522efde173c105a851c412f947178Chong Zhang    if (!mReconfigurationInProgress) {
16557c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        int32_t pickTrack = 0;
1656309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        msg->findInt32("pickTrack", &pickTrack);
16577c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        changeConfiguration(-1ll /* timeUs */, -1, pickTrack);
1658dcb89b3b505522efde173c105a851c412f947178Chong Zhang    } else {
1659dcb89b3b505522efde173c105a851c412f947178Chong Zhang        msg->post(1000000ll); // retry in 1 sec
1660dcb89b3b505522efde173c105a851c412f947178Chong Zhang    }
1661dcb89b3b505522efde173c105a851c412f947178Chong Zhang}
1662dcb89b3b505522efde173c105a851c412f947178Chong Zhang
166314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::onChangeConfiguration2(const sp<AMessage> &msg) {
166425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    ALOGV("onChangeConfiguration2");
166525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang
166614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mContinuation.clear();
1667bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
166814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // All fetchers are either suspended or have been removed now.
1669bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
1670964adb17885185808398507d2de88665fe193ee2Chong Zhang    // If we're seeking, clear all packet sources before we report
1671964adb17885185808398507d2de88665fe193ee2Chong Zhang    // seek complete, to prevent decoder from pulling stale data.
1672964adb17885185808398507d2de88665fe193ee2Chong Zhang    int64_t timeUs;
1673964adb17885185808398507d2de88665fe193ee2Chong Zhang    CHECK(msg->findInt64("timeUs", &timeUs));
1674964adb17885185808398507d2de88665fe193ee2Chong Zhang
1675964adb17885185808398507d2de88665fe193ee2Chong Zhang    if (timeUs >= 0) {
1676964adb17885185808398507d2de88665fe193ee2Chong Zhang        mLastSeekTimeUs = timeUs;
16778464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang        mLastDequeuedTimeUs = timeUs;
1678964adb17885185808398507d2de88665fe193ee2Chong Zhang
1679964adb17885185808398507d2de88665fe193ee2Chong Zhang        for (size_t i = 0; i < mPacketSources.size(); i++) {
16807f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih            sp<AnotherPacketSource> packetSource = mPacketSources.editValueAt(i);
16817f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih            sp<MetaData> format = packetSource->getFormat();
16827f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih            packetSource->clear();
16837f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih            // Set a tentative format here such that HTTPLiveSource will always have
16847f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih            // a format available when NuPlayer queries. Without an available video
16857f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih            // format when setting a surface NuPlayer might disable video decoding
16867f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih            // altogether. The tentative format will be overwritten by the
16877f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih            // authoritative (and possibly same) format once content from the new
16887f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih            // position is dequeued.
16897f3bb5ad9dfb30388b69166e58391ff3aa6f00a3Robert Shih            packetSource->setFormat(format);
1690964adb17885185808398507d2de88665fe193ee2Chong Zhang        }
1691964adb17885185808398507d2de88665fe193ee2Chong Zhang
16927c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        for (size_t i = 0; i < kMaxStreams; ++i) {
169381636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang            mStreams[i].reset();
16947c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        }
16957c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
1696964adb17885185808398507d2de88665fe193ee2Chong Zhang        mDiscontinuityOffsetTimesUs.clear();
1697964adb17885185808398507d2de88665fe193ee2Chong Zhang        mDiscontinuityAbsStartTimesUs.clear();
1698964adb17885185808398507d2de88665fe193ee2Chong Zhang
1699c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        if (mSeekReplyID != NULL) {
1700964adb17885185808398507d2de88665fe193ee2Chong Zhang            CHECK(mSeekReply != NULL);
1701964adb17885185808398507d2de88665fe193ee2Chong Zhang            mSeekReply->setInt32("err", OK);
1702964adb17885185808398507d2de88665fe193ee2Chong Zhang            mSeekReply->postReply(mSeekReplyID);
1703c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang            mSeekReplyID.clear();
1704964adb17885185808398507d2de88665fe193ee2Chong Zhang            mSeekReply.clear();
1705964adb17885185808398507d2de88665fe193ee2Chong Zhang        }
17067c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
17077c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // restart buffer polling after seek becauese previous
17087c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // buffering position is no longer valid.
17097c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        restartPollBuffering();
1710964adb17885185808398507d2de88665fe193ee2Chong Zhang    }
1711964adb17885185808398507d2de88665fe193ee2Chong Zhang
1712309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    uint32_t streamMask, resumeMask;
171314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(msg->findInt32("streamMask", (int32_t *)&streamMask));
1714309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    CHECK(msg->findInt32("resumeMask", (int32_t *)&resumeMask));
1715309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
1716309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    streamMask |= resumeMask;
1717bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
17188ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    AString URIs[kMaxStreams];
17198ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
17208ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        if (streamMask & indexToType(i)) {
17218ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            const AString &uriKey = mStreams[i].uriKey();
17228ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            CHECK(msg->findString(uriKey.c_str(), &URIs[i]));
17238ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            ALOGV("%s = '%s'", uriKey.c_str(), URIs[i].c_str());
17248ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        }
172522fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber    }
17263831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber
172714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    uint32_t changedMask = 0;
17288ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams && i != kSubtitleIndex; ++i) {
1729c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        // stream URI could change even if onChangeConfiguration2 is only
1730c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        // used for seek. Seek could happen during a bw switch, in this
1731c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        // case bw switch will be cancelled, but the seekTo position will
1732c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        // fetch from the new URI.
1733c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        if ((mStreamMask & streamMask & indexToType(i))
1734c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang                && !mStreams[i].mUri.empty()
1735c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang                && !(URIs[i] == mStreams[i].mUri)) {
17364604458dfe57b0e91a464aefafea50ae7b9876c1Chong Zhang            ALOGV("stream %zu changed: oldURI %s, newURI %s", i,
1737c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang                    mStreams[i].mUri.c_str(), URIs[i].c_str());
1738c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang            sp<AnotherPacketSource> source = mPacketSources.valueFor(indexToType(i));
17398464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            if (source->getLatestDequeuedMeta() != NULL) {
17408464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang                source->queueDiscontinuity(
17418464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang                        ATSParser::DISCONTINUITY_FORMATCHANGE, NULL, true);
17428464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            }
1743c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        }
1744c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        // Determine which decoders to shutdown on the player side,
1745c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        // a decoder has to be shutdown if its streamtype was active
1746c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        // before but now longer isn't.
1747c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        if ((mStreamMask & ~streamMask & indexToType(i))) {
17488ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            changedMask |= indexToType(i);
17498ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        }
1750b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber    }
1751b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
175214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (changedMask == 0) {
175314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        // If nothing changed as far as the audio/video decoders
175414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        // are concerned we can proceed.
175514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        onChangeConfiguration3(msg);
175614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        return;
175714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
175843c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
175914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Something changed, inform the player which will shutdown the
176014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // corresponding decoders and will post the reply once that's done.
176114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Handling the reply will continue executing below in
176214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // onChangeConfiguration3.
176314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> notify = mNotify->dup();
176414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->setInt32("what", kWhatStreamsChanged);
176514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->setInt32("changedMask", changedMask);
176620f725ebcef13ded1b4b85c61c8a4b37cd030656Andreas Huber
176714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    msg->setWhat(kWhatChangeConfiguration3);
17681d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    msg->setTarget(this);
1769b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
177014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->setMessage("reply", msg);
177114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->post();
177214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
1773b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
177414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::onChangeConfiguration3(const sp<AMessage> &msg) {
17751543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    mContinuation.clear();
177614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // All remaining fetchers are still suspended, the player has shutdown
177714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // any decoders that needed it.
1778b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
17791543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    uint32_t streamMask, resumeMask;
178014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(msg->findInt32("streamMask", (int32_t *)&streamMask));
17811543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    CHECK(msg->findInt32("resumeMask", (int32_t *)&resumeMask));
1782a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1783d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang    mNewStreamMask = streamMask | resumeMask;
1784d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang
178514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    int64_t timeUs;
1786309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    int32_t pickTrack;
17871543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    bool switching = false;
178814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(msg->findInt64("timeUs", &timeUs));
1789309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    CHECK(msg->findInt32("pickTrack", &pickTrack));
1790a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
179114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (timeUs < 0ll) {
1792309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        if (!pickTrack) {
1793d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            // mSwapMask contains streams that are in both old and new variant,
1794d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            // (in mNewStreamMask & mStreamMask) but with different URIs
1795d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            // (not in resumeMask).
1796d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            // For example, old variant has video and audio in two separate
1797d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            // URIs, and new variant has only audio with unchanged URI. mSwapMask
1798d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            // should be 0 as there is nothing to swap. We only need to stop video,
1799d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            // and resume audio.
1800d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            mSwapMask =  mNewStreamMask & mStreamMask & ~resumeMask;
1801d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            switching = (mSwapMask != 0);
1802309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        }
1803309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        mRealTimeBaseUs = ALooper::GetNowUs() - mLastDequeuedTimeUs;
1804309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    } else {
1805309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        mRealTimeBaseUs = ALooper::GetNowUs() - timeUs;
180614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
1807a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
180825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    ALOGV("onChangeConfiguration3: timeUs=%lld, switching=%d, pickTrack=%d, "
180925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            "mStreamMask=0x%x, mNewStreamMask=0x%x, mSwapMask=0x%x",
181025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            (long long)timeUs, switching, pickTrack,
181125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            mStreamMask, mNewStreamMask, mSwapMask);
181225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang
1813f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
1814f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        if (streamMask & indexToType(i)) {
1815f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            if (switching) {
1816f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih                CHECK(msg->findString(mStreams[i].uriKey().c_str(), &mStreams[i].mNewUri));
1817f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            } else {
1818f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih                CHECK(msg->findString(mStreams[i].uriKey().c_str(), &mStreams[i].mUri));
1819f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            }
1820f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        }
1821f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    }
1822f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih
18231543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // Of all existing fetchers:
18241543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // * Resume fetchers that are still needed and assign them original packet sources.
18251543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // * Mark otherwise unneeded fetchers for removal.
18261543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    ALOGV("resuming fetchers for mask 0x%08x", resumeMask);
182714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
182814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        const AString &uri = mFetcherInfos.keyAt(i);
18297c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        if (!resumeFetcher(uri, resumeMask, timeUs)) {
183025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            ALOGV("marking fetcher-%d to be removed",
183125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                    mFetcherInfos[i].mFetcher->getFetcherID());
183225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang
18337c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            mFetcherInfos.editValueAt(i).mToBeRemoved = true;
18341543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        }
1835a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1836a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
183714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // streamMask now only contains the types that need a new fetcher created.
183814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (streamMask != 0) {
183914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        ALOGV("creating new fetchers for mask 0x%08x", streamMask);
1840a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1841a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
18421543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // Find out when the original fetchers have buffered up to and start the new fetchers
18431543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // at a later timestamp.
18448ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams; i++) {
18458ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        if (!(indexToType(i) & streamMask)) {
18468ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            continue;
18478ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        }
18481156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
184914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        AString uri;
1850f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        uri = switching ? mStreams[i].mNewUri : mStreams[i].mUri;
18519b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber
185214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        sp<PlaylistFetcher> fetcher = addFetcher(uri.c_str());
185314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        CHECK(fetcher != NULL);
1854a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1855d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        HLSTime startTime;
1856a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        SeekMode seekMode = kSeekModeExactPosition;
18570852843d304006e3ab333081fddda13b07193de8Robert Shih        sp<AnotherPacketSource> sources[kNumSources];
18581543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
1859d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        if (i == kSubtitleIndex || (!pickTrack && !switching)) {
1860d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            startTime = latestMediaSegmentStartTime();
1861b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih        }
1862b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih
18638ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        // TRICKY: looping from i as earlier streams are already removed from streamMask
18648ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        for (size_t j = i; j < kMaxStreams; ++j) {
1865f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            const AString &streamUri = switching ? mStreams[j].mNewUri : mStreams[j].mUri;
1866f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            if ((streamMask & indexToType(j)) && uri == streamUri) {
18678ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                sources[j] = mPacketSources.valueFor(indexToType(j));
18681543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
1869309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                if (timeUs >= 0) {
1870d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                    startTime.mTimeUs = timeUs;
18711543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                } else {
1872309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    int32_t type;
1873309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    sp<AMessage> meta;
1874d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                    if (!switching) {
1875d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                        // selecting, or adapting but no swap required
1876309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        meta = sources[j]->getLatestDequeuedMeta();
1877309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    } else {
1878d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                        // adapting and swap required
1879309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        meta = sources[j]->getLatestEnqueuedMeta();
18807c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                        if (meta != NULL && mCurBandwidthIndex > mOrigBandwidthIndex) {
18817c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                            // switching up
18827c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                            meta = sources[j]->getMetaAfterLastDequeued(mUpSwitchMargin);
18837c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                        }
1884309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    }
18851543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
18860852843d304006e3ab333081fddda13b07193de8Robert Shih                    if ((j == kAudioIndex || j == kVideoIndex)
18870852843d304006e3ab333081fddda13b07193de8Robert Shih                            && meta != NULL && !meta->findInt32("discontinuity", &type)) {
1888d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                        HLSTime tmpTime(meta);
1889d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                        if (startTime < tmpTime) {
1890d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                            startTime = tmpTime;
18911543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        }
18921543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    }
18931543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
1894d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                    if (!switching) {
1895d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                        // selecting, or adapting but no swap required
1896309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        sources[j]->clear();
1897309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        if (j == kSubtitleIndex) {
1898309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                            break;
1899309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        }
1900964adb17885185808398507d2de88665fe193ee2Chong Zhang
19014604458dfe57b0e91a464aefafea50ae7b9876c1Chong Zhang                        ALOGV("stream[%zu]: queue format change", j);
1902964adb17885185808398507d2de88665fe193ee2Chong Zhang                        sources[j]->queueDiscontinuity(
1903a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                                ATSParser::DISCONTINUITY_FORMAT_ONLY, NULL, true);
1904309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    } else {
1905d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                        // switching, queue discontinuities after resume
1906309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        sources[j] = mPacketSources2.valueFor(indexToType(j));
1907309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        sources[j]->clear();
1908a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                        // the new fetcher might be providing streams that used to be
1909a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                        // provided by two different fetchers,  if one of the fetcher
1910a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                        // paused in the middle while the other somehow paused in next
1911a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                        // seg, we have to start from next seg.
1912a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                        if (seekMode < mStreams[j].mSeekMode) {
1913a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                            seekMode = mStreams[j].mSeekMode;
1914309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        }
19151543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    }
19161543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                }
1917a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
19188ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                streamMask &= ~indexToType(j);
19198ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            }
1920a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
192114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
192225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang        ALOGV("[fetcher-%d] startAsync: startTimeUs %lld mLastSeekTimeUs %lld "
192325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                "segmentStartTimeUs %lld seekMode %d",
192425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                fetcher->getFetcherID(),
192525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                (long long)startTime.mTimeUs,
192625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                (long long)mLastSeekTimeUs,
1927978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang                (long long)startTime.getSegmentTimeUs(),
192825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                seekMode);
192925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang
1930d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        // Set the target segment start time to the middle point of the
1931d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        // segment where the last sample was.
1932d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        // This gives a better guess if segments of the two variants are not
1933d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        // perfectly aligned. (If the corresponding segment in new variant
1934d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        // starts slightly later than that in the old variant, we still want
1935d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        // to pick that segment, not the one before)
19368ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        fetcher->startAsync(
19378ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                sources[kAudioIndex],
19388ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                sources[kVideoIndex],
19398ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                sources[kSubtitleIndex],
19400852843d304006e3ab333081fddda13b07193de8Robert Shih                getMetadataSource(sources, mNewStreamMask, switching),
1941d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                startTime.mTimeUs < 0 ? mLastSeekTimeUs : startTime.mTimeUs,
1942978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang                startTime.getSegmentTimeUs(),
1943d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                startTime.mSeq,
1944a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                seekMode);
1945a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1946a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
194714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // All fetchers have now been started, the configuration change
194814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // has completed.
1949a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
195014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mReconfigurationInProgress = false;
19511543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    if (switching) {
19521543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        mSwitchInProgress = true;
19531543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    } else {
19541543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        mStreamMask = mNewStreamMask;
19558464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang        if (mOrigBandwidthIndex != mCurBandwidthIndex) {
19568464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            ALOGV("#### Finished Bandwidth Switch Early: %zd => %zd",
19578464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang                    mOrigBandwidthIndex, mCurBandwidthIndex);
19588464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            mOrigBandwidthIndex = mCurBandwidthIndex;
19598464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang        }
19601543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
1961a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
196225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    ALOGV("onChangeConfiguration3: mSwitchInProgress %d, mStreamMask 0x%x",
196325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            mSwitchInProgress, mStreamMask);
196425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang
1965c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang    if (mDisconnectReplyID != NULL) {
196614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        finishDisconnect();
1967a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
196814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
1969a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1970a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhangvoid LiveSession::swapPacketSource(StreamType stream) {
197125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    ALOGV("[%s] swapPacketSource", getNameForStream(stream));
1972a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
1973a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    // transfer packets from source2 to source
1974a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    sp<AnotherPacketSource> &aps = mPacketSources.editValueFor(stream);
1975a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    sp<AnotherPacketSource> &aps2 = mPacketSources2.editValueFor(stream);
1976a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
1977a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    // queue discontinuity in mPacketSource
1978a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    aps->queueDiscontinuity(ATSParser::DISCONTINUITY_FORMAT_ONLY, NULL, false);
1979a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
1980a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    // queue packets in mPacketSource2 to mPacketSource
1981a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    status_t finalResult = OK;
1982a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    sp<ABuffer> accessUnit;
1983a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    while (aps2->hasBufferAvailable(&finalResult) && finalResult == OK &&
1984a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang          OK == aps2->dequeueAccessUnit(&accessUnit)) {
1985a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        aps->queueAccessUnit(accessUnit);
1986a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    }
1987a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    aps2->clear();
1988a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang}
1989a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
19907c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::tryToFinishBandwidthSwitch(const AString &oldUri) {
1991a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    if (!mSwitchInProgress) {
1992a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        return;
1993a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    }
1994a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
19957c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    ssize_t index = mFetcherInfos.indexOfKey(oldUri);
1996a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    if (index < 0 || !mFetcherInfos[index].mToBeRemoved) {
19971543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return;
19981543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
19991543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
2000a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    // Swap packet source of streams provided by old variant
2001a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    for (size_t idx = 0; idx < kMaxStreams; idx++) {
20027c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        StreamType stream = indexToType(idx);
20037c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        if ((mSwapMask & stream) && (oldUri == mStreams[idx].mUri)) {
2004a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang            swapPacketSource(stream);
2005a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
2006a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang            if ((mNewStreamMask & stream) && mStreams[idx].mNewUri.empty()) {
2007a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                ALOGW("swapping stream type %d %s to empty stream",
2008a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                        stream, mStreams[idx].mUri.c_str());
2009a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang            }
2010a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang            mStreams[idx].mUri = mStreams[idx].mNewUri;
2011a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang            mStreams[idx].mNewUri.clear();
2012a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
2013a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang            mSwapMask &= ~stream;
2014a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        }
2015f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    }
2016f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih
20177c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    mFetcherInfos.editValueAt(index).mFetcher->stopAsync(false /* clear */);
2018a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
201925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    ALOGV("tryToFinishBandwidthSwitch: mSwapMask=0x%x", mSwapMask);
2020309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    if (mSwapMask != 0) {
20211543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return;
20221543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
20231543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
20241543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // Check if new variant contains extra streams.
20251543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    uint32_t extraStreams = mNewStreamMask & (~mStreamMask);
20261543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    while (extraStreams) {
2027a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        StreamType stream = (StreamType) (extraStreams & ~(extraStreams - 1));
2028a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        extraStreams &= ~stream;
2029a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
2030a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        swapPacketSource(stream);
2031f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih
2032a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        ssize_t idx = typeToIndex(stream);
2033f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        CHECK(idx >= 0);
2034f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        if (mStreams[idx].mNewUri.empty()) {
2035f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            ALOGW("swapping extra stream type %d %s to empty stream",
2036a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                    stream, mStreams[idx].mUri.c_str());
2037f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        }
2038f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        mStreams[idx].mUri = mStreams[idx].mNewUri;
2039f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        mStreams[idx].mNewUri.clear();
20401543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
20411543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
2042a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    // Restart new fetcher (it was paused after the first 47k block)
2043a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    // and let it fetch into mPacketSources (not mPacketSources2)
2044a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
2045a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        FetcherInfo &info = mFetcherInfos.editValueAt(i);
2046a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        if (info.mToBeResumed) {
20477c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            resumeFetcher(mFetcherInfos.keyAt(i), mNewStreamMask);
2048a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang            info.mToBeResumed = false;
2049a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        }
2050a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    }
2051a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
20527c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    ALOGI("#### Finished Bandwidth Switch: %zd => %zd",
20537c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            mOrigBandwidthIndex, mCurBandwidthIndex);
20547c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
2055a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    mStreamMask = mNewStreamMask;
2056a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    mSwitchInProgress = false;
20577c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    mOrigBandwidthIndex = mCurBandwidthIndex;
2058a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
20597c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    restartPollBuffering();
20601543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
20611543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
2062964adb17885185808398507d2de88665fe193ee2Chong Zhangvoid LiveSession::schedulePollBuffering() {
2063964adb17885185808398507d2de88665fe193ee2Chong Zhang    sp<AMessage> msg = new AMessage(kWhatPollBuffering, this);
2064964adb17885185808398507d2de88665fe193ee2Chong Zhang    msg->setInt32("generation", mPollBufferingGeneration);
2065964adb17885185808398507d2de88665fe193ee2Chong Zhang    msg->post(1000000ll);
2066964adb17885185808398507d2de88665fe193ee2Chong Zhang}
2067678bcdc852dd8f801f5c46fdc85db587b721d83dApurupa Pattapu
2068964adb17885185808398507d2de88665fe193ee2Chong Zhangvoid LiveSession::cancelPollBuffering() {
2069964adb17885185808398507d2de88665fe193ee2Chong Zhang    ++mPollBufferingGeneration;
20707c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    mPrevBufferPercentage = -1;
20717c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang}
20727c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
20737c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::restartPollBuffering() {
20747c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    cancelPollBuffering();
20757c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    onPollBuffering();
2076964adb17885185808398507d2de88665fe193ee2Chong Zhang}
20770ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
2078964adb17885185808398507d2de88665fe193ee2Chong Zhangvoid LiveSession::onPollBuffering() {
2079964adb17885185808398507d2de88665fe193ee2Chong Zhang    ALOGV("onPollBuffering: mSwitchInProgress %d, mReconfigurationInProgress %d, "
2080a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang            "mInPreparationPhase %d, mCurBandwidthIndex %zd, mStreamMask 0x%x",
2081964adb17885185808398507d2de88665fe193ee2Chong Zhang        mSwitchInProgress, mReconfigurationInProgress,
2082538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        mInPreparationPhase, mCurBandwidthIndex, mStreamMask);
20830ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
20847c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    bool underflow, ready, down, up;
20857c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    if (checkBuffering(underflow, ready, down, up)) {
20868464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang        if (mInPreparationPhase) {
20878464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            // Allow down switch even if we're still preparing.
20888464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            //
20898464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            // Some streams have a high bandwidth index as default,
20908464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            // when bandwidth is low, it takes a long time to buffer
20918464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            // to ready mark, then it immediately pauses after start
20928464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            // as we have to do a down switch. It's better experience
20938464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            // to restart from a lower index, if we detect low bw.
20948464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            if (!switchBandwidthIfNeeded(false /* up */, down) && ready) {
20958464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang                postPrepared(OK);
20968464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            }
20970ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        }
20980ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
2099538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        if (!mInPreparationPhase) {
21007c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            if (ready) {
21017c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                stopBufferingIfNecessary();
21027c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            } else if (underflow) {
21037c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                startBufferingIfNecessary();
21047c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            }
21057c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            switchBandwidthIfNeeded(up, down);
21068464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang        }
21070ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    }
21080ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
2109964adb17885185808398507d2de88665fe193ee2Chong Zhang    schedulePollBuffering();
21100ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih}
21110ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
21127c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::cancelBandwidthSwitch(bool resume) {
21137c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    ALOGV("cancelBandwidthSwitch: mSwitchGen(%d)++, orig %zd, cur %zd",
21147c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            mSwitchGeneration, mOrigBandwidthIndex, mCurBandwidthIndex);
21157c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    if (!mSwitchInProgress) {
21167c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        return;
21177c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    }
2118f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih
2119f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
2120f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        FetcherInfo& info = mFetcherInfos.editValueAt(i);
2121f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        if (info.mToBeRemoved) {
2122f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            info.mToBeRemoved = false;
21237c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            if (resume) {
21247c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                resumeFetcher(mFetcherInfos.keyAt(i), mSwapMask);
21257c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            }
2126f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        }
2127f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    }
2128f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih
2129f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
21307c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        AString newUri = mStreams[i].mNewUri;
21317c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        if (!newUri.empty()) {
21327c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            // clear all mNewUri matching this newUri
21337c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            for (size_t j = i; j < kMaxStreams; ++j) {
21347c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                if (mStreams[j].mNewUri == newUri) {
21357c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    mStreams[j].mNewUri.clear();
21367c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                }
21377c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            }
21387c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            ALOGV("stopping newUri = %s", newUri.c_str());
21397c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            ssize_t index = mFetcherInfos.indexOfKey(newUri);
21407c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            if (index < 0) {
21417c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                ALOGE("did not find fetcher for newUri: %s", newUri.c_str());
2142f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih                continue;
2143f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            }
21447c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            FetcherInfo &info = mFetcherInfos.editValueAt(index);
21457c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            info.mToBeRemoved = true;
2146f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            info.mFetcher->stopAsync();
2147f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        }
2148f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    }
21497c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
21507c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    ALOGI("#### Canceled Bandwidth Switch: %zd => %zd",
215125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            mOrigBandwidthIndex, mCurBandwidthIndex);
21527c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
21537c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    mSwitchGeneration++;
21547c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    mSwitchInProgress = false;
21557c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    mCurBandwidthIndex = mOrigBandwidthIndex;
21567c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    mSwapMask = 0;
21571543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
21581543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
21597c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangbool LiveSession::checkBuffering(
21607c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        bool &underflow, bool &ready, bool &down, bool &up) {
21617c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    underflow = ready = down = up = false;
2162964adb17885185808398507d2de88665fe193ee2Chong Zhang
21637c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    if (mReconfigurationInProgress) {
2164964adb17885185808398507d2de88665fe193ee2Chong Zhang        ALOGV("Switch/Reconfig in progress, defer buffer polling");
21651543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return false;
21661543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
21671543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
21687c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    size_t activeCount, underflowCount, readyCount, downCount, upCount;
21697c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    activeCount = underflowCount = readyCount = downCount = upCount =0;
21707c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    int32_t minBufferPercent = -1;
21717c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    int64_t durationUs;
21727c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    if (getDuration(&durationUs) != OK) {
21737c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        durationUs = -1;
21747c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    }
2175964adb17885185808398507d2de88665fe193ee2Chong Zhang    for (size_t i = 0; i < mPacketSources.size(); ++i) {
2176964adb17885185808398507d2de88665fe193ee2Chong Zhang        // we don't check subtitles for buffering level
2177964adb17885185808398507d2de88665fe193ee2Chong Zhang        if (!(mStreamMask & mPacketSources.keyAt(i)
2178964adb17885185808398507d2de88665fe193ee2Chong Zhang                & (STREAMTYPE_AUDIO | STREAMTYPE_VIDEO))) {
2179964adb17885185808398507d2de88665fe193ee2Chong Zhang            continue;
2180964adb17885185808398507d2de88665fe193ee2Chong Zhang        }
2181964adb17885185808398507d2de88665fe193ee2Chong Zhang        // ignore streams that never had any packet queued.
2182964adb17885185808398507d2de88665fe193ee2Chong Zhang        // (it's possible that the variant only has audio or video)
2183964adb17885185808398507d2de88665fe193ee2Chong Zhang        sp<AMessage> meta = mPacketSources[i]->getLatestEnqueuedMeta();
2184964adb17885185808398507d2de88665fe193ee2Chong Zhang        if (meta == NULL) {
2185964adb17885185808398507d2de88665fe193ee2Chong Zhang            continue;
2186964adb17885185808398507d2de88665fe193ee2Chong Zhang        }
2187964adb17885185808398507d2de88665fe193ee2Chong Zhang
21880dd229bb306df68b88e7419b3cc11fc6175be1daRobert Shih        status_t finalResult;
2189964adb17885185808398507d2de88665fe193ee2Chong Zhang        int64_t bufferedDurationUs =
21900dd229bb306df68b88e7419b3cc11fc6175be1daRobert Shih                mPacketSources[i]->getBufferedDurationUs(&finalResult);
219125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang        ALOGV("[%s] buffered %lld us",
219225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                getNameForStream(mPacketSources.keyAt(i)),
219325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                (long long)bufferedDurationUs);
21947c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        if (durationUs >= 0) {
21957c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            int32_t percent;
21967c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            if (mPacketSources[i]->isFinished(0 /* duration */)) {
21977c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                percent = 100;
21987c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            } else {
21998464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang                percent = (int32_t)(100.0 *
22008464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang                        (mLastDequeuedTimeUs + bufferedDurationUs) / durationUs);
22017c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            }
22027c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            if (minBufferPercent < 0 || percent < minBufferPercent) {
22037c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                minBufferPercent = percent;
22047c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            }
2205964adb17885185808398507d2de88665fe193ee2Chong Zhang        }
22067c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
22077c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        ++activeCount;
220848fa06d1e80a872c7495804979256e021e566ae0Wei Jia        int64_t readyMarkUs =
220948fa06d1e80a872c7495804979256e021e566ae0Wei Jia            (mInPreparationPhase ?
22109bb3803a80a680ea7a3bc11e07b8a89ccddee003Wei Jia                mBufferingSettings.mInitialMarkMs :
22119bb3803a80a680ea7a3bc11e07b8a89ccddee003Wei Jia                mBufferingSettings.mResumePlaybackMarkMs) * 1000ll;
221248fa06d1e80a872c7495804979256e021e566ae0Wei Jia        if (bufferedDurationUs > readyMarkUs
22137c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                || mPacketSources[i]->isFinished(0)) {
22147c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            ++readyCount;
22157c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        }
22167c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        if (!mPacketSources[i]->isFinished(0)) {
22179bb3803a80a680ea7a3bc11e07b8a89ccddee003Wei Jia            if (bufferedDurationUs < kUnderflowMarkMs * 1000ll) {
22187c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                ++underflowCount;
22197c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            }
22207c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            if (bufferedDurationUs > mUpSwitchMark) {
22217c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                ++upCount;
2222d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            }
2223d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            if (bufferedDurationUs < mDownSwitchMark) {
22247c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                ++downCount;
22257c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            }
22267c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        }
22277c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    }
22287c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
22297c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    if (minBufferPercent >= 0) {
22307c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        notifyBufferingUpdate(minBufferPercent);
223114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
223214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
2233964adb17885185808398507d2de88665fe193ee2Chong Zhang    if (activeCount > 0) {
22347c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        up        = (upCount == activeCount);
22357c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        down      = (downCount > 0);
22367c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        ready     = (readyCount == activeCount);
22377c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        underflow = (underflowCount > 0);
22381543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return true;
22391543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
2240964adb17885185808398507d2de88665fe193ee2Chong Zhang
2241964adb17885185808398507d2de88665fe193ee2Chong Zhang    return false;
22421543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
22431543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
22447c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::startBufferingIfNecessary() {
22457c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    ALOGV("startBufferingIfNecessary: mInPreparationPhase=%d, mBuffering=%d",
22467c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            mInPreparationPhase, mBuffering);
22477c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    if (!mBuffering) {
22487c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        mBuffering = true;
22497c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
22507c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        sp<AMessage> notify = mNotify->dup();
22517c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        notify->setInt32("what", kWhatBufferingStart);
22527c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        notify->post();
22537c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    }
22547c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang}
22557c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
22567c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::stopBufferingIfNecessary() {
22577c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    ALOGV("stopBufferingIfNecessary: mInPreparationPhase=%d, mBuffering=%d",
22587c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            mInPreparationPhase, mBuffering);
22597c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
22607c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    if (mBuffering) {
22617c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        mBuffering = false;
22627c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
22637c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        sp<AMessage> notify = mNotify->dup();
22647c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        notify->setInt32("what", kWhatBufferingEnd);
22657c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        notify->post();
22667c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    }
22677c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang}
22687c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
22697c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::notifyBufferingUpdate(int32_t percentage) {
22707c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    if (percentage < mPrevBufferPercentage) {
22717c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        percentage = mPrevBufferPercentage;
22727c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    } else if (percentage > 100) {
22737c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        percentage = 100;
22747c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    }
22757c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
22767c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    mPrevBufferPercentage = percentage;
22777c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
22787c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    ALOGV("notifyBufferingUpdate: percentage=%d%%", percentage);
22797c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
22807c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    sp<AMessage> notify = mNotify->dup();
22817c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    notify->setInt32("what", kWhatBufferingUpdate);
22827c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    notify->setInt32("percentage", percentage);
22837c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    notify->post();
22847c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang}
22857c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
22865ef659e010e90175eb5282d9642a02f6105189bfChong Zhangbool LiveSession::tryBandwidthFallback() {
22875ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    if (mInPreparationPhase || mReconfigurationInProgress) {
22885ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        // Don't try fallback during prepare or reconfig.
22895ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        // If error happens there, it's likely unrecoverable.
22905ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        return false;
22915ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    }
22925ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    if (mCurBandwidthIndex > mOrigBandwidthIndex) {
22935ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        // if we're switching up, simply cancel and resume old variant
22945ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        cancelBandwidthSwitch(true /* resume */);
22955ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        return true;
22965ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    } else {
22975ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        // if we're switching down, we're likely about to underflow (if
22985ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        // not already underflowing). try the lowest viable bandwidth if
22995ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        // not on that variant already.
23005ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        ssize_t lowestValid = getLowestValidBandwidthIndex();
23015ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        if (mCurBandwidthIndex > lowestValid) {
23025ef659e010e90175eb5282d9642a02f6105189bfChong Zhang            cancelBandwidthSwitch();
23035ef659e010e90175eb5282d9642a02f6105189bfChong Zhang            changeConfiguration(-1ll, lowestValid);
23045ef659e010e90175eb5282d9642a02f6105189bfChong Zhang            return true;
23055ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        }
23065ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    }
23075ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    // return false if we couldn't find any fallback
23085ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    return false;
23095ef659e010e90175eb5282d9642a02f6105189bfChong Zhang}
23105ef659e010e90175eb5282d9642a02f6105189bfChong Zhang
23118464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang/*
23128464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang * returns true if a bandwidth switch is actually needed (and started),
23138464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang * returns false otherwise
23148464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang */
23158464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhangbool LiveSession::switchBandwidthIfNeeded(bool bufferHigh, bool bufferLow) {
2316538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    // no need to check bandwidth if we only have 1 bandwidth settings
23175ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    if (mBandwidthItems.size() < 2) {
23185ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        return false;
23195ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    }
23205ef659e010e90175eb5282d9642a02f6105189bfChong Zhang
23215ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    if (mSwitchInProgress) {
23225ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        if (mBuffering) {
23235ef659e010e90175eb5282d9642a02f6105189bfChong Zhang            tryBandwidthFallback();
23245ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        }
23258464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang        return false;
2326538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    }
2327538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
23285ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    int32_t bandwidthBps, shortTermBps;
2329978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    bool isStable;
23305ef659e010e90175eb5282d9642a02f6105189bfChong Zhang    if (mBandwidthEstimator->estimateBandwidth(
23315ef659e010e90175eb5282d9642a02f6105189bfChong Zhang            &bandwidthBps, &isStable, &shortTermBps)) {
23325ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        ALOGV("bandwidth estimated at %.2f kbps, "
23335ef659e010e90175eb5282d9642a02f6105189bfChong Zhang                "stable %d, shortTermBps %.2f kbps",
23345ef659e010e90175eb5282d9642a02f6105189bfChong Zhang                bandwidthBps / 1024.0f, isStable, shortTermBps / 1024.0f);
2335a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        mLastBandwidthBps = bandwidthBps;
23365ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        mLastBandwidthStable = isStable;
2337538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    } else {
2338538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        ALOGV("no bandwidth estimate.");
23398464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang        return false;
2340538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    }
2341538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
2342538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    int32_t curBandwidth = mBandwidthItems.itemAt(mCurBandwidthIndex).mBandwidth;
2343d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang    // canSwithDown and canSwitchUp can't both be true.
2344d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang    // we only want to switch up when measured bw is 120% higher than current variant,
2345d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang    // and we only want to switch down when measured bw is below current variant.
2346978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    bool canSwitchDown = bufferLow
2347d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            && (bandwidthBps < (int32_t)curBandwidth);
2348d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang    bool canSwitchUp = bufferHigh
2349d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            && (bandwidthBps > (int32_t)curBandwidth * 12 / 10);
2350d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang
2351978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    if (canSwitchDown || canSwitchUp) {
2352978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang        // bandwidth estimating has some delay, if we have to downswitch when
23535ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        // it hasn't stabilized, use the short term to guess real bandwidth,
23545ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        // since it may be dropping too fast.
23555ef659e010e90175eb5282d9642a02f6105189bfChong Zhang        // (note this doesn't apply to upswitch, always use longer average there)
2356978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang        if (!isStable && canSwitchDown) {
23575ef659e010e90175eb5282d9642a02f6105189bfChong Zhang            if (shortTermBps < bandwidthBps) {
23585ef659e010e90175eb5282d9642a02f6105189bfChong Zhang                bandwidthBps = shortTermBps;
23595ef659e010e90175eb5282d9642a02f6105189bfChong Zhang            }
2360978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang        }
2361978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang
2362538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        ssize_t bandwidthIndex = getBandwidthIndex(bandwidthBps);
2363538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
2364d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        // it's possible that we're checking for canSwitchUp case, but the returned
2365d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        // bandwidthIndex is < mCurBandwidthIndex, as getBandwidthIndex() only uses 70%
2366d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        // of measured bw. In that case we don't want to do anything, since we have
2367d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        // both enough buffer and enough bw.
23688464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang        if ((canSwitchUp && bandwidthIndex > mCurBandwidthIndex)
2369978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang         || (canSwitchDown && bandwidthIndex < mCurBandwidthIndex)) {
23708464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            // if not yet prepared, just restart again with new bw index.
23718464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            // this is faster and playback experience is cleaner.
23728464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            changeConfiguration(
23738464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang                    mInPreparationPhase ? 0 : -1ll, bandwidthIndex);
23748464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            return true;
2375538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        }
237614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
23778464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang    return false;
2378a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
2379a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
23807c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::postError(status_t err) {
23817c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    // if we reached EOS, notify buffering of 100%
23827c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    if (err == ERROR_END_OF_STREAM) {
23837c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        notifyBufferingUpdate(100);
23847c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    }
23857c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    // we'll stop buffer polling now, before that notify
23867c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    // stop buffering to stop the spinning icon
23877c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    stopBufferingIfNecessary();
23887c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    cancelPollBuffering();
23897c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
23907c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    sp<AMessage> notify = mNotify->dup();
23917c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    notify->setInt32("what", kWhatError);
23927c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    notify->setInt32("err", err);
23937c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    notify->post();
23947c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang}
23957c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
239614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::postPrepared(status_t err) {
239714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(mInPreparationPhase);
2398a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
239914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> notify = mNotify->dup();
240014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (err == OK || err == ERROR_END_OF_STREAM) {
240114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        notify->setInt32("what", kWhatPrepared);
240214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    } else {
24037c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        cancelPollBuffering();
24047c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
240514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        notify->setInt32("what", kWhatPreparationFailed);
240614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        notify->setInt32("err", err);
240714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
2408a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
240914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->post();
2410a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
241114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mInPreparationPhase = false;
2412b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber}
2413b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
2414964adb17885185808398507d2de88665fe193ee2Chong Zhang
2415a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}  // namespace android
2416a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
2417