LiveSession.cpp revision 8a048338d9291b2db1b3a325fff58cb1aa69f04d
1a44153c1a57202fb538659eb50706e60454d6273Andreas Huber/*
2a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * Copyright (C) 2010 The Android Open Source Project
3a44153c1a57202fb538659eb50706e60454d6273Andreas Huber *
4a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * you may not use this file except in compliance with the License.
6a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * You may obtain a copy of the License at
7a44153c1a57202fb538659eb50706e60454d6273Andreas Huber *
8a44153c1a57202fb538659eb50706e60454d6273Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
9a44153c1a57202fb538659eb50706e60454d6273Andreas Huber *
10a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * Unless required by applicable law or agreed to in writing, software
11a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * See the License for the specific language governing permissions and
14a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * limitations under the License.
15a44153c1a57202fb538659eb50706e60454d6273Andreas Huber */
16a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
17a44153c1a57202fb538659eb50706e60454d6273Andreas Huber//#define LOG_NDEBUG 0
18a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#define LOG_TAG "LiveSession"
19a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <utils/Log.h>
20a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
2114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include "LiveSession.h"
225abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang#include "HTTPDownloader.h"
2314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include "M3UParser.h"
2414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include "PlaylistFetcher.h"
25a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
2614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include "mpeg2ts/AnotherPacketSource.h"
27a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
28a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <cutils/properties.h>
291b86fe063badb5f28c467ade39be0f4008688947Andreas Huber#include <media/IMediaHTTPService.h>
30a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <media/stagefright/foundation/ABuffer.h>
31a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <media/stagefright/foundation/ADebug.h>
32a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <media/stagefright/foundation/AMessage.h>
337c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang#include <media/stagefright/foundation/AUtils.h>
340852843d304006e3ab333081fddda13b07193de8Robert Shih#include <media/stagefright/MediaDefs.h>
3514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include <media/stagefright/MetaData.h>
3614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include <media/stagefright/Utils.h>
37a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
381543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih#include <utils/Mutex.h>
391543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
40a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <ctype.h>
41b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross#include <inttypes.h>
42a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
43a44153c1a57202fb538659eb50706e60454d6273Andreas Hubernamespace android {
44a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
45765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang// static
46765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang// Bandwidth Switch Mark Defaults
47d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhangconst int64_t LiveSession::kUpSwitchMarkUs = 15000000ll;
48d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhangconst int64_t LiveSession::kDownSwitchMarkUs = 20000000ll;
49765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhangconst int64_t LiveSession::kUpSwitchMarginUs = 5000000ll;
50d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhangconst int64_t LiveSession::kResumeThresholdUs = 100000ll;
51765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang
52765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang// Buffer Prepare/Ready/Underflow Marks
53765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhangconst int64_t LiveSession::kReadyMarkUs = 5000000ll;
54765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhangconst int64_t LiveSession::kPrepareMarkUs = 1500000ll;
55765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhangconst int64_t LiveSession::kUnderflowMarkUs = 1000000ll;
56765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang
57538b6d22a3578c0201d48f8548289aa254d81484Chong Zhangstruct LiveSession::BandwidthEstimator : public RefBase {
58538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    BandwidthEstimator();
59538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
60538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    void addBandwidthMeasurement(size_t numBytes, int64_t delayUs);
61978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    bool estimateBandwidth(int32_t *bandwidth, bool *isStable = NULL);
62538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
63538b6d22a3578c0201d48f8548289aa254d81484Chong Zhangprivate:
64538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    // Bandwidth estimation parameters
6581636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang    static const int32_t kMinBandwidthHistoryItems = 20;
6681636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang    static const int64_t kMinBandwidthHistoryWindowUs = 5000000ll; // 5 sec
6781636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang    static const int64_t kMaxBandwidthHistoryWindowUs = 30000000ll; // 30 sec
68538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
69538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    struct BandwidthEntry {
70538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        int64_t mDelayUs;
71538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        size_t mNumBytes;
72538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    };
73538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
74538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    Mutex mLock;
75538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    List<BandwidthEntry> mBandwidthHistory;
76978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    List<int32_t> mPrevEstimates;
77978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    bool mHasNewSample;
78978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    bool mIsStable;
79538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    int64_t mTotalTransferTimeUs;
80538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    size_t mTotalTransferBytes;
81538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
82538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    DISALLOW_EVIL_CONSTRUCTORS(BandwidthEstimator);
83538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang};
84538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
85538b6d22a3578c0201d48f8548289aa254d81484Chong ZhangLiveSession::BandwidthEstimator::BandwidthEstimator() :
86978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    mHasNewSample(false),
87978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    mIsStable(true),
88538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    mTotalTransferTimeUs(0),
89538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    mTotalTransferBytes(0) {
90538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang}
91538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
92538b6d22a3578c0201d48f8548289aa254d81484Chong Zhangvoid LiveSession::BandwidthEstimator::addBandwidthMeasurement(
93538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        size_t numBytes, int64_t delayUs) {
94538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    AutoMutex autoLock(mLock);
95538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
96538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    BandwidthEntry entry;
97538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    entry.mDelayUs = delayUs;
98538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    entry.mNumBytes = numBytes;
99538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    mTotalTransferTimeUs += delayUs;
100538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    mTotalTransferBytes += numBytes;
101538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    mBandwidthHistory.push_back(entry);
102978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    mHasNewSample = true;
103538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
10481636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang    // Remove no more than 10% of total transfer time at a time
10581636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang    // to avoid sudden jump on bandwidth estimation. There might
10681636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang    // be long blocking reads that takes up signification time,
10781636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang    // we have to keep a longer window in that case.
10881636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang    int64_t bandwidthHistoryWindowUs = mTotalTransferTimeUs * 9 / 10;
10981636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang    if (bandwidthHistoryWindowUs < kMinBandwidthHistoryWindowUs) {
11081636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang        bandwidthHistoryWindowUs = kMinBandwidthHistoryWindowUs;
11181636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang    } else if (bandwidthHistoryWindowUs > kMaxBandwidthHistoryWindowUs) {
11281636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang        bandwidthHistoryWindowUs = kMaxBandwidthHistoryWindowUs;
11381636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang    }
114538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    // trim old samples, keeping at least kMaxBandwidthHistoryItems samples,
115538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    // and total transfer time at least kMaxBandwidthHistoryWindowUs.
11681636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang    while (mBandwidthHistory.size() > kMinBandwidthHistoryItems) {
117538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        List<BandwidthEntry>::iterator it = mBandwidthHistory.begin();
11881636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang        if (mTotalTransferTimeUs - it->mDelayUs < bandwidthHistoryWindowUs) {
119538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang            break;
120538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        }
121538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        mTotalTransferTimeUs -= it->mDelayUs;
122538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        mTotalTransferBytes -= it->mNumBytes;
123538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        mBandwidthHistory.erase(mBandwidthHistory.begin());
124538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    }
125538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang}
126538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
12781636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhangbool LiveSession::BandwidthEstimator::estimateBandwidth(
12881636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang        int32_t *bandwidthBps, bool *isStable) {
129538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    AutoMutex autoLock(mLock);
130538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
131538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    if (mBandwidthHistory.size() < 2) {
132538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        return false;
133538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    }
134538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
135978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    if (!mHasNewSample) {
136978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang        *bandwidthBps = *(--mPrevEstimates.end());
137978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang        if (isStable) {
138978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang            *isStable = mIsStable;
139978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang        }
140978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang        return true;
141978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    }
142978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang
143538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    *bandwidthBps = ((double)mTotalTransferBytes * 8E6 / mTotalTransferTimeUs);
144978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    mPrevEstimates.push_back(*bandwidthBps);
145978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    while (mPrevEstimates.size() > 3) {
146978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang        mPrevEstimates.erase(mPrevEstimates.begin());
147978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    }
148978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    mHasNewSample = false;
149978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang
150978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    int32_t minEstimate = -1, maxEstimate = -1;
151978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    List<int32_t>::iterator it;
152978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    for (it = mPrevEstimates.begin(); it != mPrevEstimates.end(); it++) {
153978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang        int32_t estimate = *it;
154978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang        if (minEstimate < 0 || minEstimate > estimate) {
155978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang            minEstimate = estimate;
156978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang        }
157978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang        if (maxEstimate < 0 || maxEstimate < estimate) {
158978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang            maxEstimate = estimate;
159978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang        }
160978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    }
161978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    mIsStable = (maxEstimate <= minEstimate * 4 / 3);
162978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    if (isStable) {
163978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang       *isStable = mIsStable;
164978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    }
16581636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang#if 0
16681636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang    {
16781636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang        char dumpStr[1024] = {0};
16881636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang        size_t itemIdx = 0;
16981636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang        size_t histSize = mBandwidthHistory.size();
17081636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang        sprintf(dumpStr, "estimate bps=%d stable=%d history (n=%d): {",
17181636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang            *bandwidthBps, mIsStable, histSize);
17281636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang        List<BandwidthEntry>::iterator it = mBandwidthHistory.begin();
17381636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang        for (; it != mBandwidthHistory.end(); ++it) {
17481636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang            if (itemIdx > 50) {
17581636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang                sprintf(dumpStr + strlen(dumpStr),
17681636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang                        "...(%zd more items)... }", histSize - itemIdx);
17781636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang                break;
17881636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang            }
17981636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang            sprintf(dumpStr + strlen(dumpStr), "%dk/%.3fs%s",
18081636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang                it->mNumBytes / 1024,
18181636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang                (double)it->mDelayUs * 1.0e-6,
18281636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang                (it == (--mBandwidthHistory.end())) ? "}" : ", ");
18381636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang            itemIdx++;
18481636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang        }
18581636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang        ALOGE(dumpStr);
18681636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang    }
18781636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang#endif
188538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    return true;
189538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang}
190538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
1917c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang//static
1927c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangconst char *LiveSession::getKeyForStream(StreamType type) {
1937c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    switch (type) {
1947c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        case STREAMTYPE_VIDEO:
1957c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            return "timeUsVideo";
1967c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        case STREAMTYPE_AUDIO:
1977c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            return "timeUsAudio";
1987c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        case STREAMTYPE_SUBTITLES:
1997c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            return "timeUsSubtitle";
2000852843d304006e3ab333081fddda13b07193de8Robert Shih        case STREAMTYPE_METADATA:
2010852843d304006e3ab333081fddda13b07193de8Robert Shih            return "timeUsMetadata"; // unused
2027c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        default:
2037c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            TRESPASS();
2047c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    }
2057c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    return NULL;
2067c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang}
2077c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
20825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang//static
20925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhangconst char *LiveSession::getNameForStream(StreamType type) {
21025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    switch (type) {
21125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang        case STREAMTYPE_VIDEO:
21225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            return "video";
21325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang        case STREAMTYPE_AUDIO:
21425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            return "audio";
21525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang        case STREAMTYPE_SUBTITLES:
21625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            return "subs";
2170852843d304006e3ab333081fddda13b07193de8Robert Shih        case STREAMTYPE_METADATA:
2180852843d304006e3ab333081fddda13b07193de8Robert Shih            return "metadata";
21925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang        default:
22025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            break;
22125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    }
22225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    return "unknown";
22325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang}
22425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang
2250852843d304006e3ab333081fddda13b07193de8Robert Shih//static
2260852843d304006e3ab333081fddda13b07193de8Robert ShihATSParser::SourceType LiveSession::getSourceTypeForStream(StreamType type) {
2270852843d304006e3ab333081fddda13b07193de8Robert Shih    switch (type) {
2280852843d304006e3ab333081fddda13b07193de8Robert Shih        case STREAMTYPE_VIDEO:
2290852843d304006e3ab333081fddda13b07193de8Robert Shih            return ATSParser::VIDEO;
2300852843d304006e3ab333081fddda13b07193de8Robert Shih        case STREAMTYPE_AUDIO:
2310852843d304006e3ab333081fddda13b07193de8Robert Shih            return ATSParser::AUDIO;
2320852843d304006e3ab333081fddda13b07193de8Robert Shih        case STREAMTYPE_METADATA:
2330852843d304006e3ab333081fddda13b07193de8Robert Shih            return ATSParser::META;
2340852843d304006e3ab333081fddda13b07193de8Robert Shih        case STREAMTYPE_SUBTITLES:
2350852843d304006e3ab333081fddda13b07193de8Robert Shih        default:
2360852843d304006e3ab333081fddda13b07193de8Robert Shih            TRESPASS();
2370852843d304006e3ab333081fddda13b07193de8Robert Shih    }
2380852843d304006e3ab333081fddda13b07193de8Robert Shih    return ATSParser::NUM_SOURCE_TYPES; // should not reach here
2390852843d304006e3ab333081fddda13b07193de8Robert Shih}
2400852843d304006e3ab333081fddda13b07193de8Robert Shih
2410df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas HuberLiveSession::LiveSession(
2421b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        const sp<AMessage> &notify, uint32_t flags,
24381e68448f3361eaf8618930471fdc3c21bdf5cbcAndreas Huber        const sp<IMediaHTTPService> &httpService)
2440df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas Huber    : mNotify(notify),
2450df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas Huber      mFlags(flags),
2461b86fe063badb5f28c467ade39be0f4008688947Andreas Huber      mHTTPService(httpService),
2477c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang      mBuffering(false),
2480df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas Huber      mInPreparationPhase(true),
2497c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang      mPollBufferingGeneration(0),
2507c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang      mPrevBufferPercentage(-1),
251309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih      mCurBandwidthIndex(-1),
2527c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang      mOrigBandwidthIndex(-1),
253a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang      mLastBandwidthBps(-1ll),
254538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang      mBandwidthEstimator(new BandwidthEstimator()),
255a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang      mMaxWidth(720),
256a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang      mMaxHeight(480),
25714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber      mStreamMask(0),
2581543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih      mNewStreamMask(0),
2591543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih      mSwapMask(0),
2601543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih      mSwitchGeneration(0),
261b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih      mSubtitleGeneration(0),
26214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber      mLastDequeuedTimeUs(0ll),
263dcb89b3b505522efde173c105a851c412f947178Chong Zhang      mRealTimeBaseUs(0ll),
26414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber      mReconfigurationInProgress(false),
2651543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih      mSwitchInProgress(false),
266765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang      mUpSwitchMark(kUpSwitchMarkUs),
267765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang      mDownSwitchMark(kDownSwitchMarkUs),
268765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang      mUpSwitchMargin(kUpSwitchMarginUs),
269309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih      mFirstTimeUsValid(false),
270309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih      mFirstTimeUs(0),
2710852843d304006e3ab333081fddda13b07193de8Robert Shih      mLastSeekTimeUs(0),
2720852843d304006e3ab333081fddda13b07193de8Robert Shih      mHasMetadata(false) {
2738ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    mStreams[kAudioIndex] = StreamItem("audio");
2748ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    mStreams[kVideoIndex] = StreamItem("video");
275e4f25c280a8f1655c31a745978e0fcbc61f91deeRobert Shih    mStreams[kSubtitleIndex] = StreamItem("subtitles");
27614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
2770852843d304006e3ab333081fddda13b07193de8Robert Shih    for (size_t i = 0; i < kNumSources; ++i) {
2788ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        mPacketSources.add(indexToType(i), new AnotherPacketSource(NULL /* meta */));
2791543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        mPacketSources2.add(indexToType(i), new AnotherPacketSource(NULL /* meta */));
2808ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    }
281a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
282a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
283a44153c1a57202fb538659eb50706e60454d6273Andreas HuberLiveSession::~LiveSession() {
284964adb17885185808398507d2de88665fe193ee2Chong Zhang    if (mFetcherLooper != NULL) {
285964adb17885185808398507d2de88665fe193ee2Chong Zhang        mFetcherLooper->stop();
286964adb17885185808398507d2de88665fe193ee2Chong Zhang    }
287a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
288a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
2890852843d304006e3ab333081fddda13b07193de8Robert Shihint64_t LiveSession::calculateMediaTimeUs(
2900852843d304006e3ab333081fddda13b07193de8Robert Shih        int64_t firstTimeUs, int64_t timeUs, int32_t discontinuitySeq) {
2910852843d304006e3ab333081fddda13b07193de8Robert Shih    if (timeUs >= firstTimeUs) {
2920852843d304006e3ab333081fddda13b07193de8Robert Shih        timeUs -= firstTimeUs;
2930852843d304006e3ab333081fddda13b07193de8Robert Shih    } else {
2940852843d304006e3ab333081fddda13b07193de8Robert Shih        timeUs = 0;
2950852843d304006e3ab333081fddda13b07193de8Robert Shih    }
2960852843d304006e3ab333081fddda13b07193de8Robert Shih    timeUs += mLastSeekTimeUs;
2970852843d304006e3ab333081fddda13b07193de8Robert Shih    if (mDiscontinuityOffsetTimesUs.indexOfKey(discontinuitySeq) >= 0) {
2980852843d304006e3ab333081fddda13b07193de8Robert Shih        timeUs += mDiscontinuityOffsetTimesUs.valueFor(discontinuitySeq);
2990852843d304006e3ab333081fddda13b07193de8Robert Shih    }
3000852843d304006e3ab333081fddda13b07193de8Robert Shih    return timeUs;
3010852843d304006e3ab333081fddda13b07193de8Robert Shih}
3020852843d304006e3ab333081fddda13b07193de8Robert Shih
30314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::dequeueAccessUnit(
30414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        StreamType stream, sp<ABuffer> *accessUnit) {
305964adb17885185808398507d2de88665fe193ee2Chong Zhang    status_t finalResult = OK;
30614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AnotherPacketSource> packetSource = mPacketSources.valueFor(stream);
30714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
30825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    ssize_t streamIdx = typeToIndex(stream);
30925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    if (streamIdx < 0) {
3105abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang        return BAD_VALUE;
31125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    }
31225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    const char *streamStr = getNameForStream(stream);
313a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    // Do not let client pull data if we don't have data packets yet.
314a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    // We might only have a format discontinuity queued without data.
315a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    // When NuPlayerDecoder dequeues the format discontinuity, it will
316a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    // immediately try to getFormat. If we return NULL, NuPlayerDecoder
317a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    // thinks it can do seamless change, so will not shutdown decoder.
318a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    // When the actual format arrives, it can't handle it and get stuck.
319a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    if (!packetSource->hasDataBufferAvailable(&finalResult)) {
32025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang        ALOGV("[%s] dequeueAccessUnit: no buffer available (finalResult=%d)",
32125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                streamStr, finalResult);
32225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang
323f69c996864844e8f669308af8412cede043062a2Robert Shih        if (finalResult == OK) {
324f69c996864844e8f669308af8412cede043062a2Robert Shih            return -EAGAIN;
325f69c996864844e8f669308af8412cede043062a2Robert Shih        } else {
326f69c996864844e8f669308af8412cede043062a2Robert Shih            return finalResult;
327f69c996864844e8f669308af8412cede043062a2Robert Shih        }
328f69c996864844e8f669308af8412cede043062a2Robert Shih    }
329f69c996864844e8f669308af8412cede043062a2Robert Shih
330a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    // Let the client dequeue as long as we have buffers available
331a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    // Do not make pause/resume decisions here.
332309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
33314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    status_t err = packetSource->dequeueAccessUnit(accessUnit);
33414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
33514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (err == INFO_DISCONTINUITY) {
336309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        // adaptive streaming, discontinuities in the playlist
33714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        int32_t type;
33814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        CHECK((*accessUnit)->meta()->findInt32("discontinuity", &type));
33914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
34014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        sp<AMessage> extra;
34114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (!(*accessUnit)->meta()->findMessage("extra", &extra)) {
34214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            extra.clear();
34314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
34414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
34514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        ALOGI("[%s] read discontinuity of type %d, extra = %s",
34614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber              streamStr,
34714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber              type,
34814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber              extra == NULL ? "NULL" : extra->debugString().c_str());
34914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    } else if (err == OK) {
350309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
351dcb89b3b505522efde173c105a851c412f947178Chong Zhang        if (stream == STREAMTYPE_AUDIO || stream == STREAMTYPE_VIDEO) {
35225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            int64_t timeUs, originalTimeUs;
353309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            int32_t discontinuitySeq = 0;
3540852843d304006e3ab333081fddda13b07193de8Robert Shih            StreamItem& strm = mStreams[streamIdx];
355dcb89b3b505522efde173c105a851c412f947178Chong Zhang            CHECK((*accessUnit)->meta()->findInt64("timeUs",  &timeUs));
35625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            originalTimeUs = timeUs;
357309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            (*accessUnit)->meta()->findInt32("discontinuitySeq", &discontinuitySeq);
3587c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            if (discontinuitySeq > (int32_t) strm.mCurDiscontinuitySeq) {
3597c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                int64_t offsetTimeUs;
3607c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                if (mDiscontinuityOffsetTimesUs.indexOfKey(strm.mCurDiscontinuitySeq) >= 0) {
3617c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    offsetTimeUs = mDiscontinuityOffsetTimesUs.valueFor(strm.mCurDiscontinuitySeq);
3627c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                } else {
3637c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    offsetTimeUs = 0;
3647c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                }
3657c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
36681636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang                if (mDiscontinuityAbsStartTimesUs.indexOfKey(strm.mCurDiscontinuitySeq) >= 0
36781636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang                        && strm.mLastDequeuedTimeUs >= 0) {
3687c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    int64_t firstTimeUs;
3697c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    firstTimeUs = mDiscontinuityAbsStartTimesUs.valueFor(strm.mCurDiscontinuitySeq);
3707c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    offsetTimeUs += strm.mLastDequeuedTimeUs - firstTimeUs;
3717c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    offsetTimeUs += strm.mLastSampleDurationUs;
3727c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                } else {
3737c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    offsetTimeUs += strm.mLastSampleDurationUs;
3747c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                }
3757c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
3767c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                mDiscontinuityOffsetTimesUs.add(discontinuitySeq, offsetTimeUs);
3777c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                strm.mCurDiscontinuitySeq = discontinuitySeq;
3787c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            }
379309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
380309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            int32_t discard = 0;
381309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            int64_t firstTimeUs;
382309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            if (mDiscontinuityAbsStartTimesUs.indexOfKey(strm.mCurDiscontinuitySeq) >= 0) {
383309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                int64_t durUs; // approximate sample duration
384309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                if (timeUs > strm.mLastDequeuedTimeUs) {
385309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    durUs = timeUs - strm.mLastDequeuedTimeUs;
386309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                } else {
387309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    durUs = strm.mLastDequeuedTimeUs - timeUs;
388309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                }
389309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                strm.mLastSampleDurationUs = durUs;
390309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                firstTimeUs = mDiscontinuityAbsStartTimesUs.valueFor(strm.mCurDiscontinuitySeq);
391309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            } else if ((*accessUnit)->meta()->findInt32("discard", &discard) && discard) {
392309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                firstTimeUs = timeUs;
393309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            } else {
394309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                mDiscontinuityAbsStartTimesUs.add(strm.mCurDiscontinuitySeq, timeUs);
395309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                firstTimeUs = timeUs;
396309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            }
397309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
398309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            strm.mLastDequeuedTimeUs = timeUs;
3990852843d304006e3ab333081fddda13b07193de8Robert Shih            timeUs = calculateMediaTimeUs(firstTimeUs, timeUs, discontinuitySeq);
400dcb89b3b505522efde173c105a851c412f947178Chong Zhang
40125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            ALOGV("[%s] dequeueAccessUnit: time %lld us, original %lld us",
40225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                    streamStr, (long long)timeUs, (long long)originalTimeUs);
403309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            (*accessUnit)->meta()->setInt64("timeUs",  timeUs);
404dcb89b3b505522efde173c105a851c412f947178Chong Zhang            mLastDequeuedTimeUs = timeUs;
405dcb89b3b505522efde173c105a851c412f947178Chong Zhang            mRealTimeBaseUs = ALooper::GetNowUs() - timeUs;
406dcb89b3b505522efde173c105a851c412f947178Chong Zhang        } else if (stream == STREAMTYPE_SUBTITLES) {
407b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih            int32_t subtitleGeneration;
408b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih            if ((*accessUnit)->meta()->findInt32("subtitleGeneration", &subtitleGeneration)
409b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih                    && subtitleGeneration != mSubtitleGeneration) {
410b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih               return -EAGAIN;
411b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih            };
412dcb89b3b505522efde173c105a851c412f947178Chong Zhang            (*accessUnit)->meta()->setInt32(
413dcb89b3b505522efde173c105a851c412f947178Chong Zhang                    "trackIndex", mPlaylist->getSelectedIndex());
414dcb89b3b505522efde173c105a851c412f947178Chong Zhang            (*accessUnit)->meta()->setInt64("baseUs", mRealTimeBaseUs);
4150852843d304006e3ab333081fddda13b07193de8Robert Shih        } else if (stream == STREAMTYPE_METADATA) {
4160852843d304006e3ab333081fddda13b07193de8Robert Shih            HLSTime mdTime((*accessUnit)->meta());
4170852843d304006e3ab333081fddda13b07193de8Robert Shih            if (mDiscontinuityAbsStartTimesUs.indexOfKey(mdTime.mSeq) < 0) {
4180852843d304006e3ab333081fddda13b07193de8Robert Shih                packetSource->requeueAccessUnit((*accessUnit));
4190852843d304006e3ab333081fddda13b07193de8Robert Shih                return -EAGAIN;
4200852843d304006e3ab333081fddda13b07193de8Robert Shih            } else {
4210852843d304006e3ab333081fddda13b07193de8Robert Shih                int64_t firstTimeUs = mDiscontinuityAbsStartTimesUs.valueFor(mdTime.mSeq);
4220852843d304006e3ab333081fddda13b07193de8Robert Shih                int64_t timeUs = calculateMediaTimeUs(firstTimeUs, mdTime.mTimeUs, mdTime.mSeq);
4230852843d304006e3ab333081fddda13b07193de8Robert Shih                (*accessUnit)->meta()->setInt64("timeUs",  timeUs);
4240852843d304006e3ab333081fddda13b07193de8Robert Shih                (*accessUnit)->meta()->setInt64("baseUs", mRealTimeBaseUs);
4250852843d304006e3ab333081fddda13b07193de8Robert Shih            }
426dcb89b3b505522efde173c105a851c412f947178Chong Zhang        }
42714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    } else {
42814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        ALOGI("[%s] encountered error %d", streamStr, err);
42914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
43014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
43114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return err;
43214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
43314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
43414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::getStreamFormat(StreamType stream, sp<AMessage> *format) {
43514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (!(mStreamMask & stream)) {
43614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        return UNKNOWN_ERROR;
43714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
43814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
43914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AnotherPacketSource> packetSource = mPacketSources.valueFor(stream);
44014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
44114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<MetaData> meta = packetSource->getFormat();
44214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
44314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (meta == NULL) {
44414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        return -EAGAIN;
44514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
44614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
4477c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    if (stream == STREAMTYPE_AUDIO) {
4487c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // set AAC input buffer size to 32K bytes (256kbps x 1sec)
4497c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        meta->setInt32(kKeyMaxInputSize, 32 * 1024);
450a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang    } else if (stream == STREAMTYPE_VIDEO) {
451a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang        meta->setInt32(kKeyMaxWidth, mMaxWidth);
452a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang        meta->setInt32(kKeyMaxHeight, mMaxHeight);
4537c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    }
4547c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
45514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return convertMetaDataToMessage(meta, format);
456a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
457a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
4585abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhangsp<HTTPDownloader> LiveSession::getHTTPDownloader() {
4595abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    return new HTTPDownloader(mHTTPService, mExtraHeaders);
460a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang}
461a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
46214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::connectAsync(
463ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        const char *url, const KeyedVector<String8, String8> *headers) {
4641d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatConnect, this);
465a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    msg->setString("url", url);
466ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber
467ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    if (headers != NULL) {
468ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        msg->setPointer(
469ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber                "headers",
470ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber                new KeyedVector<String8, String8>(*headers));
471ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    }
472ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber
473a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    msg->post();
474a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
475a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
47614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::disconnect() {
4771d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatDisconnect, this);
478ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
47914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> response;
48014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    status_t err = msg->postAndAwaitResponse(&response);
481ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
48214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return err;
483a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
484a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
48514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::seekTo(int64_t timeUs) {
4861d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatSeek, this);
487a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    msg->setInt64("timeUs", timeUs);
488a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
48914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> response;
49014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    status_t err = msg->postAndAwaitResponse(&response);
49114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
49214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return err;
493a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
494a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
4957c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangbool LiveSession::checkSwitchProgress(
4967c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        sp<AMessage> &stopParams, int64_t delayUs, bool *needResumeUntil) {
4977c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    AString newUri;
4987c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    CHECK(stopParams->findString("uri", &newUri));
4997c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
5007c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    *needResumeUntil = false;
5017c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    sp<AMessage> firstNewMeta[kMaxStreams];
5027c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    for (size_t i = 0; i < kMaxStreams; ++i) {
5037c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        StreamType stream = indexToType(i);
5047c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        if (!(mSwapMask & mNewStreamMask & stream)
5057c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            || (mStreams[i].mNewUri != newUri)) {
5067c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            continue;
5077c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        }
5087c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        if (stream == STREAMTYPE_SUBTITLES) {
5097c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            continue;
5107c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        }
5117c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        sp<AnotherPacketSource> &source = mPacketSources.editValueAt(i);
5127c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
5137c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // First, get latest dequeued meta, which is where the decoder is at.
5147c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // (when upswitching, we take the meta after a certain delay, so that
5157c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // the decoder is left with some cushion)
5167c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        sp<AMessage> lastDequeueMeta, lastEnqueueMeta;
5177c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        if (delayUs > 0) {
5187c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            lastDequeueMeta = source->getMetaAfterLastDequeued(delayUs);
519d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            if (lastDequeueMeta == NULL) {
520d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                // this means we don't have enough cushion, try again later
521d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                ALOGV("[%s] up switching failed due to insufficient buffer",
52225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                        getNameForStream(stream));
523d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                return false;
524d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            }
5257c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        } else {
526d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            // It's okay for lastDequeueMeta to be NULL here, it means the
527d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            // decoder hasn't even started dequeueing
5287c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            lastDequeueMeta = source->getLatestDequeuedMeta();
5297c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        }
5307c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // Then, trim off packets at beginning of mPacketSources2 that's before
5317c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // the latest dequeued time. These samples are definitely too late.
532d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        firstNewMeta[i] = mPacketSources2.editValueAt(i)
533d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                            ->trimBuffersBeforeMeta(lastDequeueMeta);
534d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang
5357c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // Now firstNewMeta[i] is the first sample after the trim.
5367c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // If it's NULL, we failed because dequeue already past all samples
5377c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // in mPacketSource2, we have to try again.
5387c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        if (firstNewMeta[i] == NULL) {
539d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            HLSTime dequeueTime(lastDequeueMeta);
5407c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            ALOGV("[%s] dequeue time (%d, %lld) past start time",
54125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                    getNameForStream(stream),
542d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                    dequeueTime.mSeq, (long long) dequeueTime.mTimeUs);
5437c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            return false;
5447c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        }
5457c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
5467c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // Otherwise, we check if mPacketSources2 overlaps with what old fetcher
5477c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // already fetched, and see if we need to resumeUntil
5487c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        lastEnqueueMeta = source->getLatestEnqueuedMeta();
5497c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // lastEnqueueMeta == NULL means old fetcher stopped at a discontinuity
5507c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // boundary, no need to resume as the content will look different anyways
5517c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        if (lastEnqueueMeta != NULL) {
552d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            HLSTime lastTime(lastEnqueueMeta), startTime(firstNewMeta[i]);
5537c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
5547c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            // no need to resume old fetcher if new fetcher started in different
5557c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            // discontinuity sequence, as the content will look different.
556d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            *needResumeUntil |= (startTime.mSeq == lastTime.mSeq
557d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                    && startTime.mTimeUs - lastTime.mTimeUs > kResumeThresholdUs);
5587c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
559d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            // update the stopTime for resumeUntil
560d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            stopParams->setInt32("discontinuitySeq", startTime.mSeq);
561d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            stopParams->setInt64(getKeyForStream(stream), startTime.mTimeUs);
5627c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        }
5637c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    }
5647c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
5657c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    // if we're here, it means dequeue progress hasn't passed some samples in
5667c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    // mPacketSource2, we can trim off the excess in mPacketSource.
5677c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    // (old fetcher might still need to resumeUntil the start time of new fetcher)
5687c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    for (size_t i = 0; i < kMaxStreams; ++i) {
5697c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        StreamType stream = indexToType(i);
5707c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        if (!(mSwapMask & mNewStreamMask & stream)
571d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            || (newUri != mStreams[i].mNewUri)
572d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            || stream == STREAMTYPE_SUBTITLES) {
5737c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            continue;
5747c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        }
575d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        mPacketSources.valueFor(stream)->trimBuffersAfterMeta(firstNewMeta[i]);
5767c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    }
5777c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
5787c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    // no resumeUntil if already underflow
5797c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    *needResumeUntil &= !mBuffering;
5807c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
5817c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    return true;
5827c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang}
5837c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
584a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onMessageReceived(const sp<AMessage> &msg) {
585a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    switch (msg->what()) {
586a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        case kWhatConnect:
58714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
588a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            onConnect(msg);
589a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
59014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
591a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
592a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        case kWhatDisconnect:
59314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
59414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            CHECK(msg->senderAwaitsResponse(&mDisconnectReplyID));
59514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
59614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            if (mReconfigurationInProgress) {
59714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                break;
59814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            }
59914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
60014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            finishDisconnect();
601a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
60214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
603a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
60414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case kWhatSeek:
60514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
606a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar            if (mReconfigurationInProgress) {
607800599cdd50737de1cde483a34b39923750b0658Robert Shih                msg->post(50000);
608a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar                break;
609800599cdd50737de1cde483a34b39923750b0658Robert Shih            }
610a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar
611a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar            CHECK(msg->senderAwaitsResponse(&mSeekReplyID));
612a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar            mSeekReply = new AMessage;
613a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar
614a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar            onSeek(msg);
61514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            break;
61614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
61714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
61814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case kWhatFetcherNotify:
61914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
62014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            int32_t what;
62114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            CHECK(msg->findInt32("what", &what));
62214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
62314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            switch (what) {
62414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                case PlaylistFetcher::kWhatStarted:
62514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    break;
62614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                case PlaylistFetcher::kWhatPaused:
62714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                case PlaylistFetcher::kWhatStopped:
62814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                {
629a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                    AString uri;
630a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                    CHECK(msg->findString("uri", &uri));
631a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                    ssize_t index = mFetcherInfos.indexOfKey(uri);
632a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                    if (index < 0) {
633a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                        // ignore msgs from fetchers that's already gone
634a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                        break;
635a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                    }
636a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
63725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                    ALOGV("fetcher-%d %s",
63825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                            mFetcherInfos[index].mFetcher->getFetcherID(),
63925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                            what == PlaylistFetcher::kWhatPaused ?
64025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                                    "paused" : "stopped");
64125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang
64214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    if (what == PlaylistFetcher::kWhatStopped) {
643964adb17885185808398507d2de88665fe193ee2Chong Zhang                        mFetcherLooper->unregisterHandler(
644964adb17885185808398507d2de88665fe193ee2Chong Zhang                                mFetcherInfos[index].mFetcher->id());
645964adb17885185808398507d2de88665fe193ee2Chong Zhang                        mFetcherInfos.removeItemsAt(index);
646a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                    } else if (what == PlaylistFetcher::kWhatPaused) {
647a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                        int32_t seekMode;
648a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                        CHECK(msg->findInt32("seekMode", &seekMode));
649a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                        for (size_t i = 0; i < kMaxStreams; ++i) {
650a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                            if (mStreams[i].mUri == uri) {
651a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                                mStreams[i].mSeekMode = (SeekMode) seekMode;
652a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                            }
653309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        }
65414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    }
65514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
65614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    if (mContinuation != NULL) {
65714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        CHECK_GT(mContinuationCounter, 0);
65814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        if (--mContinuationCounter == 0) {
65914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                            mContinuation->post();
66014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        }
66125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                        ALOGV("%zu fetcher(s) left", mContinuationCounter);
66214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    }
66314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    break;
66414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                }
66514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
66614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                case PlaylistFetcher::kWhatDurationUpdate:
66714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                {
66814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    AString uri;
66914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    CHECK(msg->findString("uri", &uri));
67014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
67114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    int64_t durationUs;
67214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    CHECK(msg->findInt64("durationUs", &durationUs));
67314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
674964adb17885185808398507d2de88665fe193ee2Chong Zhang                    ssize_t index = mFetcherInfos.indexOfKey(uri);
675964adb17885185808398507d2de88665fe193ee2Chong Zhang                    if (index >= 0) {
676964adb17885185808398507d2de88665fe193ee2Chong Zhang                        FetcherInfo *info = &mFetcherInfos.editValueFor(uri);
677964adb17885185808398507d2de88665fe193ee2Chong Zhang                        info->mDurationUs = durationUs;
678964adb17885185808398507d2de88665fe193ee2Chong Zhang                    }
67914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    break;
68014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                }
68114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
6827c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                case PlaylistFetcher::kWhatTargetDurationUpdate:
6837c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                {
6847c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    int64_t targetDurationUs;
6857c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    CHECK(msg->findInt64("targetDurationUs", &targetDurationUs));
686d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                    mUpSwitchMark = min(kUpSwitchMarkUs, targetDurationUs * 7 / 4);
687765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang                    mDownSwitchMark = min(kDownSwitchMarkUs, targetDurationUs * 9 / 4);
688765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang                    mUpSwitchMargin = min(kUpSwitchMarginUs, targetDurationUs);
6897c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    break;
6907c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                }
6917c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
69214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                case PlaylistFetcher::kWhatError:
69314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                {
69414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    status_t err;
69514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    CHECK(msg->findInt32("err", &err));
69614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
69714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    ALOGE("XXX Received error %d from PlaylistFetcher.", err);
69814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
69915f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                    // handle EOS on subtitle tracks independently
70015f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                    AString uri;
70115f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                    if (err == ERROR_END_OF_STREAM && msg->findString("uri", &uri)) {
70215f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                        ssize_t i = mFetcherInfos.indexOfKey(uri);
70315f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                        if (i >= 0) {
70415f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                            const sp<PlaylistFetcher> &fetcher = mFetcherInfos.valueAt(i).mFetcher;
70515f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                            if (fetcher != NULL) {
70615f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                                uint32_t type = fetcher->getStreamTypeMask();
70715f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                                if (type == STREAMTYPE_SUBTITLES) {
70815f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                                    mPacketSources.valueFor(
70915f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                                            STREAMTYPE_SUBTITLES)->signalEOS(err);;
71015f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                                    break;
71115f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                                }
71215f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                            }
71315f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                        }
71415f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                    }
71515f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih
71614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    if (mInPreparationPhase) {
71714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        postPrepared(err);
71814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    }
71914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
7201543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    cancelBandwidthSwitch();
7211543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
72214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    mPacketSources.valueFor(STREAMTYPE_AUDIO)->signalEOS(err);
72314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
72414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    mPacketSources.valueFor(STREAMTYPE_VIDEO)->signalEOS(err);
72514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
72614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    mPacketSources.valueFor(
72714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                            STREAMTYPE_SUBTITLES)->signalEOS(err);
72814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
7297c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    postError(err);
7307c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    break;
7317c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                }
7327c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
7337c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                case PlaylistFetcher::kWhatStopReached:
7347c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                {
7357c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    ALOGV("kWhatStopReached");
7367c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
737d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                    AString oldUri;
738d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                    CHECK(msg->findString("uri", &oldUri));
7397c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
740d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                    ssize_t index = mFetcherInfos.indexOfKey(oldUri);
7417c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    if (index < 0) {
7427c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                        break;
7437c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    }
7447c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
745d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                    tryToFinishBandwidthSwitch(oldUri);
74614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    break;
74714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                }
74814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
7491543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                case PlaylistFetcher::kWhatStartedAt:
7501543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                {
7511543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    int32_t switchGeneration;
7521543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    CHECK(msg->findInt32("switchGeneration", &switchGeneration));
7531543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
75425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                    ALOGV("kWhatStartedAt: switchGen=%d, mSwitchGen=%d",
75525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                            switchGeneration, mSwitchGeneration);
75625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang
7571543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    if (switchGeneration != mSwitchGeneration) {
7581543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        break;
7591543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    }
7601543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
761a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                    AString uri;
762a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                    CHECK(msg->findString("uri", &uri));
7637c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
7647c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    // mark new fetcher mToBeResumed
765a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                    ssize_t index = mFetcherInfos.indexOfKey(uri);
766a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                    if (index >= 0) {
767a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                        mFetcherInfos.editValueAt(index).mToBeResumed = true;
768a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                    }
769a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
7707c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    // temporarily disable packet sources to be swapped to prevent
7717c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    // NuPlayerDecoder from dequeuing while we check progress
7727c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    for (size_t i = 0; i < mPacketSources.size(); ++i) {
7737c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                        if ((mSwapMask & mPacketSources.keyAt(i))
7747c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                                && uri == mStreams[i].mNewUri) {
7757c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                            mPacketSources.editValueAt(i)->enable(false);
7761543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        }
7771543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    }
7787c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    bool switchUp = (mCurBandwidthIndex > mOrigBandwidthIndex);
7797c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    // If switching up, require a cushion bigger than kUnderflowMark
7807c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    // to avoid buffering immediately after the switch.
7817c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    // (If we don't have that cushion we'd rather cancel and try again.)
782765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang                    int64_t delayUs = switchUp ? (kUnderflowMarkUs + 1000000ll) : 0;
7837c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    bool needResumeUntil = false;
7847c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    sp<AMessage> stopParams = msg;
7857c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    if (checkSwitchProgress(stopParams, delayUs, &needResumeUntil)) {
7867c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                        // playback time hasn't passed startAt time
7877c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                        if (!needResumeUntil) {
78825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                            ALOGV("finish switch");
7897c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                            for (size_t i = 0; i < kMaxStreams; ++i) {
7907c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                                if ((mSwapMask & indexToType(i))
7917c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                                        && uri == mStreams[i].mNewUri) {
7927c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                                    // have to make a copy of mStreams[i].mUri because
7937c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                                    // tryToFinishBandwidthSwitch is modifying mStreams[]
7947c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                                    AString oldURI = mStreams[i].mUri;
7957c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                                    tryToFinishBandwidthSwitch(oldURI);
7967c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                                    break;
7977c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                                }
7987c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                            }
7997c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                        } else {
8007c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                            // startAt time is after last enqueue time
8017c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                            // Resume fetcher for the original variant; the resumed fetcher should
8027c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                            // continue until the timestamps found in msg, which is stored by the
8037c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                            // new fetcher to indicate where the new variant has started buffering.
80425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                            ALOGV("finish switch with resumeUntilAsync");
8057c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                            for (size_t i = 0; i < mFetcherInfos.size(); i++) {
8067c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                                const FetcherInfo &info = mFetcherInfos.valueAt(i);
8077c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                                if (info.mToBeRemoved) {
8087c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                                    info.mFetcher->resumeUntilAsync(stopParams);
8097c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                                }
8107c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                            }
8117c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                        }
8127c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    } else {
8137c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                        // playback time passed startAt time
8147c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                        if (switchUp) {
8157c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                            // if switching up, cancel and retry if condition satisfies again
81625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                            ALOGV("cancel up switch because we're too late");
8177c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                            cancelBandwidthSwitch(true /* resume */);
8187c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                        } else {
81925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                            ALOGV("retry down switch at next sample");
8207c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                            resumeFetcher(uri, mSwapMask, -1, true /* newUri */);
8217c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                        }
8227c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    }
8237c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    // re-enable all packet sources
8247c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    for (size_t i = 0; i < mPacketSources.size(); ++i) {
8257c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                        mPacketSources.editValueAt(i)->enable(true);
8267c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    }
8277c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
8281543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    break;
8291543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                }
8301543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
8315abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang                case PlaylistFetcher::kWhatPlaylistFetched:
8325abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang                {
8335abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang                    onMasterPlaylistFetched(msg);
8345abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang                    break;
8355abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang                }
8365abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang
8370852843d304006e3ab333081fddda13b07193de8Robert Shih                case PlaylistFetcher::kWhatMetadataDetected:
8380852843d304006e3ab333081fddda13b07193de8Robert Shih                {
8390852843d304006e3ab333081fddda13b07193de8Robert Shih                    if (!mHasMetadata) {
8400852843d304006e3ab333081fddda13b07193de8Robert Shih                        mHasMetadata = true;
8410852843d304006e3ab333081fddda13b07193de8Robert Shih                        sp<AMessage> notify = mNotify->dup();
8420852843d304006e3ab333081fddda13b07193de8Robert Shih                        notify->setInt32("what", kWhatMetadataDetected);
8430852843d304006e3ab333081fddda13b07193de8Robert Shih                        notify->post();
8440852843d304006e3ab333081fddda13b07193de8Robert Shih                    }
8450852843d304006e3ab333081fddda13b07193de8Robert Shih                    break;
8460852843d304006e3ab333081fddda13b07193de8Robert Shih                }
8470852843d304006e3ab333081fddda13b07193de8Robert Shih
84814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                default:
84914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    TRESPASS();
85014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            }
85114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
85214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            break;
85314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
85414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
855dcb89b3b505522efde173c105a851c412f947178Chong Zhang        case kWhatChangeConfiguration:
856dcb89b3b505522efde173c105a851c412f947178Chong Zhang        {
857dcb89b3b505522efde173c105a851c412f947178Chong Zhang            onChangeConfiguration(msg);
858dcb89b3b505522efde173c105a851c412f947178Chong Zhang            break;
859dcb89b3b505522efde173c105a851c412f947178Chong Zhang        }
860dcb89b3b505522efde173c105a851c412f947178Chong Zhang
86114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case kWhatChangeConfiguration2:
86214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
86314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            onChangeConfiguration2(msg);
86414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            break;
86514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
86614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
86714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case kWhatChangeConfiguration3:
86814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
86914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            onChangeConfiguration3(msg);
87014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            break;
87114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
87214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
873964adb17885185808398507d2de88665fe193ee2Chong Zhang        case kWhatPollBuffering:
8740ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        {
875964adb17885185808398507d2de88665fe193ee2Chong Zhang            int32_t generation;
876964adb17885185808398507d2de88665fe193ee2Chong Zhang            CHECK(msg->findInt32("generation", &generation));
877964adb17885185808398507d2de88665fe193ee2Chong Zhang            if (generation == mPollBufferingGeneration) {
878964adb17885185808398507d2de88665fe193ee2Chong Zhang                onPollBuffering();
879964adb17885185808398507d2de88665fe193ee2Chong Zhang            }
8800ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih            break;
8810ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        }
8820ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
883a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        default:
884a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            TRESPASS();
885a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
886a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
887a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
888a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
889a44153c1a57202fb538659eb50706e60454d6273Andreas Huber// static
890a44153c1a57202fb538659eb50706e60454d6273Andreas Huberint LiveSession::SortByBandwidth(const BandwidthItem *a, const BandwidthItem *b) {
891a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (a->mBandwidth < b->mBandwidth) {
892a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return -1;
893a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else if (a->mBandwidth == b->mBandwidth) {
894a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return 0;
895a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
896a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
897a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return 1;
898a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
899a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
9008ca002eedc747dd854b61cbe364b52c06869273fRobert Shih// static
9018ca002eedc747dd854b61cbe364b52c06869273fRobert ShihLiveSession::StreamType LiveSession::indexToType(int idx) {
9020852843d304006e3ab333081fddda13b07193de8Robert Shih    CHECK(idx >= 0 && idx < kNumSources);
9038ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    return (StreamType)(1 << idx);
9048ca002eedc747dd854b61cbe364b52c06869273fRobert Shih}
9058ca002eedc747dd854b61cbe364b52c06869273fRobert Shih
906f69c996864844e8f669308af8412cede043062a2Robert Shih// static
907f69c996864844e8f669308af8412cede043062a2Robert Shihssize_t LiveSession::typeToIndex(int32_t type) {
908f69c996864844e8f669308af8412cede043062a2Robert Shih    switch (type) {
909f69c996864844e8f669308af8412cede043062a2Robert Shih        case STREAMTYPE_AUDIO:
910f69c996864844e8f669308af8412cede043062a2Robert Shih            return 0;
911f69c996864844e8f669308af8412cede043062a2Robert Shih        case STREAMTYPE_VIDEO:
912f69c996864844e8f669308af8412cede043062a2Robert Shih            return 1;
913f69c996864844e8f669308af8412cede043062a2Robert Shih        case STREAMTYPE_SUBTITLES:
914f69c996864844e8f669308af8412cede043062a2Robert Shih            return 2;
9150852843d304006e3ab333081fddda13b07193de8Robert Shih        case STREAMTYPE_METADATA:
9160852843d304006e3ab333081fddda13b07193de8Robert Shih            return 3;
917f69c996864844e8f669308af8412cede043062a2Robert Shih        default:
918f69c996864844e8f669308af8412cede043062a2Robert Shih            return -1;
919f69c996864844e8f669308af8412cede043062a2Robert Shih    };
920f69c996864844e8f669308af8412cede043062a2Robert Shih    return -1;
921f69c996864844e8f669308af8412cede043062a2Robert Shih}
922f69c996864844e8f669308af8412cede043062a2Robert Shih
923a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onConnect(const sp<AMessage> &msg) {
9245abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    CHECK(msg->findString("url", &mMasterURL));
9255abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang
9265abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    // TODO currently we don't know if we are coming here from incognito mode
9275abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    ALOGI("onConnect %s", uriDebugString(mMasterURL).c_str());
928a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
929ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    KeyedVector<String8, String8> *headers = NULL;
930ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    if (!msg->findPointer("headers", (void **)&headers)) {
931ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        mExtraHeaders.clear();
932ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    } else {
933ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        mExtraHeaders = *headers;
934ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber
935ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        delete headers;
936ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        headers = NULL;
937ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    }
938ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber
939964adb17885185808398507d2de88665fe193ee2Chong Zhang    // create looper for fetchers
940964adb17885185808398507d2de88665fe193ee2Chong Zhang    if (mFetcherLooper == NULL) {
941964adb17885185808398507d2de88665fe193ee2Chong Zhang        mFetcherLooper = new ALooper();
942964adb17885185808398507d2de88665fe193ee2Chong Zhang
943964adb17885185808398507d2de88665fe193ee2Chong Zhang        mFetcherLooper->setName("Fetcher");
944964adb17885185808398507d2de88665fe193ee2Chong Zhang        mFetcherLooper->start(false, false);
945964adb17885185808398507d2de88665fe193ee2Chong Zhang    }
946964adb17885185808398507d2de88665fe193ee2Chong Zhang
9475abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    // create fetcher to fetch the master playlist
9485abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    addFetcher(mMasterURL.c_str())->fetchPlaylistAsync();
9495abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang}
9505abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang
9515abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhangvoid LiveSession::onMasterPlaylistFetched(const sp<AMessage> &msg) {
9525abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    AString uri;
9535abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    CHECK(msg->findString("uri", &uri));
9545abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    ssize_t index = mFetcherInfos.indexOfKey(uri);
9555abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    if (index < 0) {
9565abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang        ALOGW("fetcher for master playlist is gone.");
9575abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang        return;
9585abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    }
9595abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang
9605abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    // no longer useful, remove
9615abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    mFetcherLooper->unregisterHandler(mFetcherInfos[index].mFetcher->id());
9625abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    mFetcherInfos.removeItemsAt(index);
9635abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang
9645abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    CHECK(msg->findObject("playlist", (sp<RefBase> *)&mPlaylist));
9655abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    if (mPlaylist == NULL) {
9665abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang        ALOGE("unable to fetch master playlist %s.",
9675abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang                uriDebugString(mMasterURL).c_str());
9685abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang
9695abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang        postPrepared(ERROR_IO);
9705abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang        return;
9715abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    }
97214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // We trust the content provider to make a reasonable choice of preferred
97314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // initial bandwidth by listing it first in the variant playlist.
97414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // At startup we really don't have a good estimate on the available
97514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // network bandwidth since we haven't tranferred any data yet. Once
97614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // we have we can make a better informed choice.
97714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    size_t initialBandwidth = 0;
97814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    size_t initialBandwidthIndex = 0;
97914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
980a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang    int32_t maxWidth = 0;
981a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang    int32_t maxHeight = 0;
982a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang
98314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (mPlaylist->isVariantPlaylist()) {
984d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        Vector<BandwidthItem> itemsWithVideo;
98514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        for (size_t i = 0; i < mPlaylist->size(); ++i) {
986a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            BandwidthItem item;
987a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
98814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            item.mPlaylistIndex = i;
98914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
990a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            sp<AMessage> meta;
99114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            AString uri;
99214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            mPlaylist->itemAt(i, &uri, &meta);
993a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
994a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            CHECK(meta->findInt32("bandwidth", (int32_t *)&item.mBandwidth));
995a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
996a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang            int32_t width, height;
997a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang            if (meta->findInt32("width", &width)) {
998a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang                maxWidth = max(maxWidth, width);
999a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang            }
1000a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang            if (meta->findInt32("height", &height)) {
1001a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang                maxHeight = max(maxHeight, height);
1002a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang            }
1003a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang
1004a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            mBandwidthItems.push(item);
1005d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            if (mPlaylist->hasType(i, "video")) {
1006d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                itemsWithVideo.push(item);
1007d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            }
1008d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        }
1009d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        // remove the audio-only variants if we have at least one with video
1010d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        if (!itemsWithVideo.empty()
1011d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                && itemsWithVideo.size() < mBandwidthItems.size()) {
1012d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            mBandwidthItems.clear();
1013d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            for (size_t i = 0; i < itemsWithVideo.size(); ++i) {
1014d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                mBandwidthItems.push(itemsWithVideo[i]);
1015d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            }
1016a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
1017a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1018a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        CHECK_GT(mBandwidthItems.size(), 0u);
1019d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        initialBandwidth = mBandwidthItems[0].mBandwidth;
1020a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1021a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        mBandwidthItems.sort(SortByBandwidth);
102214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
102314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        for (size_t i = 0; i < mBandwidthItems.size(); ++i) {
102414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            if (mBandwidthItems.itemAt(i).mBandwidth == initialBandwidth) {
102514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                initialBandwidthIndex = i;
102614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                break;
102714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            }
102814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
102914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    } else {
103014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        // dummy item.
103114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        BandwidthItem item;
103214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        item.mPlaylistIndex = 0;
103314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        item.mBandwidth = 0;
103414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        mBandwidthItems.push(item);
1035a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1036a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1037a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang    mMaxWidth = maxWidth > 0 ? maxWidth : mMaxWidth;
1038a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang    mMaxHeight = maxHeight > 0 ? maxHeight : mMaxHeight;
1039a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang
1040309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    mPlaylist->pickRandomMediaItems();
1041dcb89b3b505522efde173c105a851c412f947178Chong Zhang    changeConfiguration(
1042309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            0ll /* timeUs */, initialBandwidthIndex, false /* pickTrack */);
1043a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
1044a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
104514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::finishDisconnect() {
1046a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    ALOGV("finishDisconnect");
1047a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
104814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // No reconfiguration is currently pending, make sure none will trigger
104914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // during disconnection either.
10501543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    cancelBandwidthSwitch();
10511543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
1052964adb17885185808398507d2de88665fe193ee2Chong Zhang    // cancel buffer polling
1053964adb17885185808398507d2de88665fe193ee2Chong Zhang    cancelPollBuffering();
10540ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
10555abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    // TRICKY: don't wait for all fetcher to be stopped when disconnecting
10565abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    //
10575abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    // Some fetchers might be stuck in connect/getSize at this point. These
10585abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    // operations will eventually timeout (as we have a timeout set in
10595abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    // MediaHTTPConnection), but we don't want to block the main UI thread
10605abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    // until then. Here we just need to make sure we clear all references
10615abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    // to the fetchers, so that when they finally exit from the blocking
10625abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    // operation, they can be destructed.
10635abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    //
10645abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    // There is one very tricky point though. For this scheme to work, the
10655abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    // fecther must hold a reference to LiveSession, so that LiveSession is
10665abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    // destroyed after fetcher. Otherwise LiveSession would get stuck in its
10675abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    // own destructor when it waits for mFetcherLooper to stop, which still
10685abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    // blocks main UI thread.
106914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
107014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        mFetcherInfos.valueAt(i).mFetcher->stopAsync();
10715abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang        mFetcherLooper->unregisterHandler(
10725abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang                mFetcherInfos.valueAt(i).mFetcher->id());
107314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
10745abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang    mFetcherInfos.clear();
107514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
107614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mPacketSources.valueFor(STREAMTYPE_AUDIO)->signalEOS(ERROR_END_OF_STREAM);
107714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mPacketSources.valueFor(STREAMTYPE_VIDEO)->signalEOS(ERROR_END_OF_STREAM);
107814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
107914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mPacketSources.valueFor(
108014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            STREAMTYPE_SUBTITLES)->signalEOS(ERROR_END_OF_STREAM);
108114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
108214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> response = new AMessage;
108314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    response->setInt32("err", OK);
108414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
108514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    response->postReply(mDisconnectReplyID);
1086c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang    mDisconnectReplyID.clear();
108714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
108814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
108914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubersp<PlaylistFetcher> LiveSession::addFetcher(const char *uri) {
109014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    ssize_t index = mFetcherInfos.indexOfKey(uri);
109114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
109214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (index >= 0) {
109314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        return NULL;
109414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
109514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
10961d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> notify = new AMessage(kWhatFetcherNotify, this);
109714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->setString("uri", uri);
10981543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    notify->setInt32("switchGeneration", mSwitchGeneration);
109914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
110014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    FetcherInfo info;
110125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    info.mFetcher = new PlaylistFetcher(
110225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            notify, this, uri, mCurBandwidthIndex, mSubtitleGeneration);
110314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    info.mDurationUs = -1ll;
11041543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    info.mToBeRemoved = false;
1105a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    info.mToBeResumed = false;
1106964adb17885185808398507d2de88665fe193ee2Chong Zhang    mFetcherLooper->registerHandler(info.mFetcher);
110714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
110814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mFetcherInfos.add(uri, info);
110914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
111014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return info.mFetcher;
1111a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
1112a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1113b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe#if 0
1114a44153c1a57202fb538659eb50706e60454d6273Andreas Huberstatic double uniformRand() {
1115a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return (double)rand() / RAND_MAX;
1116a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
1117b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe#endif
1118a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
11190852843d304006e3ab333081fddda13b07193de8Robert Shihbool LiveSession::UriIsSameAsIndex(const AString &uri, int32_t i, bool newUri) {
11200852843d304006e3ab333081fddda13b07193de8Robert Shih    ALOGI("[timed_id3] i %d UriIsSameAsIndex newUri %s, %s", i,
11210852843d304006e3ab333081fddda13b07193de8Robert Shih            newUri ? "true" : "false",
11220852843d304006e3ab333081fddda13b07193de8Robert Shih            newUri ? mStreams[i].mNewUri.c_str() : mStreams[i].mUri.c_str());
11230852843d304006e3ab333081fddda13b07193de8Robert Shih    return i >= 0
11240852843d304006e3ab333081fddda13b07193de8Robert Shih            && ((!newUri && uri == mStreams[i].mUri)
11250852843d304006e3ab333081fddda13b07193de8Robert Shih            || (newUri && uri == mStreams[i].mNewUri));
11260852843d304006e3ab333081fddda13b07193de8Robert Shih}
11270852843d304006e3ab333081fddda13b07193de8Robert Shih
11280852843d304006e3ab333081fddda13b07193de8Robert Shihsp<AnotherPacketSource> LiveSession::getPacketSourceForStreamIndex(
11290852843d304006e3ab333081fddda13b07193de8Robert Shih        size_t trackIndex, bool newUri) {
11300852843d304006e3ab333081fddda13b07193de8Robert Shih    StreamType type = indexToType(trackIndex);
11310852843d304006e3ab333081fddda13b07193de8Robert Shih    sp<AnotherPacketSource> source = NULL;
11320852843d304006e3ab333081fddda13b07193de8Robert Shih    if (newUri) {
11330852843d304006e3ab333081fddda13b07193de8Robert Shih        source = mPacketSources2.valueFor(type);
11340852843d304006e3ab333081fddda13b07193de8Robert Shih        source->clear();
11350852843d304006e3ab333081fddda13b07193de8Robert Shih    } else {
11360852843d304006e3ab333081fddda13b07193de8Robert Shih        source = mPacketSources.valueFor(type);
11370852843d304006e3ab333081fddda13b07193de8Robert Shih    };
11380852843d304006e3ab333081fddda13b07193de8Robert Shih    return source;
11390852843d304006e3ab333081fddda13b07193de8Robert Shih}
11400852843d304006e3ab333081fddda13b07193de8Robert Shih
11410852843d304006e3ab333081fddda13b07193de8Robert Shihsp<AnotherPacketSource> LiveSession::getMetadataSource(
11420852843d304006e3ab333081fddda13b07193de8Robert Shih        sp<AnotherPacketSource> sources[kNumSources], uint32_t streamMask, bool newUri) {
11430852843d304006e3ab333081fddda13b07193de8Robert Shih    // todo: One case where the following strategy can fail is when audio and video
11440852843d304006e3ab333081fddda13b07193de8Robert Shih    // are in separate playlists, both are transport streams, and the metadata
11450852843d304006e3ab333081fddda13b07193de8Robert Shih    // is actually contained in the audio stream.
11460852843d304006e3ab333081fddda13b07193de8Robert Shih    ALOGV("[timed_id3] getMetadataSourceForUri streamMask %x newUri %s",
11470852843d304006e3ab333081fddda13b07193de8Robert Shih            streamMask, newUri ? "true" : "false");
11480852843d304006e3ab333081fddda13b07193de8Robert Shih
11490852843d304006e3ab333081fddda13b07193de8Robert Shih    if ((sources[kVideoIndex] != NULL) // video fetcher; or ...
11500852843d304006e3ab333081fddda13b07193de8Robert Shih            || (!(streamMask & STREAMTYPE_VIDEO) && sources[kAudioIndex] != NULL)) {
11510852843d304006e3ab333081fddda13b07193de8Robert Shih            // ... audio fetcher for audio only variant
11520852843d304006e3ab333081fddda13b07193de8Robert Shih        return getPacketSourceForStreamIndex(kMetaDataIndex, newUri);
11530852843d304006e3ab333081fddda13b07193de8Robert Shih    }
11540852843d304006e3ab333081fddda13b07193de8Robert Shih
11550852843d304006e3ab333081fddda13b07193de8Robert Shih    return NULL;
11560852843d304006e3ab333081fddda13b07193de8Robert Shih}
11570852843d304006e3ab333081fddda13b07193de8Robert Shih
11587c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangbool LiveSession::resumeFetcher(
11597c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        const AString &uri, uint32_t streamMask, int64_t timeUs, bool newUri) {
11607c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    ssize_t index = mFetcherInfos.indexOfKey(uri);
11617c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    if (index < 0) {
11627c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        ALOGE("did not find fetcher for uri: %s", uri.c_str());
11637c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        return false;
11647c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    }
11657c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
11667c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    bool resume = false;
11670852843d304006e3ab333081fddda13b07193de8Robert Shih    sp<AnotherPacketSource> sources[kNumSources];
11687c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    for (size_t i = 0; i < kMaxStreams; ++i) {
11690852843d304006e3ab333081fddda13b07193de8Robert Shih        if ((streamMask & indexToType(i)) && UriIsSameAsIndex(uri, i, newUri)) {
11707c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            resume = true;
11710852843d304006e3ab333081fddda13b07193de8Robert Shih            sources[i] = getPacketSourceForStreamIndex(i, newUri);
11727c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        }
11737c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    }
11747c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
11757c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    if (resume) {
117625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang        sp<PlaylistFetcher> &fetcher = mFetcherInfos.editValueAt(index).mFetcher;
11777c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        SeekMode seekMode = newUri ? kSeekModeNextSample : kSeekModeExactPosition;
117825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang
117925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang        ALOGV("resuming fetcher-%d, timeUs=%lld, seekMode=%d",
118025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                fetcher->getFetcherID(), (long long)timeUs, seekMode);
118125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang
118225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang        fetcher->startAsync(
11837c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                sources[kAudioIndex],
11847c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                sources[kVideoIndex],
11857c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                sources[kSubtitleIndex],
11860852843d304006e3ab333081fddda13b07193de8Robert Shih                getMetadataSource(sources, streamMask, newUri),
11877c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                timeUs, -1, -1, seekMode);
11887c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    }
11897c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
11907c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    return resume;
11917c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang}
11927c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
1193a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhangfloat LiveSession::getAbortThreshold(
1194a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        ssize_t currentBWIndex, ssize_t targetBWIndex) const {
1195a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    float abortThreshold = -1.0f;
1196a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    if (currentBWIndex > 0 && targetBWIndex < currentBWIndex) {
1197a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        /*
1198a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           If we're switching down, we need to decide whether to
1199a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
1200a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           1) finish last segment of high-bandwidth variant, or
1201a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           2) abort last segment of high-bandwidth variant, and fetch an
1202a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang              overlapping portion from low-bandwidth variant.
1203a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
1204a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           Here we try to maximize the amount of buffer left when the
1205a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           switch point is met. Given the following parameters:
1206a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
1207a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           B: our current buffering level in seconds
1208a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           T: target duration in seconds
1209a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           X: sample duration in seconds remain to fetch in last segment
1210a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           bw0: bandwidth of old variant (as specified in playlist)
1211a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           bw1: bandwidth of new variant (as specified in playlist)
1212a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           bw: measured bandwidth available
1213a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
1214a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           If we choose 1), when switch happens at the end of current
1215a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           segment, our buffering will be
1216a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                  B + X - X * bw0 / bw
1217a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
1218a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           If we choose 2), when switch happens where we aborted current
1219a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           segment, our buffering will be
1220a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                  B - (T - X) * bw1 / bw
1221a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
1222a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang           We should only choose 1) if
1223a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                  X/T < bw1 / (bw1 + bw0 - bw)
1224a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        */
1225a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
12267c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // Taking the measured current bandwidth at 50% face value only,
12277c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // as our bandwidth estimation is a lagging indicator. Being
12287c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // conservative on this, we prefer switching to lower bandwidth
12297c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // unless we're really confident finishing up the last segment
12307c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // of higher bandwidth will be fast.
1231a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        CHECK(mLastBandwidthBps >= 0);
1232a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        abortThreshold =
1233a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                (float)mBandwidthItems.itemAt(targetBWIndex).mBandwidth
1234a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang             / ((float)mBandwidthItems.itemAt(targetBWIndex).mBandwidth
1235a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang              + (float)mBandwidthItems.itemAt(currentBWIndex).mBandwidth
12367c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang              - (float)mLastBandwidthBps * 0.5f);
1237a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        if (abortThreshold < 0.0f) {
1238a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang            abortThreshold = -1.0f; // do not abort
1239a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        }
1240a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        ALOGV("Switching Down: bps %ld => %ld, measured %d, abort ratio %.2f",
1241a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                mBandwidthItems.itemAt(currentBWIndex).mBandwidth,
1242a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                mBandwidthItems.itemAt(targetBWIndex).mBandwidth,
1243a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                mLastBandwidthBps,
1244a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                abortThreshold);
1245a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    }
1246a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    return abortThreshold;
1247a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang}
1248a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
1249538b6d22a3578c0201d48f8548289aa254d81484Chong Zhangvoid LiveSession::addBandwidthMeasurement(size_t numBytes, int64_t delayUs) {
1250538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    mBandwidthEstimator->addBandwidthMeasurement(numBytes, delayUs);
1251538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang}
1252538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
1253538b6d22a3578c0201d48f8548289aa254d81484Chong Zhangsize_t LiveSession::getBandwidthIndex(int32_t bandwidthBps) {
1254538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    if (mBandwidthItems.size() < 2) {
1255538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        // shouldn't be here if we only have 1 bandwidth, check
1256538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        // logic to get rid of redundant bandwidth polling
1257538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        ALOGW("getBandwidthIndex() called for single bandwidth playlist!");
1258a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return 0;
1259a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1260a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1261a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#if 1
1262a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    char value[PROPERTY_VALUE_MAX];
1263673158582c9589cee1d5e4d7c79622609938b8f8Andreas Huber    ssize_t index = -1;
126414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (property_get("media.httplive.bw-index", value, NULL)) {
1265a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        char *end;
126614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        index = strtol(value, &end, 10);
126714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        CHECK(end > value && *end == '\0');
126814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
126914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (index >= 0 && (size_t)index >= mBandwidthItems.size()) {
127014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            index = mBandwidthItems.size() - 1;
1271a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
1272a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1273a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
127414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (index < 0) {
127514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        char value[PROPERTY_VALUE_MAX];
127614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (property_get("media.httplive.max-bw", value, NULL)) {
127714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            char *end;
127814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            long maxBw = strtoul(value, &end, 10);
127914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            if (end > value && *end == '\0') {
128014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                if (maxBw > 0 && bandwidthBps > maxBw) {
128114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    ALOGV("bandwidth capped to %ld bps", maxBw);
128214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    bandwidthBps = maxBw;
128314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                }
128414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            }
128514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
1286a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
128714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        // Pick the highest bandwidth stream below or equal to estimated bandwidth.
128814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
128914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        index = mBandwidthItems.size() - 1;
129000598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih        while (index > 0) {
1291538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang            // be conservative (70%) to avoid overestimating and immediately
1292538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang            // switching down again.
1293538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang            size_t adjustedBandwidthBps = bandwidthBps * 7 / 10;
129400598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih            if (mBandwidthItems.itemAt(index).mBandwidth <= adjustedBandwidthBps) {
129500598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih                break;
129600598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih            }
129714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            --index;
129814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
1299a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1300a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0
1301a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // Change bandwidth at random()
1302a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index = uniformRand() * mBandwidthItems.size();
1303a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0
1304a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // There's a 50% chance to stay on the current bandwidth and
1305a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // a 50% chance to switch to the next higher bandwidth (wrapping around
1306a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // to lowest)
1307a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    const size_t kMinIndex = 0;
1308a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1309309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    static ssize_t mCurBandwidthIndex = -1;
131014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
1311a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index;
1312309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    if (mCurBandwidthIndex < 0) {
1313a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        index = kMinIndex;
1314a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else if (uniformRand() < 0.5) {
1315309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        index = (size_t)mCurBandwidthIndex;
1316a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else {
1317309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        index = mCurBandwidthIndex + 1;
1318a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (index == mBandwidthItems.size()) {
1319a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            index = kMinIndex;
1320a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
1321a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1322309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    mCurBandwidthIndex = index;
1323a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0
1324a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // Pick the highest bandwidth stream below or equal to 1.2 Mbit/sec
1325a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1326a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index = mBandwidthItems.size() - 1;
1327a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    while (index > 0 && mBandwidthItems.itemAt(index).mBandwidth > 1200000) {
1328a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        --index;
1329a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
133014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#elif 1
133114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    char value[PROPERTY_VALUE_MAX];
133214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    size_t index;
133314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (property_get("media.httplive.bw-index", value, NULL)) {
133414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        char *end;
133514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        index = strtoul(value, &end, 10);
133614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        CHECK(end > value && *end == '\0');
133714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
133814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (index >= mBandwidthItems.size()) {
133914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            index = mBandwidthItems.size() - 1;
134014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
134114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    } else {
134214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        index = 0;
134314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
1344a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#else
1345a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index = mBandwidthItems.size() - 1;  // Highest bandwidth stream
1346a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#endif
1347a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
134814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK_GE(index, 0);
134914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
1350a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return index;
1351a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
1352a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1353d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong ZhangHLSTime LiveSession::latestMediaSegmentStartTime() const {
1354d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang    HLSTime audioTime(mPacketSources.valueFor(
1355d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                    STREAMTYPE_AUDIO)->getLatestDequeuedMeta());
1356b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih
1357d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang    HLSTime videoTime(mPacketSources.valueFor(
1358d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                    STREAMTYPE_VIDEO)->getLatestDequeuedMeta());
1359b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih
1360d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang    return audioTime < videoTime ? videoTime : audioTime;
1361b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih}
1362b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih
1363a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnarvoid LiveSession::onSeek(const sp<AMessage> &msg) {
136414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    int64_t timeUs;
136514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(msg->findInt64("timeUs", &timeUs));
1366a1151185c7eb3b4c483f7067deba1775fd0a2510Lajos Molnar    changeConfiguration(timeUs);
13677e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber}
13687e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
136914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::getDuration(int64_t *durationUs) const {
1370895651b07fec30b0f9b0d2499599a179d95c9be4Wei Jia    int64_t maxDurationUs = -1ll;
137114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
137214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        int64_t fetcherDurationUs = mFetcherInfos.valueAt(i).mDurationUs;
1373b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
1374895651b07fec30b0f9b0d2499599a179d95c9be4Wei Jia        if (fetcherDurationUs > maxDurationUs) {
137514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            maxDurationUs = fetcherDurationUs;
1376a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
1377a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1378a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
137914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    *durationUs = maxDurationUs;
1380a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
138114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return OK;
138214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
13830f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber
138414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberbool LiveSession::isSeekable() const {
138514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    int64_t durationUs;
138614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return getDuration(&durationUs) == OK && durationUs >= 0;
138714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
13880f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber
138914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberbool LiveSession::hasDynamicDuration() const {
139014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return false;
139114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
13920f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber
1393404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhangsize_t LiveSession::getTrackCount() const {
13949d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih    if (mPlaylist == NULL) {
13959d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih        return 0;
13969d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih    } else {
13970852843d304006e3ab333081fddda13b07193de8Robert Shih        return mPlaylist->getTrackCount() + (mHasMetadata ? 1 : 0);
13989d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih    }
1399404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang}
1400404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang
1401404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhangsp<AMessage> LiveSession::getTrackInfo(size_t trackIndex) const {
14029d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih    if (mPlaylist == NULL) {
14039d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih        return NULL;
14049d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih    } else {
14050852843d304006e3ab333081fddda13b07193de8Robert Shih        if (trackIndex == mPlaylist->getTrackCount() && mHasMetadata) {
14060852843d304006e3ab333081fddda13b07193de8Robert Shih            sp<AMessage> format = new AMessage();
14070852843d304006e3ab333081fddda13b07193de8Robert Shih            format->setInt32("type", MEDIA_TRACK_TYPE_METADATA);
14080852843d304006e3ab333081fddda13b07193de8Robert Shih            format->setString("language", "und");
14090852843d304006e3ab333081fddda13b07193de8Robert Shih            format->setString("mime", MEDIA_MIMETYPE_DATA_METADATA);
14100852843d304006e3ab333081fddda13b07193de8Robert Shih            return format;
14110852843d304006e3ab333081fddda13b07193de8Robert Shih        }
14129d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih        return mPlaylist->getTrackInfo(trackIndex);
14139d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih    }
1414dcb89b3b505522efde173c105a851c412f947178Chong Zhang}
1415dcb89b3b505522efde173c105a851c412f947178Chong Zhang
1416dcb89b3b505522efde173c105a851c412f947178Chong Zhangstatus_t LiveSession::selectTrack(size_t index, bool select) {
1417b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    if (mPlaylist == NULL) {
1418b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih        return INVALID_OPERATION;
1419b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    }
1420b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih
142125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    ALOGV("selectTrack: index=%zu, select=%d, mSubtitleGen=%d++",
142225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            index, select, mSubtitleGeneration);
142325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang
1424b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    ++mSubtitleGeneration;
1425dcb89b3b505522efde173c105a851c412f947178Chong Zhang    status_t err = mPlaylist->selectTrack(index, select);
1426dcb89b3b505522efde173c105a851c412f947178Chong Zhang    if (err == OK) {
14271d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar        sp<AMessage> msg = new AMessage(kWhatChangeConfiguration, this);
1428309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        msg->setInt32("pickTrack", select);
1429309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        msg->post();
1430dcb89b3b505522efde173c105a851c412f947178Chong Zhang    }
1431dcb89b3b505522efde173c105a851c412f947178Chong Zhang    return err;
1432dcb89b3b505522efde173c105a851c412f947178Chong Zhang}
1433dcb89b3b505522efde173c105a851c412f947178Chong Zhang
143489bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shihssize_t LiveSession::getSelectedTrack(media_track_type type) const {
143589bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih    if (mPlaylist == NULL) {
143689bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih        return -1;
143789bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih    } else {
143889bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih        return mPlaylist->getSelectedTrack(type);
143989bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih    }
144089bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih}
144189bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih
1442dcb89b3b505522efde173c105a851c412f947178Chong Zhangvoid LiveSession::changeConfiguration(
14437c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        int64_t timeUs, ssize_t bandwidthIndex, bool pickTrack) {
144425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    ALOGV("changeConfiguration: timeUs=%lld us, bwIndex=%zd, pickTrack=%d",
144525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang          (long long)timeUs, bandwidthIndex, pickTrack);
144625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang
14471543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    cancelBandwidthSwitch();
14481543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
144914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(!mReconfigurationInProgress);
145014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mReconfigurationInProgress = true;
14517c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    if (bandwidthIndex >= 0) {
14527c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        mOrigBandwidthIndex = mCurBandwidthIndex;
14537c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        mCurBandwidthIndex = bandwidthIndex;
14548464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang        if (mOrigBandwidthIndex != mCurBandwidthIndex) {
14558464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            ALOGI("#### Starting Bandwidth Switch: %zd => %zd",
14568464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang                    mOrigBandwidthIndex, mCurBandwidthIndex);
14578464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang        }
14587c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    }
14597c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    CHECK_LT(mCurBandwidthIndex, mBandwidthItems.size());
14607c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    const BandwidthItem &item = mBandwidthItems.itemAt(mCurBandwidthIndex);
1461a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
14621543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    uint32_t streamMask = 0; // streams that should be fetched by the new fetcher
14631543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    uint32_t resumeMask = 0; // streams that should be fetched by the original fetcher
1464a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
14658ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    AString URIs[kMaxStreams];
14668ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
14678ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        if (mPlaylist->getTypeURI(item.mPlaylistIndex, mStreams[i].mType, &URIs[i])) {
14688ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            streamMask |= indexToType(i);
14698ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        }
147014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
1471aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber
147214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Step 1, stop and discard fetchers that are no longer needed.
147314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Pause those that we'll reuse.
147414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
14757c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // skip fetchers that are marked mToBeRemoved,
14767c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // these are done and can't be reused
14777c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        if (mFetcherInfos[i].mToBeRemoved) {
14787c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            continue;
14797c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        }
14807c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
148114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        const AString &uri = mFetcherInfos.keyAt(i);
1482d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        sp<PlaylistFetcher> &fetcher = mFetcherInfos.editValueAt(i).mFetcher;
1483aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber
1484d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        bool discardFetcher = true, delayRemoval = false;
1485c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        for (size_t j = 0; j < kMaxStreams; ++j) {
1486c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang            StreamType type = indexToType(j);
1487c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang            if ((streamMask & type) && uri == URIs[j]) {
1488c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang                resumeMask |= type;
1489c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang                streamMask &= ~type;
1490c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang                discardFetcher = false;
14916801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber            }
149214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
1493d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        // Delay fetcher removal if not picking tracks, AND old fetcher
1494d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        // has stream mask that overlaps new variant. (Okay to discard
1495d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        // old fetcher now, if completely no overlap.)
1496d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        if (discardFetcher && timeUs < 0ll && !pickTrack
1497d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                && (fetcher->getStreamTypeMask() & streamMask)) {
1498d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            discardFetcher = false;
1499d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            delayRemoval = true;
1500d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        }
1501a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
150214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (discardFetcher) {
150325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            ALOGV("discarding fetcher-%d", fetcher->getFetcherID());
1504d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            fetcher->stopAsync();
15056801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber        } else {
15068a048338d9291b2db1b3a325fff58cb1aa69f04dChong Zhang            float threshold = 0.0f; // default to pause after current block (47Kbytes)
15075abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang            bool disconnect = false;
1508a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang            if (timeUs >= 0ll) {
1509a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                // seeking, no need to finish fetching
15105abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang                disconnect = true;
1511d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            } else if (delayRemoval) {
1512a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                // adapting, abort if remaining of current segment is over threshold
1513a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                threshold = getAbortThreshold(
15147c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                        mOrigBandwidthIndex, mCurBandwidthIndex);
1515a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang            }
1516a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
151725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            ALOGV("pausing fetcher-%d, threshold=%.2f",
151825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                    fetcher->getFetcherID(), threshold);
15195abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang            fetcher->pauseAsync(threshold, disconnect);
15206801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber        }
1521a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1522a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
15231543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    sp<AMessage> msg;
15241543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    if (timeUs < 0ll) {
1525309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        // skip onChangeConfiguration2 (decoder destruction) if not seeking.
15261d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar        msg = new AMessage(kWhatChangeConfiguration3, this);
15271543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    } else {
15281d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar        msg = new AMessage(kWhatChangeConfiguration2, this);
15291543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
153014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    msg->setInt32("streamMask", streamMask);
15311543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    msg->setInt32("resumeMask", resumeMask);
1532309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    msg->setInt32("pickTrack", pickTrack);
153314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    msg->setInt64("timeUs", timeUs);
15348ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
1535309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        if ((streamMask | resumeMask) & indexToType(i)) {
15368ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            msg->setString(mStreams[i].uriKey().c_str(), URIs[i].c_str());
15378ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        }
15386e6b1cae2bac1b78205cefab8e4e9e9538982965Andreas Huber    }
1539a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
154014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Every time a fetcher acknowledges the stopAsync or pauseAsync request
154114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // we'll decrement mContinuationCounter, once it reaches zero, i.e. all
154214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // fetchers have completed their asynchronous operation, we'll post
154314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // mContinuation, which then is handled below in onChangeConfiguration2.
154414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mContinuationCounter = mFetcherInfos.size();
154514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mContinuation = msg;
154688b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber
154714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (mContinuationCounter == 0) {
154814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        msg->post();
154988b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber    }
155014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
1551a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1552dcb89b3b505522efde173c105a851c412f947178Chong Zhangvoid LiveSession::onChangeConfiguration(const sp<AMessage> &msg) {
155325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    ALOGV("onChangeConfiguration");
155425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang
1555dcb89b3b505522efde173c105a851c412f947178Chong Zhang    if (!mReconfigurationInProgress) {
15567c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        int32_t pickTrack = 0;
1557309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        msg->findInt32("pickTrack", &pickTrack);
15587c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        changeConfiguration(-1ll /* timeUs */, -1, pickTrack);
1559dcb89b3b505522efde173c105a851c412f947178Chong Zhang    } else {
1560dcb89b3b505522efde173c105a851c412f947178Chong Zhang        msg->post(1000000ll); // retry in 1 sec
1561dcb89b3b505522efde173c105a851c412f947178Chong Zhang    }
1562dcb89b3b505522efde173c105a851c412f947178Chong Zhang}
1563dcb89b3b505522efde173c105a851c412f947178Chong Zhang
156414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::onChangeConfiguration2(const sp<AMessage> &msg) {
156525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    ALOGV("onChangeConfiguration2");
156625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang
156714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mContinuation.clear();
1568bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
156914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // All fetchers are either suspended or have been removed now.
1570bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
1571964adb17885185808398507d2de88665fe193ee2Chong Zhang    // If we're seeking, clear all packet sources before we report
1572964adb17885185808398507d2de88665fe193ee2Chong Zhang    // seek complete, to prevent decoder from pulling stale data.
1573964adb17885185808398507d2de88665fe193ee2Chong Zhang    int64_t timeUs;
1574964adb17885185808398507d2de88665fe193ee2Chong Zhang    CHECK(msg->findInt64("timeUs", &timeUs));
1575964adb17885185808398507d2de88665fe193ee2Chong Zhang
1576964adb17885185808398507d2de88665fe193ee2Chong Zhang    if (timeUs >= 0) {
1577964adb17885185808398507d2de88665fe193ee2Chong Zhang        mLastSeekTimeUs = timeUs;
15788464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang        mLastDequeuedTimeUs = timeUs;
1579964adb17885185808398507d2de88665fe193ee2Chong Zhang
1580964adb17885185808398507d2de88665fe193ee2Chong Zhang        for (size_t i = 0; i < mPacketSources.size(); i++) {
1581964adb17885185808398507d2de88665fe193ee2Chong Zhang            mPacketSources.editValueAt(i)->clear();
1582964adb17885185808398507d2de88665fe193ee2Chong Zhang        }
1583964adb17885185808398507d2de88665fe193ee2Chong Zhang
15847c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        for (size_t i = 0; i < kMaxStreams; ++i) {
158581636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang            mStreams[i].reset();
15867c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        }
15877c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
1588964adb17885185808398507d2de88665fe193ee2Chong Zhang        mDiscontinuityOffsetTimesUs.clear();
1589964adb17885185808398507d2de88665fe193ee2Chong Zhang        mDiscontinuityAbsStartTimesUs.clear();
1590964adb17885185808398507d2de88665fe193ee2Chong Zhang
1591c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        if (mSeekReplyID != NULL) {
1592964adb17885185808398507d2de88665fe193ee2Chong Zhang            CHECK(mSeekReply != NULL);
1593964adb17885185808398507d2de88665fe193ee2Chong Zhang            mSeekReply->setInt32("err", OK);
1594964adb17885185808398507d2de88665fe193ee2Chong Zhang            mSeekReply->postReply(mSeekReplyID);
1595c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang            mSeekReplyID.clear();
1596964adb17885185808398507d2de88665fe193ee2Chong Zhang            mSeekReply.clear();
1597964adb17885185808398507d2de88665fe193ee2Chong Zhang        }
15987c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
15997c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // restart buffer polling after seek becauese previous
16007c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        // buffering position is no longer valid.
16017c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        restartPollBuffering();
1602964adb17885185808398507d2de88665fe193ee2Chong Zhang    }
1603964adb17885185808398507d2de88665fe193ee2Chong Zhang
1604309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    uint32_t streamMask, resumeMask;
160514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(msg->findInt32("streamMask", (int32_t *)&streamMask));
1606309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    CHECK(msg->findInt32("resumeMask", (int32_t *)&resumeMask));
1607309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
1608309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    streamMask |= resumeMask;
1609bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
16108ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    AString URIs[kMaxStreams];
16118ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
16128ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        if (streamMask & indexToType(i)) {
16138ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            const AString &uriKey = mStreams[i].uriKey();
16148ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            CHECK(msg->findString(uriKey.c_str(), &URIs[i]));
16158ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            ALOGV("%s = '%s'", uriKey.c_str(), URIs[i].c_str());
16168ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        }
161722fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber    }
16183831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber
161914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    uint32_t changedMask = 0;
16208ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams && i != kSubtitleIndex; ++i) {
1621c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        // stream URI could change even if onChangeConfiguration2 is only
1622c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        // used for seek. Seek could happen during a bw switch, in this
1623c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        // case bw switch will be cancelled, but the seekTo position will
1624c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        // fetch from the new URI.
1625c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        if ((mStreamMask & streamMask & indexToType(i))
1626c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang                && !mStreams[i].mUri.empty()
1627c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang                && !(URIs[i] == mStreams[i].mUri)) {
16284604458dfe57b0e91a464aefafea50ae7b9876c1Chong Zhang            ALOGV("stream %zu changed: oldURI %s, newURI %s", i,
1629c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang                    mStreams[i].mUri.c_str(), URIs[i].c_str());
1630c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang            sp<AnotherPacketSource> source = mPacketSources.valueFor(indexToType(i));
16318464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            if (source->getLatestDequeuedMeta() != NULL) {
16328464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang                source->queueDiscontinuity(
16338464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang                        ATSParser::DISCONTINUITY_FORMATCHANGE, NULL, true);
16348464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            }
1635c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        }
1636c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        // Determine which decoders to shutdown on the player side,
1637c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        // a decoder has to be shutdown if its streamtype was active
1638c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        // before but now longer isn't.
1639c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        if ((mStreamMask & ~streamMask & indexToType(i))) {
16408ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            changedMask |= indexToType(i);
16418ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        }
1642b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber    }
1643b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
164414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (changedMask == 0) {
164514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        // If nothing changed as far as the audio/video decoders
164614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        // are concerned we can proceed.
164714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        onChangeConfiguration3(msg);
164814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        return;
164914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
165043c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
165114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Something changed, inform the player which will shutdown the
165214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // corresponding decoders and will post the reply once that's done.
165314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Handling the reply will continue executing below in
165414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // onChangeConfiguration3.
165514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> notify = mNotify->dup();
165614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->setInt32("what", kWhatStreamsChanged);
165714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->setInt32("changedMask", changedMask);
165820f725ebcef13ded1b4b85c61c8a4b37cd030656Andreas Huber
165914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    msg->setWhat(kWhatChangeConfiguration3);
16601d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    msg->setTarget(this);
1661b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
166214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->setMessage("reply", msg);
166314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->post();
166414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
1665b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
166614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::onChangeConfiguration3(const sp<AMessage> &msg) {
16671543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    mContinuation.clear();
166814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // All remaining fetchers are still suspended, the player has shutdown
166914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // any decoders that needed it.
1670b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
16711543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    uint32_t streamMask, resumeMask;
167214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(msg->findInt32("streamMask", (int32_t *)&streamMask));
16731543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    CHECK(msg->findInt32("resumeMask", (int32_t *)&resumeMask));
1674a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1675d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang    mNewStreamMask = streamMask | resumeMask;
1676d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang
167714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    int64_t timeUs;
1678309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    int32_t pickTrack;
16791543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    bool switching = false;
168014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(msg->findInt64("timeUs", &timeUs));
1681309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    CHECK(msg->findInt32("pickTrack", &pickTrack));
1682a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
168314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (timeUs < 0ll) {
1684309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        if (!pickTrack) {
1685d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            // mSwapMask contains streams that are in both old and new variant,
1686d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            // (in mNewStreamMask & mStreamMask) but with different URIs
1687d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            // (not in resumeMask).
1688d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            // For example, old variant has video and audio in two separate
1689d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            // URIs, and new variant has only audio with unchanged URI. mSwapMask
1690d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            // should be 0 as there is nothing to swap. We only need to stop video,
1691d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            // and resume audio.
1692d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            mSwapMask =  mNewStreamMask & mStreamMask & ~resumeMask;
1693d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            switching = (mSwapMask != 0);
1694309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        }
1695309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        mRealTimeBaseUs = ALooper::GetNowUs() - mLastDequeuedTimeUs;
1696309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    } else {
1697309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        mRealTimeBaseUs = ALooper::GetNowUs() - timeUs;
169814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
1699a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
170025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    ALOGV("onChangeConfiguration3: timeUs=%lld, switching=%d, pickTrack=%d, "
170125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            "mStreamMask=0x%x, mNewStreamMask=0x%x, mSwapMask=0x%x",
170225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            (long long)timeUs, switching, pickTrack,
170325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            mStreamMask, mNewStreamMask, mSwapMask);
170425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang
1705f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
1706f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        if (streamMask & indexToType(i)) {
1707f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            if (switching) {
1708f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih                CHECK(msg->findString(mStreams[i].uriKey().c_str(), &mStreams[i].mNewUri));
1709f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            } else {
1710f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih                CHECK(msg->findString(mStreams[i].uriKey().c_str(), &mStreams[i].mUri));
1711f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            }
1712f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        }
1713f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    }
1714f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih
17151543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // Of all existing fetchers:
17161543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // * Resume fetchers that are still needed and assign them original packet sources.
17171543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // * Mark otherwise unneeded fetchers for removal.
17181543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    ALOGV("resuming fetchers for mask 0x%08x", resumeMask);
171914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
172014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        const AString &uri = mFetcherInfos.keyAt(i);
17217c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        if (!resumeFetcher(uri, resumeMask, timeUs)) {
172225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            ALOGV("marking fetcher-%d to be removed",
172325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                    mFetcherInfos[i].mFetcher->getFetcherID());
172425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang
17257c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            mFetcherInfos.editValueAt(i).mToBeRemoved = true;
17261543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        }
1727a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1728a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
172914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // streamMask now only contains the types that need a new fetcher created.
173014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (streamMask != 0) {
173114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        ALOGV("creating new fetchers for mask 0x%08x", streamMask);
1732a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1733a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
17341543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // Find out when the original fetchers have buffered up to and start the new fetchers
17351543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // at a later timestamp.
17368ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams; i++) {
17378ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        if (!(indexToType(i) & streamMask)) {
17388ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            continue;
17398ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        }
17401156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
174114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        AString uri;
1742f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        uri = switching ? mStreams[i].mNewUri : mStreams[i].mUri;
17439b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber
174414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        sp<PlaylistFetcher> fetcher = addFetcher(uri.c_str());
174514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        CHECK(fetcher != NULL);
1746a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1747d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        HLSTime startTime;
1748a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        SeekMode seekMode = kSeekModeExactPosition;
17490852843d304006e3ab333081fddda13b07193de8Robert Shih        sp<AnotherPacketSource> sources[kNumSources];
17501543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
1751d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        if (i == kSubtitleIndex || (!pickTrack && !switching)) {
1752d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            startTime = latestMediaSegmentStartTime();
1753b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih        }
1754b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih
17558ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        // TRICKY: looping from i as earlier streams are already removed from streamMask
17568ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        for (size_t j = i; j < kMaxStreams; ++j) {
1757f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            const AString &streamUri = switching ? mStreams[j].mNewUri : mStreams[j].mUri;
1758f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            if ((streamMask & indexToType(j)) && uri == streamUri) {
17598ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                sources[j] = mPacketSources.valueFor(indexToType(j));
17601543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
1761309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                if (timeUs >= 0) {
1762d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                    startTime.mTimeUs = timeUs;
17631543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                } else {
1764309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    int32_t type;
1765309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    sp<AMessage> meta;
1766d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                    if (!switching) {
1767d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                        // selecting, or adapting but no swap required
1768309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        meta = sources[j]->getLatestDequeuedMeta();
1769309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    } else {
1770d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                        // adapting and swap required
1771309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        meta = sources[j]->getLatestEnqueuedMeta();
17727c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                        if (meta != NULL && mCurBandwidthIndex > mOrigBandwidthIndex) {
17737c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                            // switching up
17747c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                            meta = sources[j]->getMetaAfterLastDequeued(mUpSwitchMargin);
17757c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                        }
1776309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    }
17771543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
17780852843d304006e3ab333081fddda13b07193de8Robert Shih                    if ((j == kAudioIndex || j == kVideoIndex)
17790852843d304006e3ab333081fddda13b07193de8Robert Shih                            && meta != NULL && !meta->findInt32("discontinuity", &type)) {
1780d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                        HLSTime tmpTime(meta);
1781d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                        if (startTime < tmpTime) {
1782d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                            startTime = tmpTime;
17831543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        }
17841543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    }
17851543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
1786d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                    if (!switching) {
1787d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                        // selecting, or adapting but no swap required
1788309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        sources[j]->clear();
1789309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        if (j == kSubtitleIndex) {
1790309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                            break;
1791309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        }
1792964adb17885185808398507d2de88665fe193ee2Chong Zhang
17934604458dfe57b0e91a464aefafea50ae7b9876c1Chong Zhang                        ALOGV("stream[%zu]: queue format change", j);
1794964adb17885185808398507d2de88665fe193ee2Chong Zhang                        sources[j]->queueDiscontinuity(
1795a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                                ATSParser::DISCONTINUITY_FORMAT_ONLY, NULL, true);
1796309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    } else {
1797d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                        // switching, queue discontinuities after resume
1798309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        sources[j] = mPacketSources2.valueFor(indexToType(j));
1799309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        sources[j]->clear();
1800a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                        // the new fetcher might be providing streams that used to be
1801a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                        // provided by two different fetchers,  if one of the fetcher
1802a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                        // paused in the middle while the other somehow paused in next
1803a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                        // seg, we have to start from next seg.
1804a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                        if (seekMode < mStreams[j].mSeekMode) {
1805a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                            seekMode = mStreams[j].mSeekMode;
1806309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        }
18071543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    }
18081543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                }
1809a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
18108ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                streamMask &= ~indexToType(j);
18118ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            }
1812a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
181314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
181425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang        ALOGV("[fetcher-%d] startAsync: startTimeUs %lld mLastSeekTimeUs %lld "
181525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                "segmentStartTimeUs %lld seekMode %d",
181625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                fetcher->getFetcherID(),
181725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                (long long)startTime.mTimeUs,
181825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                (long long)mLastSeekTimeUs,
1819978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang                (long long)startTime.getSegmentTimeUs(),
182025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                seekMode);
182125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang
1822d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        // Set the target segment start time to the middle point of the
1823d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        // segment where the last sample was.
1824d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        // This gives a better guess if segments of the two variants are not
1825d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        // perfectly aligned. (If the corresponding segment in new variant
1826d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        // starts slightly later than that in the old variant, we still want
1827d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        // to pick that segment, not the one before)
18288ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        fetcher->startAsync(
18298ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                sources[kAudioIndex],
18308ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                sources[kVideoIndex],
18318ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                sources[kSubtitleIndex],
18320852843d304006e3ab333081fddda13b07193de8Robert Shih                getMetadataSource(sources, mNewStreamMask, switching),
1833d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                startTime.mTimeUs < 0 ? mLastSeekTimeUs : startTime.mTimeUs,
1834978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang                startTime.getSegmentTimeUs(),
1835d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang                startTime.mSeq,
1836a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                seekMode);
1837a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1838a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
183914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // All fetchers have now been started, the configuration change
184014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // has completed.
1841a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
184214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mReconfigurationInProgress = false;
18431543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    if (switching) {
18441543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        mSwitchInProgress = true;
18451543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    } else {
18461543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        mStreamMask = mNewStreamMask;
18478464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang        if (mOrigBandwidthIndex != mCurBandwidthIndex) {
18488464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            ALOGV("#### Finished Bandwidth Switch Early: %zd => %zd",
18498464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang                    mOrigBandwidthIndex, mCurBandwidthIndex);
18508464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            mOrigBandwidthIndex = mCurBandwidthIndex;
18518464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang        }
18521543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
1853a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
185425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    ALOGV("onChangeConfiguration3: mSwitchInProgress %d, mStreamMask 0x%x",
185525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            mSwitchInProgress, mStreamMask);
185625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang
1857c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang    if (mDisconnectReplyID != NULL) {
185814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        finishDisconnect();
1859a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
186014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
1861a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1862a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhangvoid LiveSession::swapPacketSource(StreamType stream) {
186325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    ALOGV("[%s] swapPacketSource", getNameForStream(stream));
1864a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
1865a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    // transfer packets from source2 to source
1866a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    sp<AnotherPacketSource> &aps = mPacketSources.editValueFor(stream);
1867a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    sp<AnotherPacketSource> &aps2 = mPacketSources2.editValueFor(stream);
1868a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
1869a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    // queue discontinuity in mPacketSource
1870a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    aps->queueDiscontinuity(ATSParser::DISCONTINUITY_FORMAT_ONLY, NULL, false);
1871a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
1872a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    // queue packets in mPacketSource2 to mPacketSource
1873a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    status_t finalResult = OK;
1874a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    sp<ABuffer> accessUnit;
1875a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    while (aps2->hasBufferAvailable(&finalResult) && finalResult == OK &&
1876a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang          OK == aps2->dequeueAccessUnit(&accessUnit)) {
1877a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        aps->queueAccessUnit(accessUnit);
1878a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    }
1879a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    aps2->clear();
1880a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang}
1881a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
18827c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::tryToFinishBandwidthSwitch(const AString &oldUri) {
1883a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    if (!mSwitchInProgress) {
1884a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        return;
1885a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    }
1886a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
18877c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    ssize_t index = mFetcherInfos.indexOfKey(oldUri);
1888a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    if (index < 0 || !mFetcherInfos[index].mToBeRemoved) {
18891543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return;
18901543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
18911543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
1892a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    // Swap packet source of streams provided by old variant
1893a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    for (size_t idx = 0; idx < kMaxStreams; idx++) {
18947c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        StreamType stream = indexToType(idx);
18957c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        if ((mSwapMask & stream) && (oldUri == mStreams[idx].mUri)) {
1896a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang            swapPacketSource(stream);
1897a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
1898a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang            if ((mNewStreamMask & stream) && mStreams[idx].mNewUri.empty()) {
1899a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                ALOGW("swapping stream type %d %s to empty stream",
1900a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                        stream, mStreams[idx].mUri.c_str());
1901a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang            }
1902a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang            mStreams[idx].mUri = mStreams[idx].mNewUri;
1903a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang            mStreams[idx].mNewUri.clear();
1904a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
1905a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang            mSwapMask &= ~stream;
1906a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        }
1907f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    }
1908f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih
19097c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    mFetcherInfos.editValueAt(index).mFetcher->stopAsync(false /* clear */);
1910a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
191125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang    ALOGV("tryToFinishBandwidthSwitch: mSwapMask=0x%x", mSwapMask);
1912309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    if (mSwapMask != 0) {
19131543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return;
19141543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
19151543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
19161543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // Check if new variant contains extra streams.
19171543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    uint32_t extraStreams = mNewStreamMask & (~mStreamMask);
19181543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    while (extraStreams) {
1919a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        StreamType stream = (StreamType) (extraStreams & ~(extraStreams - 1));
1920a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        extraStreams &= ~stream;
1921a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
1922a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        swapPacketSource(stream);
1923f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih
1924a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        ssize_t idx = typeToIndex(stream);
1925f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        CHECK(idx >= 0);
1926f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        if (mStreams[idx].mNewUri.empty()) {
1927f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            ALOGW("swapping extra stream type %d %s to empty stream",
1928a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang                    stream, mStreams[idx].mUri.c_str());
1929f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        }
1930f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        mStreams[idx].mUri = mStreams[idx].mNewUri;
1931f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        mStreams[idx].mNewUri.clear();
19321543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
19331543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
1934a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    // Restart new fetcher (it was paused after the first 47k block)
1935a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    // and let it fetch into mPacketSources (not mPacketSources2)
1936a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
1937a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        FetcherInfo &info = mFetcherInfos.editValueAt(i);
1938a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        if (info.mToBeResumed) {
19397c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            resumeFetcher(mFetcherInfos.keyAt(i), mNewStreamMask);
1940a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang            info.mToBeResumed = false;
1941a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        }
1942a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    }
1943a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
19447c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    ALOGI("#### Finished Bandwidth Switch: %zd => %zd",
19457c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            mOrigBandwidthIndex, mCurBandwidthIndex);
19467c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
1947a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    mStreamMask = mNewStreamMask;
1948a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang    mSwitchInProgress = false;
19497c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    mOrigBandwidthIndex = mCurBandwidthIndex;
1950a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang
19517c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    restartPollBuffering();
19521543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
19531543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
1954964adb17885185808398507d2de88665fe193ee2Chong Zhangvoid LiveSession::schedulePollBuffering() {
1955964adb17885185808398507d2de88665fe193ee2Chong Zhang    sp<AMessage> msg = new AMessage(kWhatPollBuffering, this);
1956964adb17885185808398507d2de88665fe193ee2Chong Zhang    msg->setInt32("generation", mPollBufferingGeneration);
1957964adb17885185808398507d2de88665fe193ee2Chong Zhang    msg->post(1000000ll);
1958964adb17885185808398507d2de88665fe193ee2Chong Zhang}
1959678bcdc852dd8f801f5c46fdc85db587b721d83dApurupa Pattapu
1960964adb17885185808398507d2de88665fe193ee2Chong Zhangvoid LiveSession::cancelPollBuffering() {
1961964adb17885185808398507d2de88665fe193ee2Chong Zhang    ++mPollBufferingGeneration;
19627c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    mPrevBufferPercentage = -1;
19637c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang}
19647c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
19657c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::restartPollBuffering() {
19667c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    cancelPollBuffering();
19677c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    onPollBuffering();
1968964adb17885185808398507d2de88665fe193ee2Chong Zhang}
19690ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
1970964adb17885185808398507d2de88665fe193ee2Chong Zhangvoid LiveSession::onPollBuffering() {
1971964adb17885185808398507d2de88665fe193ee2Chong Zhang    ALOGV("onPollBuffering: mSwitchInProgress %d, mReconfigurationInProgress %d, "
1972a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang            "mInPreparationPhase %d, mCurBandwidthIndex %zd, mStreamMask 0x%x",
1973964adb17885185808398507d2de88665fe193ee2Chong Zhang        mSwitchInProgress, mReconfigurationInProgress,
1974538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        mInPreparationPhase, mCurBandwidthIndex, mStreamMask);
19750ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
19767c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    bool underflow, ready, down, up;
19777c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    if (checkBuffering(underflow, ready, down, up)) {
19788464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang        if (mInPreparationPhase) {
19798464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            // Allow down switch even if we're still preparing.
19808464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            //
19818464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            // Some streams have a high bandwidth index as default,
19828464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            // when bandwidth is low, it takes a long time to buffer
19838464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            // to ready mark, then it immediately pauses after start
19848464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            // as we have to do a down switch. It's better experience
19858464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            // to restart from a lower index, if we detect low bw.
19868464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            if (!switchBandwidthIfNeeded(false /* up */, down) && ready) {
19878464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang                postPrepared(OK);
19888464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            }
19890ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        }
19900ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
1991538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        if (!mInPreparationPhase) {
19927c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            if (ready) {
19937c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                stopBufferingIfNecessary();
19947c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            } else if (underflow) {
19957c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                startBufferingIfNecessary();
19967c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            }
19977c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            switchBandwidthIfNeeded(up, down);
19988464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang        }
19990ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    }
20000ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
2001964adb17885185808398507d2de88665fe193ee2Chong Zhang    schedulePollBuffering();
20020ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih}
20030ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
20047c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::cancelBandwidthSwitch(bool resume) {
20057c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    ALOGV("cancelBandwidthSwitch: mSwitchGen(%d)++, orig %zd, cur %zd",
20067c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            mSwitchGeneration, mOrigBandwidthIndex, mCurBandwidthIndex);
20077c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    if (!mSwitchInProgress) {
20087c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        return;
20097c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    }
2010f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih
2011f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
2012f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        FetcherInfo& info = mFetcherInfos.editValueAt(i);
2013f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        if (info.mToBeRemoved) {
2014f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            info.mToBeRemoved = false;
20157c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            if (resume) {
20167c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                resumeFetcher(mFetcherInfos.keyAt(i), mSwapMask);
20177c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            }
2018f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        }
2019f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    }
2020f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih
2021f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
20227c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        AString newUri = mStreams[i].mNewUri;
20237c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        if (!newUri.empty()) {
20247c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            // clear all mNewUri matching this newUri
20257c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            for (size_t j = i; j < kMaxStreams; ++j) {
20267c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                if (mStreams[j].mNewUri == newUri) {
20277c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                    mStreams[j].mNewUri.clear();
20287c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                }
20297c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            }
20307c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            ALOGV("stopping newUri = %s", newUri.c_str());
20317c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            ssize_t index = mFetcherInfos.indexOfKey(newUri);
20327c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            if (index < 0) {
20337c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                ALOGE("did not find fetcher for newUri: %s", newUri.c_str());
2034f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih                continue;
2035f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            }
20367c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            FetcherInfo &info = mFetcherInfos.editValueAt(index);
20377c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            info.mToBeRemoved = true;
2038f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            info.mFetcher->stopAsync();
2039f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        }
2040f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    }
20417c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
20427c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    ALOGI("#### Canceled Bandwidth Switch: %zd => %zd",
204325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang            mOrigBandwidthIndex, mCurBandwidthIndex);
20447c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
20457c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    mSwitchGeneration++;
20467c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    mSwitchInProgress = false;
20477c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    mCurBandwidthIndex = mOrigBandwidthIndex;
20487c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    mSwapMask = 0;
20491543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
20501543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
20517c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangbool LiveSession::checkBuffering(
20527c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        bool &underflow, bool &ready, bool &down, bool &up) {
20537c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    underflow = ready = down = up = false;
2054964adb17885185808398507d2de88665fe193ee2Chong Zhang
20557c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    if (mReconfigurationInProgress) {
2056964adb17885185808398507d2de88665fe193ee2Chong Zhang        ALOGV("Switch/Reconfig in progress, defer buffer polling");
20571543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return false;
20581543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
20591543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
20607c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    size_t activeCount, underflowCount, readyCount, downCount, upCount;
20617c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    activeCount = underflowCount = readyCount = downCount = upCount =0;
20627c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    int32_t minBufferPercent = -1;
20637c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    int64_t durationUs;
20647c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    if (getDuration(&durationUs) != OK) {
20657c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        durationUs = -1;
20667c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    }
2067964adb17885185808398507d2de88665fe193ee2Chong Zhang    for (size_t i = 0; i < mPacketSources.size(); ++i) {
2068964adb17885185808398507d2de88665fe193ee2Chong Zhang        // we don't check subtitles for buffering level
2069964adb17885185808398507d2de88665fe193ee2Chong Zhang        if (!(mStreamMask & mPacketSources.keyAt(i)
2070964adb17885185808398507d2de88665fe193ee2Chong Zhang                & (STREAMTYPE_AUDIO | STREAMTYPE_VIDEO))) {
2071964adb17885185808398507d2de88665fe193ee2Chong Zhang            continue;
2072964adb17885185808398507d2de88665fe193ee2Chong Zhang        }
2073964adb17885185808398507d2de88665fe193ee2Chong Zhang        // ignore streams that never had any packet queued.
2074964adb17885185808398507d2de88665fe193ee2Chong Zhang        // (it's possible that the variant only has audio or video)
2075964adb17885185808398507d2de88665fe193ee2Chong Zhang        sp<AMessage> meta = mPacketSources[i]->getLatestEnqueuedMeta();
2076964adb17885185808398507d2de88665fe193ee2Chong Zhang        if (meta == NULL) {
2077964adb17885185808398507d2de88665fe193ee2Chong Zhang            continue;
2078964adb17885185808398507d2de88665fe193ee2Chong Zhang        }
2079964adb17885185808398507d2de88665fe193ee2Chong Zhang
20800dd229bb306df68b88e7419b3cc11fc6175be1daRobert Shih        status_t finalResult;
2081964adb17885185808398507d2de88665fe193ee2Chong Zhang        int64_t bufferedDurationUs =
20820dd229bb306df68b88e7419b3cc11fc6175be1daRobert Shih                mPacketSources[i]->getBufferedDurationUs(&finalResult);
208325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang        ALOGV("[%s] buffered %lld us",
208425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                getNameForStream(mPacketSources.keyAt(i)),
208525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang                (long long)bufferedDurationUs);
20867c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        if (durationUs >= 0) {
20877c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            int32_t percent;
20887c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            if (mPacketSources[i]->isFinished(0 /* duration */)) {
20897c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                percent = 100;
20907c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            } else {
20918464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang                percent = (int32_t)(100.0 *
20928464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang                        (mLastDequeuedTimeUs + bufferedDurationUs) / durationUs);
20937c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            }
20947c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            if (minBufferPercent < 0 || percent < minBufferPercent) {
20957c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                minBufferPercent = percent;
20967c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            }
2097964adb17885185808398507d2de88665fe193ee2Chong Zhang        }
20987c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
20997c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        ++activeCount;
2100765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang        int64_t readyMark = mInPreparationPhase ? kPrepareMarkUs : kReadyMarkUs;
21017c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        if (bufferedDurationUs > readyMark
21027c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                || mPacketSources[i]->isFinished(0)) {
21037c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            ++readyCount;
21047c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        }
21057c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        if (!mPacketSources[i]->isFinished(0)) {
2106765f27c2376e83766d9e1d8f8136025c5437ce49Chong Zhang            if (bufferedDurationUs < kUnderflowMarkUs) {
21077c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                ++underflowCount;
21087c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            }
21097c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            if (bufferedDurationUs > mUpSwitchMark) {
21107c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                ++upCount;
2111d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            }
2112d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            if (bufferedDurationUs < mDownSwitchMark) {
21137c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang                ++downCount;
21147c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            }
21157c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        }
21167c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    }
21177c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
21187c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    if (minBufferPercent >= 0) {
21197c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        notifyBufferingUpdate(minBufferPercent);
212014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
212114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
2122964adb17885185808398507d2de88665fe193ee2Chong Zhang    if (activeCount > 0) {
21237c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        up        = (upCount == activeCount);
21247c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        down      = (downCount > 0);
21257c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        ready     = (readyCount == activeCount);
21267c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        underflow = (underflowCount > 0);
21271543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return true;
21281543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
2129964adb17885185808398507d2de88665fe193ee2Chong Zhang
2130964adb17885185808398507d2de88665fe193ee2Chong Zhang    return false;
21311543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
21321543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
21337c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::startBufferingIfNecessary() {
21347c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    ALOGV("startBufferingIfNecessary: mInPreparationPhase=%d, mBuffering=%d",
21357c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            mInPreparationPhase, mBuffering);
21367c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    if (!mBuffering) {
21377c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        mBuffering = true;
21387c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
21397c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        sp<AMessage> notify = mNotify->dup();
21407c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        notify->setInt32("what", kWhatBufferingStart);
21417c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        notify->post();
21427c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    }
21437c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang}
21447c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
21457c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::stopBufferingIfNecessary() {
21467c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    ALOGV("stopBufferingIfNecessary: mInPreparationPhase=%d, mBuffering=%d",
21477c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang            mInPreparationPhase, mBuffering);
21487c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
21497c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    if (mBuffering) {
21507c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        mBuffering = false;
21517c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
21527c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        sp<AMessage> notify = mNotify->dup();
21537c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        notify->setInt32("what", kWhatBufferingEnd);
21547c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        notify->post();
21557c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    }
21567c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang}
21577c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
21587c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::notifyBufferingUpdate(int32_t percentage) {
21597c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    if (percentage < mPrevBufferPercentage) {
21607c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        percentage = mPrevBufferPercentage;
21617c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    } else if (percentage > 100) {
21627c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        percentage = 100;
21637c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    }
21647c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
21657c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    mPrevBufferPercentage = percentage;
21667c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
21677c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    ALOGV("notifyBufferingUpdate: percentage=%d%%", percentage);
21687c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
21697c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    sp<AMessage> notify = mNotify->dup();
21707c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    notify->setInt32("what", kWhatBufferingUpdate);
21717c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    notify->setInt32("percentage", percentage);
21727c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    notify->post();
21737c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang}
21747c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
21758464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang/*
21768464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang * returns true if a bandwidth switch is actually needed (and started),
21778464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang * returns false otherwise
21788464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang */
21798464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhangbool LiveSession::switchBandwidthIfNeeded(bool bufferHigh, bool bufferLow) {
2180538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    // no need to check bandwidth if we only have 1 bandwidth settings
21817c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    if (mSwitchInProgress || mBandwidthItems.size() < 2) {
21828464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang        return false;
2183538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    }
2184538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
2185538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    int32_t bandwidthBps;
2186978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    bool isStable;
2187978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    if (mBandwidthEstimator->estimateBandwidth(&bandwidthBps, &isStable)) {
2188538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        ALOGV("bandwidth estimated at %.2f kbps", bandwidthBps / 1024.0f);
2189a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang        mLastBandwidthBps = bandwidthBps;
2190538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    } else {
2191538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        ALOGV("no bandwidth estimate.");
21928464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang        return false;
2193538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    }
2194538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
2195538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang    int32_t curBandwidth = mBandwidthItems.itemAt(mCurBandwidthIndex).mBandwidth;
2196d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang    // canSwithDown and canSwitchUp can't both be true.
2197d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang    // we only want to switch up when measured bw is 120% higher than current variant,
2198d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang    // and we only want to switch down when measured bw is below current variant.
2199978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    bool canSwitchDown = bufferLow
2200d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            && (bandwidthBps < (int32_t)curBandwidth);
2201d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang    bool canSwitchUp = bufferHigh
2202d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang            && (bandwidthBps > (int32_t)curBandwidth * 12 / 10);
2203d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang
2204978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang    if (canSwitchDown || canSwitchUp) {
2205978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang        // bandwidth estimating has some delay, if we have to downswitch when
2206978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang        // it hasn't stabilized, be very conservative on bandwidth.
2207978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang        if (!isStable && canSwitchDown) {
2208978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang            bandwidthBps /= 2;
2209978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang        }
2210978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang
2211538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        ssize_t bandwidthIndex = getBandwidthIndex(bandwidthBps);
2212538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang
2213d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        // it's possible that we're checking for canSwitchUp case, but the returned
2214d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        // bandwidthIndex is < mCurBandwidthIndex, as getBandwidthIndex() only uses 70%
2215d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        // of measured bw. In that case we don't want to do anything, since we have
2216d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang        // both enough buffer and enough bw.
22178464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang        if ((canSwitchUp && bandwidthIndex > mCurBandwidthIndex)
2218978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang         || (canSwitchDown && bandwidthIndex < mCurBandwidthIndex)) {
22198464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            // if not yet prepared, just restart again with new bw index.
22208464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            // this is faster and playback experience is cleaner.
22218464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            changeConfiguration(
22228464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang                    mInPreparationPhase ? 0 : -1ll, bandwidthIndex);
22238464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang            return true;
2224538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang        }
222514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
22268464d7decb34a3044e92b4085f1bbaafb51410e8Chong Zhang    return false;
2227a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
2228a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
22297c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid LiveSession::postError(status_t err) {
22307c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    // if we reached EOS, notify buffering of 100%
22317c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    if (err == ERROR_END_OF_STREAM) {
22327c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        notifyBufferingUpdate(100);
22337c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    }
22347c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    // we'll stop buffer polling now, before that notify
22357c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    // stop buffering to stop the spinning icon
22367c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    stopBufferingIfNecessary();
22377c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    cancelPollBuffering();
22387c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
22397c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    sp<AMessage> notify = mNotify->dup();
22407c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    notify->setInt32("what", kWhatError);
22417c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    notify->setInt32("err", err);
22427c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang    notify->post();
22437c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang}
22447c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
224514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::postPrepared(status_t err) {
224614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(mInPreparationPhase);
2247a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
224814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> notify = mNotify->dup();
224914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (err == OK || err == ERROR_END_OF_STREAM) {
225014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        notify->setInt32("what", kWhatPrepared);
225114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    } else {
22527c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang        cancelPollBuffering();
22537c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang
225414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        notify->setInt32("what", kWhatPreparationFailed);
225514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        notify->setInt32("err", err);
225614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
2257a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
225814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->post();
2259a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
226014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mInPreparationPhase = false;
2261b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber}
2262b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
2263964adb17885185808398507d2de88665fe193ee2Chong Zhang
2264a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}  // namespace android
2265a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
2266