LiveSession.cpp revision b3f9759c8c9437c45b9a34519ce2ea38a8314d4e
1a44153c1a57202fb538659eb50706e60454d6273Andreas Huber/*
2a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * Copyright (C) 2010 The Android Open Source Project
3a44153c1a57202fb538659eb50706e60454d6273Andreas Huber *
4a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * you may not use this file except in compliance with the License.
6a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * You may obtain a copy of the License at
7a44153c1a57202fb538659eb50706e60454d6273Andreas Huber *
8a44153c1a57202fb538659eb50706e60454d6273Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
9a44153c1a57202fb538659eb50706e60454d6273Andreas Huber *
10a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * Unless required by applicable law or agreed to in writing, software
11a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * See the License for the specific language governing permissions and
14a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * limitations under the License.
15a44153c1a57202fb538659eb50706e60454d6273Andreas Huber */
16a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
17a44153c1a57202fb538659eb50706e60454d6273Andreas Huber//#define LOG_NDEBUG 0
18a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#define LOG_TAG "LiveSession"
19a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <utils/Log.h>
20a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
2114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include "LiveSession.h"
22a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
2314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include "M3UParser.h"
2414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include "PlaylistFetcher.h"
25a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
261156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber#include "include/HTTPBase.h"
2714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include "mpeg2ts/AnotherPacketSource.h"
28a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
29a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <cutils/properties.h>
301b86fe063badb5f28c467ade39be0f4008688947Andreas Huber#include <media/IMediaHTTPConnection.h>
311b86fe063badb5f28c467ade39be0f4008688947Andreas Huber#include <media/IMediaHTTPService.h>
32a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <media/stagefright/foundation/hexdump.h>
33a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <media/stagefright/foundation/ABuffer.h>
34a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <media/stagefright/foundation/ADebug.h>
35a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <media/stagefright/foundation/AMessage.h>
36a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <media/stagefright/DataSource.h>
37a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <media/stagefright/FileSource.h>
38a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <media/stagefright/MediaErrors.h>
391b86fe063badb5f28c467ade39be0f4008688947Andreas Huber#include <media/stagefright/MediaHTTP.h>
4014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include <media/stagefright/MetaData.h>
4114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include <media/stagefright/Utils.h>
42a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
431543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih#include <utils/Mutex.h>
441543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
45a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <ctype.h>
46b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross#include <inttypes.h>
47a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <openssl/aes.h>
487e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber#include <openssl/md5.h>
49a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
50a44153c1a57202fb538659eb50706e60454d6273Andreas Hubernamespace android {
51a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
520df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas HuberLiveSession::LiveSession(
531b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        const sp<AMessage> &notify, uint32_t flags,
5481e68448f3361eaf8618930471fdc3c21bdf5cbcAndreas Huber        const sp<IMediaHTTPService> &httpService)
550df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas Huber    : mNotify(notify),
560df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas Huber      mFlags(flags),
571b86fe063badb5f28c467ade39be0f4008688947Andreas Huber      mHTTPService(httpService),
580df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas Huber      mInPreparationPhase(true),
591b86fe063badb5f28c467ade39be0f4008688947Andreas Huber      mHTTPDataSource(new MediaHTTP(mHTTPService->makeHTTPConnection())),
60309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih      mCurBandwidthIndex(-1),
6114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber      mStreamMask(0),
621543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih      mNewStreamMask(0),
631543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih      mSwapMask(0),
6414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber      mCheckBandwidthGeneration(0),
651543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih      mSwitchGeneration(0),
66b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih      mSubtitleGeneration(0),
6714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber      mLastDequeuedTimeUs(0ll),
68dcb89b3b505522efde173c105a851c412f947178Chong Zhang      mRealTimeBaseUs(0ll),
6914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber      mReconfigurationInProgress(false),
701543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih      mSwitchInProgress(false),
715ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih      mDisconnectReplyID(0),
72309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih      mSeekReplyID(0),
73309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih      mFirstTimeUsValid(false),
74309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih      mFirstTimeUs(0),
75309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih      mLastSeekTimeUs(0) {
7614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
778ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    mStreams[kAudioIndex] = StreamItem("audio");
788ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    mStreams[kVideoIndex] = StreamItem("video");
79e4f25c280a8f1655c31a745978e0fcbc61f91deeRobert Shih    mStreams[kSubtitleIndex] = StreamItem("subtitles");
8014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
818ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
82309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        mDiscontinuities.add(indexToType(i), new AnotherPacketSource(NULL /* meta */));
838ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        mPacketSources.add(indexToType(i), new AnotherPacketSource(NULL /* meta */));
841543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        mPacketSources2.add(indexToType(i), new AnotherPacketSource(NULL /* meta */));
85f69c996864844e8f669308af8412cede043062a2Robert Shih        mBuffering[i] = false;
868ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    }
87a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
88a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
89a44153c1a57202fb538659eb50706e60454d6273Andreas HuberLiveSession::~LiveSession() {
90a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
91a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
921543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shihsp<ABuffer> LiveSession::createFormatChangeBuffer(bool swap) {
931543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    ABuffer *discontinuity = new ABuffer(0);
941543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    discontinuity->meta()->setInt32("discontinuity", ATSParser::DISCONTINUITY_FORMATCHANGE);
951543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    discontinuity->meta()->setInt32("swapPacketSource", swap);
961543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    discontinuity->meta()->setInt32("switchGeneration", mSwitchGeneration);
971543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    discontinuity->meta()->setInt64("timeUs", -1);
981543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    return discontinuity;
991543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
1001543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
1011543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shihvoid LiveSession::swapPacketSource(StreamType stream) {
1021543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    sp<AnotherPacketSource> &aps = mPacketSources.editValueFor(stream);
1031543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    sp<AnotherPacketSource> &aps2 = mPacketSources2.editValueFor(stream);
1041543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    sp<AnotherPacketSource> tmp = aps;
1051543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    aps = aps2;
1061543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    aps2 = tmp;
1071543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    aps2->clear();
1081543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
1091543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
11014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::dequeueAccessUnit(
11114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        StreamType stream, sp<ABuffer> *accessUnit) {
11214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (!(mStreamMask & stream)) {
1131543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        // return -EWOULDBLOCK to avoid halting the decoder
1141543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        // when switching between audio/video and audio only.
1151543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return -EWOULDBLOCK;
11614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
11714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
118309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    status_t finalResult;
119309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    sp<AnotherPacketSource> discontinuityQueue  = mDiscontinuities.valueFor(stream);
120309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    if (discontinuityQueue->hasBufferAvailable(&finalResult)) {
121309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        discontinuityQueue->dequeueAccessUnit(accessUnit);
122309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        // seeking, track switching
123309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        sp<AMessage> extra;
124309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        int64_t timeUs;
125309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        if ((*accessUnit)->meta()->findMessage("extra", &extra)
126309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                && extra != NULL
127309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                && extra->findInt64("timeUs", &timeUs)) {
128309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            // seeking only
129309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            mLastSeekTimeUs = timeUs;
130309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            mDiscontinuityOffsetTimesUs.clear();
131309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            mDiscontinuityAbsStartTimesUs.clear();
132309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        }
133309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        return INFO_DISCONTINUITY;
134309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    }
135309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
13614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AnotherPacketSource> packetSource = mPacketSources.valueFor(stream);
13714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
138f69c996864844e8f669308af8412cede043062a2Robert Shih    ssize_t idx = typeToIndex(stream);
13914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (!packetSource->hasBufferAvailable(&finalResult)) {
140f69c996864844e8f669308af8412cede043062a2Robert Shih        if (finalResult == OK) {
141f69c996864844e8f669308af8412cede043062a2Robert Shih            mBuffering[idx] = true;
142f69c996864844e8f669308af8412cede043062a2Robert Shih            return -EAGAIN;
143f69c996864844e8f669308af8412cede043062a2Robert Shih        } else {
144f69c996864844e8f669308af8412cede043062a2Robert Shih            return finalResult;
145f69c996864844e8f669308af8412cede043062a2Robert Shih        }
146f69c996864844e8f669308af8412cede043062a2Robert Shih    }
147f69c996864844e8f669308af8412cede043062a2Robert Shih
148f69c996864844e8f669308af8412cede043062a2Robert Shih    if (mBuffering[idx]) {
149f69c996864844e8f669308af8412cede043062a2Robert Shih        if (mSwitchInProgress
150f69c996864844e8f669308af8412cede043062a2Robert Shih                || packetSource->isFinished(0)
151f69c996864844e8f669308af8412cede043062a2Robert Shih                || packetSource->getEstimatedDurationUs() > 10000000ll) {
152f69c996864844e8f669308af8412cede043062a2Robert Shih            mBuffering[idx] = false;
153f69c996864844e8f669308af8412cede043062a2Robert Shih        }
154f69c996864844e8f669308af8412cede043062a2Robert Shih    }
155f69c996864844e8f669308af8412cede043062a2Robert Shih
156f69c996864844e8f669308af8412cede043062a2Robert Shih    if (mBuffering[idx]) {
157f69c996864844e8f669308af8412cede043062a2Robert Shih        return -EAGAIN;
15814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
15914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
160309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    // wait for counterpart
161309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    sp<AnotherPacketSource> otherSource;
16273d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih    uint32_t mask = mNewStreamMask & mStreamMask;
16373d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih    uint32_t fetchersMask  = 0;
16473d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
16573d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih        uint32_t fetcherMask = mFetcherInfos.valueAt(i).mFetcher->getStreamTypeMask();
16673d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih        fetchersMask |= fetcherMask;
16773d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih    }
16873d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih    mask &= fetchersMask;
16973d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih    if (stream == STREAMTYPE_AUDIO && (mask & STREAMTYPE_VIDEO)) {
170309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        otherSource = mPacketSources.valueFor(STREAMTYPE_VIDEO);
17173d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih    } else if (stream == STREAMTYPE_VIDEO && (mask & STREAMTYPE_AUDIO)) {
172309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        otherSource = mPacketSources.valueFor(STREAMTYPE_AUDIO);
173309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    }
174309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    if (otherSource != NULL && !otherSource->hasBufferAvailable(&finalResult)) {
175309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        return finalResult == OK ? -EAGAIN : finalResult;
176309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    }
177309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
17814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    status_t err = packetSource->dequeueAccessUnit(accessUnit);
17914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
180309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    size_t streamIdx;
18114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    const char *streamStr;
18214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    switch (stream) {
18314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case STREAMTYPE_AUDIO:
184309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            streamIdx = kAudioIndex;
18514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            streamStr = "audio";
18614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            break;
18714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case STREAMTYPE_VIDEO:
188309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            streamIdx = kVideoIndex;
18914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            streamStr = "video";
19014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            break;
19114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case STREAMTYPE_SUBTITLES:
192309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            streamIdx = kSubtitleIndex;
19314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            streamStr = "subs";
19414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            break;
19514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        default:
19614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            TRESPASS();
19714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
19814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
199309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    StreamItem& strm = mStreams[streamIdx];
20014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (err == INFO_DISCONTINUITY) {
201309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        // adaptive streaming, discontinuities in the playlist
20214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        int32_t type;
20314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        CHECK((*accessUnit)->meta()->findInt32("discontinuity", &type));
20414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
20514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        sp<AMessage> extra;
20614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (!(*accessUnit)->meta()->findMessage("extra", &extra)) {
20714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            extra.clear();
20814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
20914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
21014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        ALOGI("[%s] read discontinuity of type %d, extra = %s",
21114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber              streamStr,
21214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber              type,
21314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber              extra == NULL ? "NULL" : extra->debugString().c_str());
2141543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
2151543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        int32_t swap;
216309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        if ((*accessUnit)->meta()->findInt32("swapPacketSource", &swap) && swap) {
2171543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            int32_t switchGeneration;
2181543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            CHECK((*accessUnit)->meta()->findInt32("switchGeneration", &switchGeneration));
2191543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            {
2201543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                Mutex::Autolock lock(mSwapMutex);
2211543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                if (switchGeneration == mSwitchGeneration) {
2221543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    swapPacketSource(stream);
2231543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    sp<AMessage> msg = new AMessage(kWhatSwapped, id());
2241543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    msg->setInt32("stream", stream);
2251543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    msg->setInt32("switchGeneration", switchGeneration);
2261543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    msg->post();
2271543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                }
2281543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            }
229309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        } else {
230309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            size_t seq = strm.mCurDiscontinuitySeq;
231309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            int64_t offsetTimeUs;
232309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            if (mDiscontinuityOffsetTimesUs.indexOfKey(seq) >= 0) {
233309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                offsetTimeUs = mDiscontinuityOffsetTimesUs.valueFor(seq);
234309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            } else {
235309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                offsetTimeUs = 0;
236309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            }
237309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
238309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            seq += 1;
239309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            if (mDiscontinuityAbsStartTimesUs.indexOfKey(strm.mCurDiscontinuitySeq) >= 0) {
240309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                int64_t firstTimeUs;
241309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                firstTimeUs = mDiscontinuityAbsStartTimesUs.valueFor(strm.mCurDiscontinuitySeq);
242309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                offsetTimeUs += strm.mLastDequeuedTimeUs - firstTimeUs;
243309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                offsetTimeUs += strm.mLastSampleDurationUs;
244309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            } else {
245309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                offsetTimeUs += strm.mLastSampleDurationUs;
246309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            }
247309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
248309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            mDiscontinuityOffsetTimesUs.add(seq, offsetTimeUs);
2491543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        }
25014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    } else if (err == OK) {
251309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
252dcb89b3b505522efde173c105a851c412f947178Chong Zhang        if (stream == STREAMTYPE_AUDIO || stream == STREAMTYPE_VIDEO) {
253dcb89b3b505522efde173c105a851c412f947178Chong Zhang            int64_t timeUs;
254309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            int32_t discontinuitySeq = 0;
255dcb89b3b505522efde173c105a851c412f947178Chong Zhang            CHECK((*accessUnit)->meta()->findInt64("timeUs",  &timeUs));
256309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            (*accessUnit)->meta()->findInt32("discontinuitySeq", &discontinuitySeq);
257309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            strm.mCurDiscontinuitySeq = discontinuitySeq;
258309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
259309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            int32_t discard = 0;
260309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            int64_t firstTimeUs;
261309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            if (mDiscontinuityAbsStartTimesUs.indexOfKey(strm.mCurDiscontinuitySeq) >= 0) {
262309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                int64_t durUs; // approximate sample duration
263309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                if (timeUs > strm.mLastDequeuedTimeUs) {
264309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    durUs = timeUs - strm.mLastDequeuedTimeUs;
265309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                } else {
266309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    durUs = strm.mLastDequeuedTimeUs - timeUs;
267309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                }
268309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                strm.mLastSampleDurationUs = durUs;
269309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                firstTimeUs = mDiscontinuityAbsStartTimesUs.valueFor(strm.mCurDiscontinuitySeq);
270309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            } else if ((*accessUnit)->meta()->findInt32("discard", &discard) && discard) {
271309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                firstTimeUs = timeUs;
272309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            } else {
273309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                mDiscontinuityAbsStartTimesUs.add(strm.mCurDiscontinuitySeq, timeUs);
274309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                firstTimeUs = timeUs;
275309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            }
276309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
277309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            strm.mLastDequeuedTimeUs = timeUs;
278309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            if (timeUs >= firstTimeUs) {
279309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                timeUs -= firstTimeUs;
280309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            } else {
281309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                timeUs = 0;
282309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            }
283309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            timeUs += mLastSeekTimeUs;
284309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            if (mDiscontinuityOffsetTimesUs.indexOfKey(discontinuitySeq) >= 0) {
285309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                timeUs += mDiscontinuityOffsetTimesUs.valueFor(discontinuitySeq);
286309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            }
287dcb89b3b505522efde173c105a851c412f947178Chong Zhang
288309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            ALOGV("[%s] read buffer at time %" PRId64 " us", streamStr, timeUs);
289309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            (*accessUnit)->meta()->setInt64("timeUs",  timeUs);
290dcb89b3b505522efde173c105a851c412f947178Chong Zhang            mLastDequeuedTimeUs = timeUs;
291dcb89b3b505522efde173c105a851c412f947178Chong Zhang            mRealTimeBaseUs = ALooper::GetNowUs() - timeUs;
292dcb89b3b505522efde173c105a851c412f947178Chong Zhang        } else if (stream == STREAMTYPE_SUBTITLES) {
293b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih            int32_t subtitleGeneration;
294b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih            if ((*accessUnit)->meta()->findInt32("subtitleGeneration", &subtitleGeneration)
295b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih                    && subtitleGeneration != mSubtitleGeneration) {
296b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih               return -EAGAIN;
297b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih            };
298dcb89b3b505522efde173c105a851c412f947178Chong Zhang            (*accessUnit)->meta()->setInt32(
299dcb89b3b505522efde173c105a851c412f947178Chong Zhang                    "trackIndex", mPlaylist->getSelectedIndex());
300dcb89b3b505522efde173c105a851c412f947178Chong Zhang            (*accessUnit)->meta()->setInt64("baseUs", mRealTimeBaseUs);
301dcb89b3b505522efde173c105a851c412f947178Chong Zhang        }
30214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    } else {
30314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        ALOGI("[%s] encountered error %d", streamStr, err);
30414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
30514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
30614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return err;
30714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
30814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
30914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::getStreamFormat(StreamType stream, sp<AMessage> *format) {
3101543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // No swapPacketSource race condition; called from the same thread as dequeueAccessUnit.
31114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (!(mStreamMask & stream)) {
31214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        return UNKNOWN_ERROR;
31314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
31414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
31514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AnotherPacketSource> packetSource = mPacketSources.valueFor(stream);
31614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
31714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<MetaData> meta = packetSource->getFormat();
31814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
31914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (meta == NULL) {
32014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        return -EAGAIN;
32114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
32214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
32314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return convertMetaDataToMessage(meta, format);
324a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
325a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
32614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::connectAsync(
327ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        const char *url, const KeyedVector<String8, String8> *headers) {
328a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<AMessage> msg = new AMessage(kWhatConnect, id());
329a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    msg->setString("url", url);
330ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber
331ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    if (headers != NULL) {
332ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        msg->setPointer(
333ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber                "headers",
334ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber                new KeyedVector<String8, String8>(*headers));
335ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    }
336ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber
337a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    msg->post();
338a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
339a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
34014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::disconnect() {
34114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> msg = new AMessage(kWhatDisconnect, id());
342ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
34314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> response;
34414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    status_t err = msg->postAndAwaitResponse(&response);
345ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
34614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return err;
347a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
348a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
34914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::seekTo(int64_t timeUs) {
350a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<AMessage> msg = new AMessage(kWhatSeek, id());
351a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    msg->setInt64("timeUs", timeUs);
352a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
35314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> response;
35414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    status_t err = msg->postAndAwaitResponse(&response);
35514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
35614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return err;
357a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
358a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
359a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onMessageReceived(const sp<AMessage> &msg) {
360a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    switch (msg->what()) {
361a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        case kWhatConnect:
36214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
363a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            onConnect(msg);
364a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
36514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
366a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
367a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        case kWhatDisconnect:
36814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
36914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            CHECK(msg->senderAwaitsResponse(&mDisconnectReplyID));
37014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
37114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            if (mReconfigurationInProgress) {
37214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                break;
37314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            }
37414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
37514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            finishDisconnect();
376a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
37714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
378a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
37914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case kWhatSeek:
38014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
381800599cdd50737de1cde483a34b39923750b0658Robert Shih            uint32_t seekReplyID;
382800599cdd50737de1cde483a34b39923750b0658Robert Shih            CHECK(msg->senderAwaitsResponse(&seekReplyID));
383800599cdd50737de1cde483a34b39923750b0658Robert Shih            mSeekReplyID = seekReplyID;
384800599cdd50737de1cde483a34b39923750b0658Robert Shih            mSeekReply = new AMessage;
38514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
38614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            status_t err = onSeek(msg);
38714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
388800599cdd50737de1cde483a34b39923750b0658Robert Shih            if (err != OK) {
389800599cdd50737de1cde483a34b39923750b0658Robert Shih                msg->post(50000);
390800599cdd50737de1cde483a34b39923750b0658Robert Shih            }
39114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            break;
39214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
39314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
39414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case kWhatFetcherNotify:
39514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
39614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            int32_t what;
39714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            CHECK(msg->findInt32("what", &what));
39814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
39914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            switch (what) {
40014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                case PlaylistFetcher::kWhatStarted:
40114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    break;
40214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                case PlaylistFetcher::kWhatPaused:
40314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                case PlaylistFetcher::kWhatStopped:
40414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                {
40514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    if (what == PlaylistFetcher::kWhatStopped) {
40614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        AString uri;
40714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        CHECK(msg->findString("uri", &uri));
4081543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        if (mFetcherInfos.removeItem(uri) < 0) {
4091543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                            // ignore duplicated kWhatStopped messages.
4101543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                            break;
4111543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        }
4121543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
413309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        if (mSwitchInProgress) {
414309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                            tryToFinishBandwidthSwitch();
415309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        }
41614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    }
41714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
41814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    if (mContinuation != NULL) {
41914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        CHECK_GT(mContinuationCounter, 0);
42014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        if (--mContinuationCounter == 0) {
42114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                            mContinuation->post();
4225ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih
4235ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih                            if (mSeekReplyID != 0) {
4245ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih                                CHECK(mSeekReply != NULL);
425800599cdd50737de1cde483a34b39923750b0658Robert Shih                                mSeekReply->setInt32("err", OK);
4265ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih                                mSeekReply->postReply(mSeekReplyID);
427800599cdd50737de1cde483a34b39923750b0658Robert Shih                                mSeekReplyID = 0;
428800599cdd50737de1cde483a34b39923750b0658Robert Shih                                mSeekReply.clear();
4295ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih                            }
43014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        }
43114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    }
43214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    break;
43314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                }
43414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
43514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                case PlaylistFetcher::kWhatDurationUpdate:
43614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                {
43714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    AString uri;
43814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    CHECK(msg->findString("uri", &uri));
43914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
44014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    int64_t durationUs;
44114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    CHECK(msg->findInt64("durationUs", &durationUs));
44214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
44314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    FetcherInfo *info = &mFetcherInfos.editValueFor(uri);
44414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    info->mDurationUs = durationUs;
44514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    break;
44614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                }
44714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
44814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                case PlaylistFetcher::kWhatError:
44914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                {
45014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    status_t err;
45114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    CHECK(msg->findInt32("err", &err));
45214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
45314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    ALOGE("XXX Received error %d from PlaylistFetcher.", err);
45414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
45515f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                    // handle EOS on subtitle tracks independently
45615f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                    AString uri;
45715f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                    if (err == ERROR_END_OF_STREAM && msg->findString("uri", &uri)) {
45815f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                        ssize_t i = mFetcherInfos.indexOfKey(uri);
45915f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                        if (i >= 0) {
46015f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                            const sp<PlaylistFetcher> &fetcher = mFetcherInfos.valueAt(i).mFetcher;
46115f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                            if (fetcher != NULL) {
46215f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                                uint32_t type = fetcher->getStreamTypeMask();
46315f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                                if (type == STREAMTYPE_SUBTITLES) {
46415f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                                    mPacketSources.valueFor(
46515f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                                            STREAMTYPE_SUBTITLES)->signalEOS(err);;
46615f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                                    break;
46715f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                                }
46815f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                            }
46915f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                        }
47015f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                    }
47115f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih
47214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    if (mInPreparationPhase) {
47314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        postPrepared(err);
47414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    }
47514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
4761543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    cancelBandwidthSwitch();
4771543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
47814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    mPacketSources.valueFor(STREAMTYPE_AUDIO)->signalEOS(err);
47914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
48014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    mPacketSources.valueFor(STREAMTYPE_VIDEO)->signalEOS(err);
48114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
48214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    mPacketSources.valueFor(
48314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                            STREAMTYPE_SUBTITLES)->signalEOS(err);
48414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
48514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    sp<AMessage> notify = mNotify->dup();
48614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    notify->setInt32("what", kWhatError);
48714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    notify->setInt32("err", err);
48814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    notify->post();
48914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    break;
49014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                }
49114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
49214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                case PlaylistFetcher::kWhatTemporarilyDoneFetching:
49314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                {
49414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    AString uri;
49514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    CHECK(msg->findString("uri", &uri));
49614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
4976300cbe99899da0103c910ba6a35c785261ce433Marco Nelissen                    if (mFetcherInfos.indexOfKey(uri) < 0) {
4986300cbe99899da0103c910ba6a35c785261ce433Marco Nelissen                        ALOGE("couldn't find uri");
4996300cbe99899da0103c910ba6a35c785261ce433Marco Nelissen                        break;
5006300cbe99899da0103c910ba6a35c785261ce433Marco Nelissen                    }
50114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    FetcherInfo *info = &mFetcherInfos.editValueFor(uri);
50214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    info->mIsPrepared = true;
50314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
50414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    if (mInPreparationPhase) {
50514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        bool allFetchersPrepared = true;
50614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
50714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                            if (!mFetcherInfos.valueAt(i).mIsPrepared) {
50814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                                allFetchersPrepared = false;
50914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                                break;
51014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                            }
51114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        }
51214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
51314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        if (allFetchersPrepared) {
51414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                            postPrepared(OK);
51514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        }
51614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    }
51714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    break;
51814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                }
51914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
5201543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                case PlaylistFetcher::kWhatStartedAt:
5211543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                {
5221543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    int32_t switchGeneration;
5231543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    CHECK(msg->findInt32("switchGeneration", &switchGeneration));
5241543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
5251543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    if (switchGeneration != mSwitchGeneration) {
5261543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        break;
5271543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    }
5281543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
5291543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    // Resume fetcher for the original variant; the resumed fetcher should
5301543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    // continue until the timestamps found in msg, which is stored by the
5311543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    // new fetcher to indicate where the new variant has started buffering.
5321543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    for (size_t i = 0; i < mFetcherInfos.size(); i++) {
5331543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        const FetcherInfo info = mFetcherInfos.valueAt(i);
5341543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        if (info.mToBeRemoved) {
5351543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                            info.mFetcher->resumeUntilAsync(msg);
5361543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        }
5371543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    }
5381543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    break;
5391543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                }
5401543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
54114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                default:
54214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    TRESPASS();
54314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            }
54414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
54514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            break;
54614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
54714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
54814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case kWhatCheckBandwidth:
549a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        {
550a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            int32_t generation;
551a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            CHECK(msg->findInt32("generation", &generation));
552a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
55314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            if (generation != mCheckBandwidthGeneration) {
554a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                break;
555a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            }
556a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
55700598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih            onCheckBandwidth(msg);
558a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
559a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
560a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
561dcb89b3b505522efde173c105a851c412f947178Chong Zhang        case kWhatChangeConfiguration:
562dcb89b3b505522efde173c105a851c412f947178Chong Zhang        {
563dcb89b3b505522efde173c105a851c412f947178Chong Zhang            onChangeConfiguration(msg);
564dcb89b3b505522efde173c105a851c412f947178Chong Zhang            break;
565dcb89b3b505522efde173c105a851c412f947178Chong Zhang        }
566dcb89b3b505522efde173c105a851c412f947178Chong Zhang
56714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case kWhatChangeConfiguration2:
56814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
56914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            onChangeConfiguration2(msg);
57014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            break;
57114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
57214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
57314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case kWhatChangeConfiguration3:
57414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
57514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            onChangeConfiguration3(msg);
57614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            break;
57714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
57814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
57914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case kWhatFinishDisconnect2:
58014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
58114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            onFinishDisconnect2();
582a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
58314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
584a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
5851543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        case kWhatSwapped:
5861543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        {
5871543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            onSwapped(msg);
5881543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            break;
5891543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        }
5900ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
5910ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        case kWhatCheckSwitchDown:
5920ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        {
5930ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih            onCheckSwitchDown();
5940ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih            break;
5950ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        }
5960ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
5970ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        case kWhatSwitchDown:
5980ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        {
5990ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih            onSwitchDown();
6000ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih            break;
6010ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        }
6020ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
603a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        default:
604a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            TRESPASS();
605a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
606a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
607a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
608a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
609a44153c1a57202fb538659eb50706e60454d6273Andreas Huber// static
610a44153c1a57202fb538659eb50706e60454d6273Andreas Huberint LiveSession::SortByBandwidth(const BandwidthItem *a, const BandwidthItem *b) {
611a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (a->mBandwidth < b->mBandwidth) {
612a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return -1;
613a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else if (a->mBandwidth == b->mBandwidth) {
614a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return 0;
615a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
616a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
617a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return 1;
618a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
619a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
6208ca002eedc747dd854b61cbe364b52c06869273fRobert Shih// static
6218ca002eedc747dd854b61cbe364b52c06869273fRobert ShihLiveSession::StreamType LiveSession::indexToType(int idx) {
6228ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    CHECK(idx >= 0 && idx < kMaxStreams);
6238ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    return (StreamType)(1 << idx);
6248ca002eedc747dd854b61cbe364b52c06869273fRobert Shih}
6258ca002eedc747dd854b61cbe364b52c06869273fRobert Shih
626f69c996864844e8f669308af8412cede043062a2Robert Shih// static
627f69c996864844e8f669308af8412cede043062a2Robert Shihssize_t LiveSession::typeToIndex(int32_t type) {
628f69c996864844e8f669308af8412cede043062a2Robert Shih    switch (type) {
629f69c996864844e8f669308af8412cede043062a2Robert Shih        case STREAMTYPE_AUDIO:
630f69c996864844e8f669308af8412cede043062a2Robert Shih            return 0;
631f69c996864844e8f669308af8412cede043062a2Robert Shih        case STREAMTYPE_VIDEO:
632f69c996864844e8f669308af8412cede043062a2Robert Shih            return 1;
633f69c996864844e8f669308af8412cede043062a2Robert Shih        case STREAMTYPE_SUBTITLES:
634f69c996864844e8f669308af8412cede043062a2Robert Shih            return 2;
635f69c996864844e8f669308af8412cede043062a2Robert Shih        default:
636f69c996864844e8f669308af8412cede043062a2Robert Shih            return -1;
637f69c996864844e8f669308af8412cede043062a2Robert Shih    };
638f69c996864844e8f669308af8412cede043062a2Robert Shih    return -1;
639f69c996864844e8f669308af8412cede043062a2Robert Shih}
640f69c996864844e8f669308af8412cede043062a2Robert Shih
641a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onConnect(const sp<AMessage> &msg) {
642a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    AString url;
643a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    CHECK(msg->findString("url", &url));
644a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
645ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    KeyedVector<String8, String8> *headers = NULL;
646ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    if (!msg->findPointer("headers", (void **)&headers)) {
647ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        mExtraHeaders.clear();
648ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    } else {
649ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        mExtraHeaders = *headers;
650ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber
651ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        delete headers;
652ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        headers = NULL;
653ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    }
654ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber
655a1df816c0677185534babba6ffc29970b048e52eLajos Molnar    // TODO currently we don't know if we are coming here from incognito mode
656a1df816c0677185534babba6ffc29970b048e52eLajos Molnar    ALOGI("onConnect %s", uriDebugString(url).c_str());
657a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
658a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    mMasterURL = url;
659a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
6607e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    bool dummy;
66114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mPlaylist = fetchPlaylist(url.c_str(), NULL /* curPlaylistHash */, &dummy);
662ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
66314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (mPlaylist == NULL) {
664a1df816c0677185534babba6ffc29970b048e52eLajos Molnar        ALOGE("unable to fetch master playlist %s.", uriDebugString(url).c_str());
665ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
66614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        postPrepared(ERROR_IO);
667ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber        return;
668ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber    }
669a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
67014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // We trust the content provider to make a reasonable choice of preferred
67114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // initial bandwidth by listing it first in the variant playlist.
67214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // At startup we really don't have a good estimate on the available
67314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // network bandwidth since we haven't tranferred any data yet. Once
67414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // we have we can make a better informed choice.
67514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    size_t initialBandwidth = 0;
67614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    size_t initialBandwidthIndex = 0;
67714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
67814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (mPlaylist->isVariantPlaylist()) {
67914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        for (size_t i = 0; i < mPlaylist->size(); ++i) {
680a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            BandwidthItem item;
681a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
68214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            item.mPlaylistIndex = i;
68314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
684a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            sp<AMessage> meta;
68514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            AString uri;
68614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            mPlaylist->itemAt(i, &uri, &meta);
687a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
688a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            CHECK(meta->findInt32("bandwidth", (int32_t *)&item.mBandwidth));
689a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
69014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            if (initialBandwidth == 0) {
69114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                initialBandwidth = item.mBandwidth;
69214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            }
69314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
694a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            mBandwidthItems.push(item);
695a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
696a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
697a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        CHECK_GT(mBandwidthItems.size(), 0u);
698a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
699a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        mBandwidthItems.sort(SortByBandwidth);
70014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
70114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        for (size_t i = 0; i < mBandwidthItems.size(); ++i) {
70214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            if (mBandwidthItems.itemAt(i).mBandwidth == initialBandwidth) {
70314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                initialBandwidthIndex = i;
70414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                break;
70514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            }
70614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
70714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    } else {
70814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        // dummy item.
70914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        BandwidthItem item;
71014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        item.mPlaylistIndex = 0;
71114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        item.mBandwidth = 0;
71214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        mBandwidthItems.push(item);
713a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
714a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
715309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    mPlaylist->pickRandomMediaItems();
716dcb89b3b505522efde173c105a851c412f947178Chong Zhang    changeConfiguration(
717309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            0ll /* timeUs */, initialBandwidthIndex, false /* pickTrack */);
718a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
719a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
72014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::finishDisconnect() {
72114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // No reconfiguration is currently pending, make sure none will trigger
72214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // during disconnection either.
72314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    cancelCheckBandwidthEvent();
72414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
7251543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // Protect mPacketSources from a swapPacketSource race condition through disconnect.
7261543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // (finishDisconnect, onFinishDisconnect2)
7271543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    cancelBandwidthSwitch();
7281543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
7290ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    // cancel switch down monitor
7300ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    mSwitchDownMonitor.clear();
7310ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
73214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
73314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        mFetcherInfos.valueAt(i).mFetcher->stopAsync();
73414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
73514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
73614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> msg = new AMessage(kWhatFinishDisconnect2, id());
737a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
73814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mContinuationCounter = mFetcherInfos.size();
73914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mContinuation = msg;
740ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
74114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (mContinuationCounter == 0) {
74214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        msg->post();
74314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
74414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
74514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
74614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::onFinishDisconnect2() {
74714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mContinuation.clear();
74814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
74914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mPacketSources.valueFor(STREAMTYPE_AUDIO)->signalEOS(ERROR_END_OF_STREAM);
75014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mPacketSources.valueFor(STREAMTYPE_VIDEO)->signalEOS(ERROR_END_OF_STREAM);
75114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
75214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mPacketSources.valueFor(
75314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            STREAMTYPE_SUBTITLES)->signalEOS(ERROR_END_OF_STREAM);
75414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
75514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> response = new AMessage;
75614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    response->setInt32("err", OK);
75714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
75814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    response->postReply(mDisconnectReplyID);
75914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mDisconnectReplyID = 0;
76014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
76114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
76214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubersp<PlaylistFetcher> LiveSession::addFetcher(const char *uri) {
76314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    ssize_t index = mFetcherInfos.indexOfKey(uri);
76414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
76514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (index >= 0) {
76614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        return NULL;
76714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
76814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
76914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> notify = new AMessage(kWhatFetcherNotify, id());
77014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->setString("uri", uri);
7711543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    notify->setInt32("switchGeneration", mSwitchGeneration);
77214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
77314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    FetcherInfo info;
774b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    info.mFetcher = new PlaylistFetcher(notify, this, uri, mSubtitleGeneration);
77514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    info.mDurationUs = -1ll;
77614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    info.mIsPrepared = false;
7771543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    info.mToBeRemoved = false;
77814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    looper()->registerHandler(info.mFetcher);
77914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
78014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mFetcherInfos.add(uri, info);
78114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
78214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return info.mFetcher;
783a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
784a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
7858dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih/*
7868dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * Illustration of parameters:
7878dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih *
7888dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * 0      `range_offset`
7898dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * +------------+-------------------------------------------------------+--+--+
7908dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * |            |                                 | next block to fetch |  |  |
7918dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * |            | `source` handle => `out` buffer |                     |  |  |
7928dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * | `url` file |<--------- buffer size --------->|<--- `block_size` -->|  |  |
7938dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * |            |<----------- `range_length` / buffer capacity ----------->|  |
7948dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * |<------------------------------ file_size ------------------------------->|
7958dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih *
7968dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * Special parameter values:
7978dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * - range_length == -1 means entire file
7988dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * - block_size == 0 means entire range
7998dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih *
8008dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih */
80143ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shihssize_t LiveSession::fetchFile(
8022aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        const char *url, sp<ABuffer> *out,
8038dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        int64_t range_offset, int64_t range_length,
8048dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        uint32_t block_size, /* download block size */
80597194cdf8d67f362ef8c6dfdf607298c7e102b3bMarco Nelissen        sp<DataSource> *source, /* to return and reuse source */
806784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo        String8 *actualUrl) {
8078dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    off64_t size;
8088dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    sp<DataSource> temp_source;
8098dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    if (source == NULL) {
8108dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        source = &temp_source;
8118dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    }
812a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
8138dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    if (*source == NULL) {
8148dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        if (!strncasecmp(url, "file://", 7)) {
8158dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            *source = new FileSource(url + 7);
8168dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        } else if (strncasecmp(url, "http://", 7)
8178dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                && strncasecmp(url, "https://", 8)) {
8188dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            return ERROR_UNSUPPORTED;
8198dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        } else {
8208dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            KeyedVector<String8, String8> headers = mExtraHeaders;
8218dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            if (range_offset > 0 || range_length >= 0) {
8228dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                headers.add(
8238dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                        String8("Range"),
8248dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                        String8(
8258dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                            StringPrintf(
8268dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                                "bytes=%lld-%s",
8278dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                                range_offset,
8288dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                                range_length < 0
8298dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                                    ? "" : StringPrintf("%lld",
8308dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                                            range_offset + range_length - 1).c_str()).c_str()));
8318dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            }
8328dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            status_t err = mHTTPDataSource->connect(url, &headers);
833a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
8348dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            if (err != OK) {
8358dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                return err;
8368dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            }
837a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
8388dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            *source = mHTTPDataSource;
839a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
840a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
841a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
8428dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    status_t getSizeErr = (*source)->getSize(&size);
8438dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    if (getSizeErr != OK) {
844a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        size = 65536;
845a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
846a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
8478dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    sp<ABuffer> buffer = *out != NULL ? *out : new ABuffer(size);
8488dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    if (*out == NULL) {
8498dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        buffer->setRange(0, 0);
8508dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    }
851a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
85243ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih    ssize_t bytesRead = 0;
8538dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    // adjust range_length if only reading partial block
854b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross    if (block_size > 0 && (range_length == -1 || (int64_t)(buffer->size() + block_size) < range_length)) {
8558dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        range_length = buffer->size() + block_size;
8568dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    }
857a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    for (;;) {
8588dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        // Only resize when we don't know the size.
859a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        size_t bufferRemaining = buffer->capacity() - buffer->size();
8608dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        if (bufferRemaining == 0 && getSizeErr != OK) {
861a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            bufferRemaining = 32768;
862a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
863b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross            ALOGV("increasing download buffer to %zu bytes",
864a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                 buffer->size() + bufferRemaining);
865a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
866a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            sp<ABuffer> copy = new ABuffer(buffer->size() + bufferRemaining);
867a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            memcpy(copy->data(), buffer->data(), buffer->size());
868a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            copy->setRange(0, buffer->size());
869a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
870a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            buffer = copy;
871a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
872a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
8732aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        size_t maxBytesToRead = bufferRemaining;
8742aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        if (range_length >= 0) {
8752aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber            int64_t bytesLeftInRange = range_length - buffer->size();
876b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross            if (bytesLeftInRange < (int64_t)maxBytesToRead) {
8772aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                maxBytesToRead = bytesLeftInRange;
8782aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber
8792aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                if (bytesLeftInRange == 0) {
8802aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                    break;
8812aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                }
8822aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber            }
8832aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        }
8842aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber
8858dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        // The DataSource is responsible for informing us of error (n < 0) or eof (n == 0)
8868dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        // to help us break out of the loop.
8878dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        ssize_t n = (*source)->readAt(
888a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                buffer->size(), buffer->data() + buffer->size(),
8892aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                maxBytesToRead);
890a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
891a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (n < 0) {
89220ad3a341a96e7746015ccb7369fa567897e11f6Andreas Huber            return n;
893a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
894a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
895a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (n == 0) {
896a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
897a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
898a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
899a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        buffer->setRange(0, buffer->size() + (size_t)n);
90043ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih        bytesRead += n;
901a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
902a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
903a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    *out = buffer;
904784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo    if (actualUrl != NULL) {
90597194cdf8d67f362ef8c6dfdf607298c7e102b3bMarco Nelissen        *actualUrl = (*source)->getUri();
906784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo        if (actualUrl->isEmpty()) {
907784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo            *actualUrl = url;
908784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo        }
909784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo    }
910a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
91143ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih    return bytesRead;
912a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
913a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
91414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubersp<M3UParser> LiveSession::fetchPlaylist(
91514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        const char *url, uint8_t *curPlaylistHash, bool *unchanged) {
916b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber    ALOGV("fetchPlaylist '%s'", url);
917b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
9187e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    *unchanged = false;
9197e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
920a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<ABuffer> buffer;
921784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo    String8 actualUrl;
92243ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih    ssize_t  err = fetchFile(url, &buffer, 0, -1, 0, NULL, &actualUrl);
923a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
92443ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih    if (err <= 0) {
925a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return NULL;
926a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
927a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
9287e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    // MD5 functionality is not available on the simulator, treat all
9297e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    // playlists as changed.
9307e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
9317e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber#if defined(HAVE_ANDROID_OS)
9327e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    uint8_t hash[16];
9337e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
9347e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    MD5_CTX m;
9357e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    MD5_Init(&m);
9367e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    MD5_Update(&m, buffer->data(), buffer->size());
9377e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
9387e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    MD5_Final(hash, &m);
9397e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
94014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (curPlaylistHash != NULL && !memcmp(hash, curPlaylistHash, 16)) {
9417e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        // playlist unchanged
9427e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        *unchanged = true;
9437e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
9447e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        return NULL;
9457e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    }
9467e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
94714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (curPlaylistHash != NULL) {
94814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        memcpy(curPlaylistHash, hash, sizeof(hash));
94914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
9507e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber#endif
9517e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
952a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<M3UParser> playlist =
953784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo        new M3UParser(actualUrl.string(), buffer->data(), buffer->size());
954a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
955a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (playlist->initCheck() != OK) {
95629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("failed to parse .m3u8 playlist");
9579067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber
958a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return NULL;
959a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
960a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
961a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return playlist;
962a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
963a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
964b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe#if 0
965a44153c1a57202fb538659eb50706e60454d6273Andreas Huberstatic double uniformRand() {
966a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return (double)rand() / RAND_MAX;
967a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
968b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe#endif
969a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
970a44153c1a57202fb538659eb50706e60454d6273Andreas Hubersize_t LiveSession::getBandwidthIndex() {
971a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (mBandwidthItems.size() == 0) {
972a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return 0;
973a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
974a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
975a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#if 1
976a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    char value[PROPERTY_VALUE_MAX];
977673158582c9589cee1d5e4d7c79622609938b8f8Andreas Huber    ssize_t index = -1;
97814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (property_get("media.httplive.bw-index", value, NULL)) {
979a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        char *end;
98014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        index = strtol(value, &end, 10);
98114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        CHECK(end > value && *end == '\0');
98214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
98314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (index >= 0 && (size_t)index >= mBandwidthItems.size()) {
98414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            index = mBandwidthItems.size() - 1;
985a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
986a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
987a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
98814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (index < 0) {
98914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        int32_t bandwidthBps;
99014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (mHTTPDataSource != NULL
99114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                && mHTTPDataSource->estimateBandwidth(&bandwidthBps)) {
99214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            ALOGV("bandwidth estimated at %.2f kbps", bandwidthBps / 1024.0f);
99314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        } else {
99414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            ALOGV("no bandwidth estimate.");
99514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            return 0;  // Pick the lowest bandwidth stream by default.
99614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
997a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
99814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        char value[PROPERTY_VALUE_MAX];
99914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (property_get("media.httplive.max-bw", value, NULL)) {
100014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            char *end;
100114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            long maxBw = strtoul(value, &end, 10);
100214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            if (end > value && *end == '\0') {
100314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                if (maxBw > 0 && bandwidthBps > maxBw) {
100414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    ALOGV("bandwidth capped to %ld bps", maxBw);
100514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    bandwidthBps = maxBw;
100614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                }
100714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            }
100814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
1009a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
101014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        // Pick the highest bandwidth stream below or equal to estimated bandwidth.
101114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
101214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        index = mBandwidthItems.size() - 1;
101300598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih        while (index > 0) {
101400598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih            // consider only 80% of the available bandwidth, but if we are switching up,
101500598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih            // be even more conservative (70%) to avoid overestimating and immediately
101600598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih            // switching back.
101700598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih            size_t adjustedBandwidthBps = bandwidthBps;
101800598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih            if (index > mCurBandwidthIndex) {
101900598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih                adjustedBandwidthBps = adjustedBandwidthBps * 7 / 10;
102000598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih            } else {
102100598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih                adjustedBandwidthBps = adjustedBandwidthBps * 8 / 10;
102200598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih            }
102300598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih            if (mBandwidthItems.itemAt(index).mBandwidth <= adjustedBandwidthBps) {
102400598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih                break;
102500598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih            }
102614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            --index;
102714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
1028a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1029a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0
1030a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // Change bandwidth at random()
1031a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index = uniformRand() * mBandwidthItems.size();
1032a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0
1033a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // There's a 50% chance to stay on the current bandwidth and
1034a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // a 50% chance to switch to the next higher bandwidth (wrapping around
1035a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // to lowest)
1036a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    const size_t kMinIndex = 0;
1037a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1038309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    static ssize_t mCurBandwidthIndex = -1;
103914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
1040a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index;
1041309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    if (mCurBandwidthIndex < 0) {
1042a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        index = kMinIndex;
1043a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else if (uniformRand() < 0.5) {
1044309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        index = (size_t)mCurBandwidthIndex;
1045a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else {
1046309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        index = mCurBandwidthIndex + 1;
1047a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (index == mBandwidthItems.size()) {
1048a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            index = kMinIndex;
1049a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
1050a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1051309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    mCurBandwidthIndex = index;
1052a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0
1053a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // Pick the highest bandwidth stream below or equal to 1.2 Mbit/sec
1054a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1055a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index = mBandwidthItems.size() - 1;
1056a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    while (index > 0 && mBandwidthItems.itemAt(index).mBandwidth > 1200000) {
1057a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        --index;
1058a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
105914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#elif 1
106014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    char value[PROPERTY_VALUE_MAX];
106114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    size_t index;
106214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (property_get("media.httplive.bw-index", value, NULL)) {
106314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        char *end;
106414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        index = strtoul(value, &end, 10);
106514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        CHECK(end > value && *end == '\0');
106614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
106714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (index >= mBandwidthItems.size()) {
106814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            index = mBandwidthItems.size() - 1;
106914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
107014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    } else {
107114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        index = 0;
107214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
1073a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#else
1074a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index = mBandwidthItems.size() - 1;  // Highest bandwidth stream
1075a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#endif
1076a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
107714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK_GE(index, 0);
107814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
1079a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return index;
1080a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
1081a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1082b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shihint64_t LiveSession::latestMediaSegmentStartTimeUs() {
1083b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    sp<AMessage> audioMeta = mPacketSources.valueFor(STREAMTYPE_AUDIO)->getLatestDequeuedMeta();
1084b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    int64_t minSegmentStartTimeUs = -1, videoSegmentStartTimeUs = -1;
1085b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    if (audioMeta != NULL) {
1086b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih        audioMeta->findInt64("segmentStartTimeUs", &minSegmentStartTimeUs);
1087b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    }
1088b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih
1089b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    sp<AMessage> videoMeta = mPacketSources.valueFor(STREAMTYPE_VIDEO)->getLatestDequeuedMeta();
1090b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    if (videoMeta != NULL
1091b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih            && videoMeta->findInt64("segmentStartTimeUs", &videoSegmentStartTimeUs)) {
1092b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih        if (minSegmentStartTimeUs < 0 || videoSegmentStartTimeUs < minSegmentStartTimeUs) {
1093b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih            minSegmentStartTimeUs = videoSegmentStartTimeUs;
1094b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih        }
1095b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih
1096b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    }
1097b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    return minSegmentStartTimeUs;
1098b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih}
1099b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih
110014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::onSeek(const sp<AMessage> &msg) {
110114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    int64_t timeUs;
110214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(msg->findInt64("timeUs", &timeUs));
11037e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
110414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (!mReconfigurationInProgress) {
1105800599cdd50737de1cde483a34b39923750b0658Robert Shih        changeConfiguration(timeUs, mCurBandwidthIndex);
1106800599cdd50737de1cde483a34b39923750b0658Robert Shih        return OK;
1107800599cdd50737de1cde483a34b39923750b0658Robert Shih    } else {
1108800599cdd50737de1cde483a34b39923750b0658Robert Shih        return -EWOULDBLOCK;
11097e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    }
11107e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber}
11117e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
111214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::getDuration(int64_t *durationUs) const {
111314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    int64_t maxDurationUs = 0ll;
111414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
111514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        int64_t fetcherDurationUs = mFetcherInfos.valueAt(i).mDurationUs;
1116b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
111714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (fetcherDurationUs >= 0ll && fetcherDurationUs > maxDurationUs) {
111814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            maxDurationUs = fetcherDurationUs;
1119a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
1120a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1121a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
112214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    *durationUs = maxDurationUs;
1123a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
112414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return OK;
112514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
11260f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber
112714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberbool LiveSession::isSeekable() const {
112814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    int64_t durationUs;
112914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return getDuration(&durationUs) == OK && durationUs >= 0;
113014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
11310f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber
113214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberbool LiveSession::hasDynamicDuration() const {
113314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return false;
113414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
11350f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber
1136404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhangsize_t LiveSession::getTrackCount() const {
11379d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih    if (mPlaylist == NULL) {
11389d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih        return 0;
11399d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih    } else {
11409d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih        return mPlaylist->getTrackCount();
11419d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih    }
1142404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang}
1143404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang
1144404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhangsp<AMessage> LiveSession::getTrackInfo(size_t trackIndex) const {
11459d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih    if (mPlaylist == NULL) {
11469d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih        return NULL;
11479d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih    } else {
11489d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih        return mPlaylist->getTrackInfo(trackIndex);
11499d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih    }
1150dcb89b3b505522efde173c105a851c412f947178Chong Zhang}
1151dcb89b3b505522efde173c105a851c412f947178Chong Zhang
1152dcb89b3b505522efde173c105a851c412f947178Chong Zhangstatus_t LiveSession::selectTrack(size_t index, bool select) {
1153b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    if (mPlaylist == NULL) {
1154b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih        return INVALID_OPERATION;
1155b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    }
1156b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih
1157b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    ++mSubtitleGeneration;
1158dcb89b3b505522efde173c105a851c412f947178Chong Zhang    status_t err = mPlaylist->selectTrack(index, select);
1159dcb89b3b505522efde173c105a851c412f947178Chong Zhang    if (err == OK) {
1160309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        sp<AMessage> msg = new AMessage(kWhatChangeConfiguration, id());
1161309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        msg->setInt32("bandwidthIndex", mCurBandwidthIndex);
1162309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        msg->setInt32("pickTrack", select);
1163309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        msg->post();
1164dcb89b3b505522efde173c105a851c412f947178Chong Zhang    }
1165dcb89b3b505522efde173c105a851c412f947178Chong Zhang    return err;
1166dcb89b3b505522efde173c105a851c412f947178Chong Zhang}
1167dcb89b3b505522efde173c105a851c412f947178Chong Zhang
11681543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shihbool LiveSession::canSwitchUp() {
11691543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // Allow upwards bandwidth switch when a stream has buffered at least 10 seconds.
11701543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    status_t err = OK;
11711543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    for (size_t i = 0; i < mPacketSources.size(); ++i) {
11721543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        sp<AnotherPacketSource> source = mPacketSources.valueAt(i);
11731543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        int64_t dur = source->getBufferedDurationUs(&err);
11741543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        if (err == OK && dur > 10000000) {
11751543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            return true;
11761543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        }
11771543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
11781543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    return false;
11791543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
11801543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
1181dcb89b3b505522efde173c105a851c412f947178Chong Zhangvoid LiveSession::changeConfiguration(
1182dcb89b3b505522efde173c105a851c412f947178Chong Zhang        int64_t timeUs, size_t bandwidthIndex, bool pickTrack) {
11831543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // Protect mPacketSources from a swapPacketSource race condition through reconfiguration.
11841543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // (changeConfiguration, onChangeConfiguration2, onChangeConfiguration3).
11851543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    cancelBandwidthSwitch();
11861543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
118714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(!mReconfigurationInProgress);
118814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mReconfigurationInProgress = true;
1189a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1190309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    mCurBandwidthIndex = bandwidthIndex;
119143c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
1192b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross    ALOGV("changeConfiguration => timeUs:%" PRId64 " us, bwIndex:%zu, pickTrack:%d",
1193dcb89b3b505522efde173c105a851c412f947178Chong Zhang          timeUs, bandwidthIndex, pickTrack);
119443c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
119514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK_LT(bandwidthIndex, mBandwidthItems.size());
119614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    const BandwidthItem &item = mBandwidthItems.itemAt(bandwidthIndex);
1197a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
11981543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    uint32_t streamMask = 0; // streams that should be fetched by the new fetcher
11991543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    uint32_t resumeMask = 0; // streams that should be fetched by the original fetcher
1200a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
12018ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    AString URIs[kMaxStreams];
12028ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
12038ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        if (mPlaylist->getTypeURI(item.mPlaylistIndex, mStreams[i].mType, &URIs[i])) {
12048ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            streamMask |= indexToType(i);
12058ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        }
120614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
1207aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber
120814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Step 1, stop and discard fetchers that are no longer needed.
120914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Pause those that we'll reuse.
121014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
121114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        const AString &uri = mFetcherInfos.keyAt(i);
1212aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber
121314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        bool discardFetcher = true;
1214aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber
121514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        // If we're seeking all current fetchers are discarded.
121614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (timeUs < 0ll) {
1217309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            // delay fetcher removal if not picking tracks
1218309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            discardFetcher = pickTrack;
12191543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
12208ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            for (size_t j = 0; j < kMaxStreams; ++j) {
12211543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                StreamType type = indexToType(j);
12221543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                if ((streamMask & type) && uri == URIs[j]) {
12231543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    resumeMask |= type;
12241543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    streamMask &= ~type;
1225309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    discardFetcher = false;
12268ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                }
12276801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber            }
122814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
1229a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
123014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (discardFetcher) {
123114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            mFetcherInfos.valueAt(i).mFetcher->stopAsync();
12326801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber        } else {
123314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            mFetcherInfos.valueAt(i).mFetcher->pauseAsync();
12346801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber        }
1235a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1236a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
12371543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    sp<AMessage> msg;
12381543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    if (timeUs < 0ll) {
1239309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        // skip onChangeConfiguration2 (decoder destruction) if not seeking.
12401543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        msg = new AMessage(kWhatChangeConfiguration3, id());
12411543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    } else {
12421543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        msg = new AMessage(kWhatChangeConfiguration2, id());
12431543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
124414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    msg->setInt32("streamMask", streamMask);
12451543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    msg->setInt32("resumeMask", resumeMask);
1246309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    msg->setInt32("pickTrack", pickTrack);
124714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    msg->setInt64("timeUs", timeUs);
12488ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
1249309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        if ((streamMask | resumeMask) & indexToType(i)) {
12508ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            msg->setString(mStreams[i].uriKey().c_str(), URIs[i].c_str());
12518ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        }
12526e6b1cae2bac1b78205cefab8e4e9e9538982965Andreas Huber    }
1253a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
125414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Every time a fetcher acknowledges the stopAsync or pauseAsync request
125514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // we'll decrement mContinuationCounter, once it reaches zero, i.e. all
125614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // fetchers have completed their asynchronous operation, we'll post
125714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // mContinuation, which then is handled below in onChangeConfiguration2.
125814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mContinuationCounter = mFetcherInfos.size();
125914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mContinuation = msg;
126088b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber
126114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (mContinuationCounter == 0) {
126214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        msg->post();
12635ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih
12645ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih        if (mSeekReplyID != 0) {
12655ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih            CHECK(mSeekReply != NULL);
1266800599cdd50737de1cde483a34b39923750b0658Robert Shih            mSeekReply->setInt32("err", OK);
12675ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih            mSeekReply->postReply(mSeekReplyID);
1268800599cdd50737de1cde483a34b39923750b0658Robert Shih            mSeekReplyID = 0;
1269800599cdd50737de1cde483a34b39923750b0658Robert Shih            mSeekReply.clear();
12705ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih        }
127188b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber    }
127214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
1273a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1274dcb89b3b505522efde173c105a851c412f947178Chong Zhangvoid LiveSession::onChangeConfiguration(const sp<AMessage> &msg) {
1275dcb89b3b505522efde173c105a851c412f947178Chong Zhang    if (!mReconfigurationInProgress) {
1276309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        int32_t pickTrack = 0, bandwidthIndex = mCurBandwidthIndex;
1277309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        msg->findInt32("pickTrack", &pickTrack);
1278309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        msg->findInt32("bandwidthIndex", &bandwidthIndex);
1279309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        changeConfiguration(-1ll /* timeUs */, bandwidthIndex, pickTrack);
1280dcb89b3b505522efde173c105a851c412f947178Chong Zhang    } else {
1281dcb89b3b505522efde173c105a851c412f947178Chong Zhang        msg->post(1000000ll); // retry in 1 sec
1282dcb89b3b505522efde173c105a851c412f947178Chong Zhang    }
1283dcb89b3b505522efde173c105a851c412f947178Chong Zhang}
1284dcb89b3b505522efde173c105a851c412f947178Chong Zhang
128514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::onChangeConfiguration2(const sp<AMessage> &msg) {
128614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mContinuation.clear();
1287bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
128814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // All fetchers are either suspended or have been removed now.
1289bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
1290309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    uint32_t streamMask, resumeMask;
129114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(msg->findInt32("streamMask", (int32_t *)&streamMask));
1292309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    CHECK(msg->findInt32("resumeMask", (int32_t *)&resumeMask));
1293309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
1294309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    // currently onChangeConfiguration2 is only called for seeking;
1295309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    // remove the following CHECK if using it else where.
1296309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    CHECK_EQ(resumeMask, 0);
1297309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    streamMask |= resumeMask;
1298bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
12998ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    AString URIs[kMaxStreams];
13008ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
13018ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        if (streamMask & indexToType(i)) {
13028ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            const AString &uriKey = mStreams[i].uriKey();
13038ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            CHECK(msg->findString(uriKey.c_str(), &URIs[i]));
13048ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            ALOGV("%s = '%s'", uriKey.c_str(), URIs[i].c_str());
13058ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        }
130622fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber    }
13073831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber
130814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Determine which decoders to shutdown on the player side,
130914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // a decoder has to be shutdown if either
131014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // 1) its streamtype was active before but now longer isn't.
131114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // or
131214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // 2) its streamtype was already active and still is but the URI
131314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    //    has changed.
131414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    uint32_t changedMask = 0;
13158ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams && i != kSubtitleIndex; ++i) {
13168ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        if (((mStreamMask & streamMask & indexToType(i))
13178ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                && !(URIs[i] == mStreams[i].mUri))
13188ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                || (mStreamMask & ~streamMask & indexToType(i))) {
13198ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            changedMask |= indexToType(i);
13208ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        }
1321b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber    }
1322b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
132314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (changedMask == 0) {
132414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        // If nothing changed as far as the audio/video decoders
132514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        // are concerned we can proceed.
132614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        onChangeConfiguration3(msg);
132714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        return;
132814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
132943c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
133014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Something changed, inform the player which will shutdown the
133114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // corresponding decoders and will post the reply once that's done.
133214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Handling the reply will continue executing below in
133314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // onChangeConfiguration3.
133414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> notify = mNotify->dup();
133514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->setInt32("what", kWhatStreamsChanged);
133614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->setInt32("changedMask", changedMask);
133720f725ebcef13ded1b4b85c61c8a4b37cd030656Andreas Huber
133814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    msg->setWhat(kWhatChangeConfiguration3);
133914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    msg->setTarget(id());
1340b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
134114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->setMessage("reply", msg);
134214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->post();
134314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
1344b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
134514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::onChangeConfiguration3(const sp<AMessage> &msg) {
13461543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    mContinuation.clear();
134714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // All remaining fetchers are still suspended, the player has shutdown
134814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // any decoders that needed it.
1349b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
13501543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    uint32_t streamMask, resumeMask;
135114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(msg->findInt32("streamMask", (int32_t *)&streamMask));
13521543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    CHECK(msg->findInt32("resumeMask", (int32_t *)&resumeMask));
1353a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
135414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    int64_t timeUs;
1355309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    int32_t pickTrack;
13561543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    bool switching = false;
135714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(msg->findInt64("timeUs", &timeUs));
1358309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    CHECK(msg->findInt32("pickTrack", &pickTrack));
1359a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
136014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (timeUs < 0ll) {
1361309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        if (!pickTrack) {
1362309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            switching = true;
1363309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        }
1364309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        mRealTimeBaseUs = ALooper::GetNowUs() - mLastDequeuedTimeUs;
1365309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    } else {
1366309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        mRealTimeBaseUs = ALooper::GetNowUs() - timeUs;
136714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
1368a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1369f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
1370f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        if (streamMask & indexToType(i)) {
1371f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            if (switching) {
1372f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih                CHECK(msg->findString(mStreams[i].uriKey().c_str(), &mStreams[i].mNewUri));
1373f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            } else {
1374f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih                CHECK(msg->findString(mStreams[i].uriKey().c_str(), &mStreams[i].mUri));
1375f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            }
1376f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        }
1377f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    }
1378f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih
1379309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    mNewStreamMask = streamMask | resumeMask;
1380f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    if (switching) {
1381f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        mSwapMask = mStreamMask & ~resumeMask;
1382f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    }
1383a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
13841543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // Of all existing fetchers:
13851543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // * Resume fetchers that are still needed and assign them original packet sources.
13861543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // * Mark otherwise unneeded fetchers for removal.
13871543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    ALOGV("resuming fetchers for mask 0x%08x", resumeMask);
138814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
138914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        const AString &uri = mFetcherInfos.keyAt(i);
13900df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas Huber
13918ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        sp<AnotherPacketSource> sources[kMaxStreams];
1392dc793ce8c0ead27ab43e40ce09f27fe338323502Robert Shih        for (size_t j = 0; j < kMaxStreams; ++j) {
13931543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            if ((resumeMask & indexToType(j)) && uri == mStreams[j].mUri) {
13948ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                sources[j] = mPacketSources.valueFor(indexToType(j));
1395309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
1396309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                if (j != kSubtitleIndex) {
1397309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    ALOGV("queueing dummy discontinuity for stream type %d", indexToType(j));
1398309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    sp<AnotherPacketSource> discontinuityQueue;
1399309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    discontinuityQueue = mDiscontinuities.valueFor(indexToType(j));
1400309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    discontinuityQueue->queueDiscontinuity(
1401309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                            ATSParser::DISCONTINUITY_NONE,
1402309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                            NULL,
1403309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                            true);
1404309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                }
14058ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            }
140614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
1407a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
14081543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        FetcherInfo &info = mFetcherInfos.editValueAt(i);
14091543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        if (sources[kAudioIndex] != NULL || sources[kVideoIndex] != NULL
14101543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                || sources[kSubtitleIndex] != NULL) {
14111543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            info.mFetcher->startAsync(
14121543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    sources[kAudioIndex], sources[kVideoIndex], sources[kSubtitleIndex]);
14131543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        } else {
14141543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            info.mToBeRemoved = true;
14151543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        }
1416a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1417a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
141814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // streamMask now only contains the types that need a new fetcher created.
1419a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
142014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (streamMask != 0) {
142114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        ALOGV("creating new fetchers for mask 0x%08x", streamMask);
1422a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1423a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
14241543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // Find out when the original fetchers have buffered up to and start the new fetchers
14251543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // at a later timestamp.
14268ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams; i++) {
14278ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        if (!(indexToType(i) & streamMask)) {
14288ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            continue;
14298ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        }
14301156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
143114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        AString uri;
1432f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        uri = switching ? mStreams[i].mNewUri : mStreams[i].mUri;
14339b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber
143414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        sp<PlaylistFetcher> fetcher = addFetcher(uri.c_str());
143514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        CHECK(fetcher != NULL);
1436a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1437309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        int64_t startTimeUs = -1;
1438309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        int64_t segmentStartTimeUs = -1ll;
1439309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        int32_t discontinuitySeq = -1;
14408ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        sp<AnotherPacketSource> sources[kMaxStreams];
14411543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
1442b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih        if (i == kSubtitleIndex) {
1443b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih            segmentStartTimeUs = latestMediaSegmentStartTimeUs();
1444b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih        }
1445b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih
14468ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        // TRICKY: looping from i as earlier streams are already removed from streamMask
14478ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        for (size_t j = i; j < kMaxStreams; ++j) {
1448f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            const AString &streamUri = switching ? mStreams[j].mNewUri : mStreams[j].mUri;
1449f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            if ((streamMask & indexToType(j)) && uri == streamUri) {
14508ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                sources[j] = mPacketSources.valueFor(indexToType(j));
14511543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
1452309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                if (timeUs >= 0) {
14531543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    sources[j]->clear();
1454309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    startTimeUs = timeUs;
1455309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
1456309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    sp<AnotherPacketSource> discontinuityQueue;
1457309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    sp<AMessage> extra = new AMessage;
1458309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    extra->setInt64("timeUs", timeUs);
1459309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    discontinuityQueue = mDiscontinuities.valueFor(indexToType(j));
1460309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    discontinuityQueue->queueDiscontinuity(
1461309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                            ATSParser::DISCONTINUITY_SEEK, extra, true);
14621543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                } else {
1463309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    int32_t type;
1464309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    sp<AMessage> meta;
1465309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    if (pickTrack) {
1466309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        // selecting
1467309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        meta = sources[j]->getLatestDequeuedMeta();
1468309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    } else {
1469309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        // adapting
1470309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        meta = sources[j]->getLatestEnqueuedMeta();
1471309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    }
14721543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
14731543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    if (meta != NULL && !meta->findInt32("discontinuity", &type)) {
1474309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        int64_t tmpUs;
1475309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        CHECK(meta->findInt64("timeUs", &tmpUs));
1476309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        if (startTimeUs < 0 || tmpUs < startTimeUs) {
1477309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                            startTimeUs = tmpUs;
1478309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        }
1479309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
1480309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        CHECK(meta->findInt64("segmentStartTimeUs", &tmpUs));
1481309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        if (segmentStartTimeUs < 0 || tmpUs < segmentStartTimeUs) {
1482309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                            segmentStartTimeUs = tmpUs;
14831543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        }
1484309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
1485309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        int32_t seq;
1486309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        CHECK(meta->findInt32("discontinuitySeq", &seq));
1487309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        if (discontinuitySeq < 0 || seq < discontinuitySeq) {
1488309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                            discontinuitySeq = seq;
14891543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        }
14901543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    }
14911543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
1492309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    if (pickTrack) {
1493309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        // selecting track, queue discontinuities before content
1494309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        sources[j]->clear();
1495309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        if (j == kSubtitleIndex) {
1496309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                            break;
1497309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        }
1498309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        sp<AnotherPacketSource> discontinuityQueue;
1499309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        discontinuityQueue = mDiscontinuities.valueFor(indexToType(j));
1500309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        discontinuityQueue->queueDiscontinuity(
1501309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                                ATSParser::DISCONTINUITY_FORMATCHANGE, NULL, true);
1502309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    } else {
1503309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        // adapting, queue discontinuities after resume
1504309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        sources[j] = mPacketSources2.valueFor(indexToType(j));
1505309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        sources[j]->clear();
1506309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        uint32_t extraStreams = mNewStreamMask & (~mStreamMask);
1507309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        if (extraStreams & indexToType(j)) {
1508309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                            sources[j]->queueAccessUnit(createFormatChangeBuffer(/*swap*/ false));
1509309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        }
15101543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    }
15111543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                }
1512a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
15138ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                streamMask &= ~indexToType(j);
15148ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            }
1515a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
151614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
15178ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        fetcher->startAsync(
15188ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                sources[kAudioIndex],
15198ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                sources[kVideoIndex],
15208ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                sources[kSubtitleIndex],
1521309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                startTimeUs < 0 ? mLastSeekTimeUs : startTimeUs,
1522309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                segmentStartTimeUs,
1523309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                discontinuitySeq,
1524309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                switching);
1525a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1526a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
152714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // All fetchers have now been started, the configuration change
152814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // has completed.
1529a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
153000598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih    cancelCheckBandwidthEvent();
153114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    scheduleCheckBandwidthEvent();
1532a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
153314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    ALOGV("XXX configuration change completed.");
153414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mReconfigurationInProgress = false;
15351543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    if (switching) {
15361543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        mSwitchInProgress = true;
15371543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    } else {
15381543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        mStreamMask = mNewStreamMask;
15391543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
1540a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
154114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (mDisconnectReplyID != 0) {
154214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        finishDisconnect();
1543a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
154414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
1545a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
15461543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shihvoid LiveSession::onSwapped(const sp<AMessage> &msg) {
15471543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    int32_t switchGeneration;
15481543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    CHECK(msg->findInt32("switchGeneration", &switchGeneration));
15491543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    if (switchGeneration != mSwitchGeneration) {
15501543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return;
15511543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
15521543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
15531543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    int32_t stream;
15541543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    CHECK(msg->findInt32("stream", &stream));
1555f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih
1556f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    ssize_t idx = typeToIndex(stream);
1557f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    CHECK(idx >= 0);
1558f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    if ((mNewStreamMask & stream) && mStreams[idx].mNewUri.empty()) {
1559f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        ALOGW("swapping stream type %d %s to empty stream", stream, mStreams[idx].mUri.c_str());
1560f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    }
1561f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    mStreams[idx].mUri = mStreams[idx].mNewUri;
1562f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    mStreams[idx].mNewUri.clear();
1563f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih
1564309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    mSwapMask &= ~stream;
1565309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    if (mSwapMask != 0) {
15661543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return;
15671543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
15681543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
15691543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // Check if new variant contains extra streams.
15701543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    uint32_t extraStreams = mNewStreamMask & (~mStreamMask);
15711543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    while (extraStreams) {
15721543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        StreamType extraStream = (StreamType) (extraStreams & ~(extraStreams - 1));
15731543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        swapPacketSource(extraStream);
15741543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        extraStreams &= ~extraStream;
1575f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih
1576f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        idx = typeToIndex(extraStream);
1577f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        CHECK(idx >= 0);
1578f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        if (mStreams[idx].mNewUri.empty()) {
1579f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            ALOGW("swapping extra stream type %d %s to empty stream",
1580f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih                    extraStream, mStreams[idx].mUri.c_str());
1581f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        }
1582f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        mStreams[idx].mUri = mStreams[idx].mNewUri;
1583f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        mStreams[idx].mNewUri.clear();
15841543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
15851543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
15861543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    tryToFinishBandwidthSwitch();
15871543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
15881543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
15890ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shihvoid LiveSession::onCheckSwitchDown() {
15900ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    if (mSwitchDownMonitor == NULL) {
15910ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        return;
15920ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    }
15930ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
15940ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
15950ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        int32_t targetDuration;
15960ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        sp<AnotherPacketSource> packetSource = mPacketSources.valueFor(indexToType(i));
15970ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        sp<AMessage> meta = packetSource->getLatestDequeuedMeta();
15980ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
15990ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        if (meta != NULL && meta->findInt32("targetDuration", &targetDuration) ) {
16000ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih            int64_t bufferedDurationUs = packetSource->getEstimatedDurationUs();
16010ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih            int64_t targetDurationUs = targetDuration * 1000000ll;
16020ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
16030ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih            if (bufferedDurationUs < targetDurationUs / 3) {
16040ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih                (new AMessage(kWhatSwitchDown, id()))->post();
16050ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih                break;
16060ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih            }
16070ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        }
16080ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    }
16090ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
16100ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    mSwitchDownMonitor->post(1000000ll);
16110ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih}
16120ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
16130ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shihvoid LiveSession::onSwitchDown() {
16140ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    if (mReconfigurationInProgress || mSwitchInProgress || mCurBandwidthIndex == 0) {
16150ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        return;
16160ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    }
16170ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
16180ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    ssize_t bandwidthIndex = getBandwidthIndex();
16190ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    if (bandwidthIndex < mCurBandwidthIndex) {
16200ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        changeConfiguration(-1, bandwidthIndex, false);
16210ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        return;
16220ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    }
16230ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
16240ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    changeConfiguration(-1, mCurBandwidthIndex - 1, false);
16250ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih}
16260ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
16271543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih// Mark switch done when:
1628309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih//   1. all old buffers are swapped out
16291543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shihvoid LiveSession::tryToFinishBandwidthSwitch() {
1630309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    if (!mSwitchInProgress) {
1631309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        return;
1632309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    }
1633309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
16341543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    bool needToRemoveFetchers = false;
16351543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
16361543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        if (mFetcherInfos.valueAt(i).mToBeRemoved) {
16371543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            needToRemoveFetchers = true;
16381543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            break;
16391543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        }
16401543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
1641309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
1642309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    if (!needToRemoveFetchers && mSwapMask == 0) {
1643309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        ALOGI("mSwitchInProgress = false");
16441543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        mStreamMask = mNewStreamMask;
16451543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        mSwitchInProgress = false;
16461543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
16471543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
16481543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
164914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::scheduleCheckBandwidthEvent() {
165014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> msg = new AMessage(kWhatCheckBandwidth, id());
165114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    msg->setInt32("generation", mCheckBandwidthGeneration);
165214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    msg->post(10000000ll);
1653a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
1654a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
165514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::cancelCheckBandwidthEvent() {
165614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    ++mCheckBandwidthGeneration;
1657a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
1658a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
16591543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shihvoid LiveSession::cancelBandwidthSwitch() {
16601543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    Mutex::Autolock lock(mSwapMutex);
16611543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    mSwitchGeneration++;
16621543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    mSwitchInProgress = false;
16631543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    mSwapMask = 0;
1664f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih
1665f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
1666f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        FetcherInfo& info = mFetcherInfos.editValueAt(i);
1667f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        if (info.mToBeRemoved) {
1668f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            info.mToBeRemoved = false;
1669f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        }
1670f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    }
1671f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih
1672f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
1673f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        if (!mStreams[i].mNewUri.empty()) {
1674f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            ssize_t j = mFetcherInfos.indexOfKey(mStreams[i].mNewUri);
1675f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            if (j < 0) {
1676f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih                mStreams[i].mNewUri.clear();
1677f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih                continue;
1678f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            }
1679f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih
1680f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            const FetcherInfo &info = mFetcherInfos.valueAt(j);
1681f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            info.mFetcher->stopAsync();
1682f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            mFetcherInfos.removeItemsAt(j);
1683f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            mStreams[i].mNewUri.clear();
1684f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        }
1685f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    }
16861543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
16871543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
16881543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shihbool LiveSession::canSwitchBandwidthTo(size_t bandwidthIndex) {
16891543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    if (mReconfigurationInProgress || mSwitchInProgress) {
16901543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return false;
16911543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
16921543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
1693309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    if (mCurBandwidthIndex < 0) {
16941543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return true;
169514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
169614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
1697309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    if (bandwidthIndex == (size_t)mCurBandwidthIndex) {
16981543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return false;
1699309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    } else if (bandwidthIndex > (size_t)mCurBandwidthIndex) {
17001543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return canSwitchUp();
17011543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    } else {
17021543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return true;
17031543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
17041543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
17051543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
170600598ec0b15426197494aaf9e5ec0bc88507c762Robert Shihvoid LiveSession::onCheckBandwidth(const sp<AMessage> &msg) {
170714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    size_t bandwidthIndex = getBandwidthIndex();
17081543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    if (canSwitchBandwidthTo(bandwidthIndex)) {
170914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        changeConfiguration(-1ll /* timeUs */, bandwidthIndex);
17101543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    } else {
171100598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih        // Come back and check again 10 seconds later in case there is nothing to do now.
171200598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih        // If we DO change configuration, once that completes it'll schedule a new
171300598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih        // check bandwidth event with an incremented mCheckBandwidthGeneration.
171400598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih        msg->post(10000000ll);
171514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
1716a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
1717a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
171814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::postPrepared(status_t err) {
171914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(mInPreparationPhase);
1720a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
172114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> notify = mNotify->dup();
172214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (err == OK || err == ERROR_END_OF_STREAM) {
172314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        notify->setInt32("what", kWhatPrepared);
172414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    } else {
172514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        notify->setInt32("what", kWhatPreparationFailed);
172614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        notify->setInt32("err", err);
172714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
1728a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
172914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->post();
1730a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
173114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mInPreparationPhase = false;
17320ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
17330ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    mSwitchDownMonitor = new AMessage(kWhatCheckSwitchDown, id());
17340ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    mSwitchDownMonitor->post();
1735b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber}
1736b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
1737a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}  // namespace android
1738a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1739