LiveSession.cpp revision 895651b07fec30b0f9b0d2499599a179d95c9be4
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            unsigned long bandwidth;
689a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            CHECK(meta->findInt32("bandwidth", (int32_t *)&item.mBandwidth));
690a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
69114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            if (initialBandwidth == 0) {
69214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                initialBandwidth = item.mBandwidth;
69314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            }
69414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
695a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            mBandwidthItems.push(item);
696a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
697a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
698a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        CHECK_GT(mBandwidthItems.size(), 0u);
699a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
700a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        mBandwidthItems.sort(SortByBandwidth);
70114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
70214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        for (size_t i = 0; i < mBandwidthItems.size(); ++i) {
70314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            if (mBandwidthItems.itemAt(i).mBandwidth == initialBandwidth) {
70414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                initialBandwidthIndex = i;
70514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                break;
70614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            }
70714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
70814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    } else {
70914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        // dummy item.
71014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        BandwidthItem item;
71114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        item.mPlaylistIndex = 0;
71214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        item.mBandwidth = 0;
71314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        mBandwidthItems.push(item);
714a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
715a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
716309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    mPlaylist->pickRandomMediaItems();
717dcb89b3b505522efde173c105a851c412f947178Chong Zhang    changeConfiguration(
718309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            0ll /* timeUs */, initialBandwidthIndex, false /* pickTrack */);
719a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
720a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
72114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::finishDisconnect() {
72214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // No reconfiguration is currently pending, make sure none will trigger
72314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // during disconnection either.
72414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    cancelCheckBandwidthEvent();
72514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
7261543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // Protect mPacketSources from a swapPacketSource race condition through disconnect.
7271543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // (finishDisconnect, onFinishDisconnect2)
7281543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    cancelBandwidthSwitch();
7291543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
7300ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    // cancel switch down monitor
7310ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    mSwitchDownMonitor.clear();
7320ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
73314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
73414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        mFetcherInfos.valueAt(i).mFetcher->stopAsync();
73514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
73614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
73714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> msg = new AMessage(kWhatFinishDisconnect2, id());
738a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
73914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mContinuationCounter = mFetcherInfos.size();
74014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mContinuation = msg;
741ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
74214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (mContinuationCounter == 0) {
74314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        msg->post();
74414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
74514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
74614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
74714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::onFinishDisconnect2() {
74814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mContinuation.clear();
74914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
75014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mPacketSources.valueFor(STREAMTYPE_AUDIO)->signalEOS(ERROR_END_OF_STREAM);
75114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mPacketSources.valueFor(STREAMTYPE_VIDEO)->signalEOS(ERROR_END_OF_STREAM);
75214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
75314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mPacketSources.valueFor(
75414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            STREAMTYPE_SUBTITLES)->signalEOS(ERROR_END_OF_STREAM);
75514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
75614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> response = new AMessage;
75714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    response->setInt32("err", OK);
75814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
75914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    response->postReply(mDisconnectReplyID);
76014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mDisconnectReplyID = 0;
76114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
76214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
76314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubersp<PlaylistFetcher> LiveSession::addFetcher(const char *uri) {
76414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    ssize_t index = mFetcherInfos.indexOfKey(uri);
76514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
76614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (index >= 0) {
76714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        return NULL;
76814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
76914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
77014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> notify = new AMessage(kWhatFetcherNotify, id());
77114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->setString("uri", uri);
7721543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    notify->setInt32("switchGeneration", mSwitchGeneration);
77314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
77414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    FetcherInfo info;
775b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    info.mFetcher = new PlaylistFetcher(notify, this, uri, mSubtitleGeneration);
77614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    info.mDurationUs = -1ll;
77714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    info.mIsPrepared = false;
7781543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    info.mToBeRemoved = false;
77914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    looper()->registerHandler(info.mFetcher);
78014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
78114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mFetcherInfos.add(uri, info);
78214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
78314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return info.mFetcher;
784a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
785a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
7868dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih/*
7878dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * Illustration of parameters:
7888dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih *
7898dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * 0      `range_offset`
7908dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * +------------+-------------------------------------------------------+--+--+
7918dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * |            |                                 | next block to fetch |  |  |
7928dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * |            | `source` handle => `out` buffer |                     |  |  |
7938dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * | `url` file |<--------- buffer size --------->|<--- `block_size` -->|  |  |
7948dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * |            |<----------- `range_length` / buffer capacity ----------->|  |
7958dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * |<------------------------------ file_size ------------------------------->|
7968dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih *
7978dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * Special parameter values:
7988dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * - range_length == -1 means entire file
7998dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * - block_size == 0 means entire range
8008dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih *
8018dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih */
80243ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shihssize_t LiveSession::fetchFile(
8032aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        const char *url, sp<ABuffer> *out,
8048dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        int64_t range_offset, int64_t range_length,
8058dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        uint32_t block_size, /* download block size */
80697194cdf8d67f362ef8c6dfdf607298c7e102b3bMarco Nelissen        sp<DataSource> *source, /* to return and reuse source */
807784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo        String8 *actualUrl) {
8088dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    off64_t size;
8098dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    sp<DataSource> temp_source;
8108dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    if (source == NULL) {
8118dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        source = &temp_source;
8128dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    }
813a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
8148dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    if (*source == NULL) {
8158dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        if (!strncasecmp(url, "file://", 7)) {
8168dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            *source = new FileSource(url + 7);
8178dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        } else if (strncasecmp(url, "http://", 7)
8188dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                && strncasecmp(url, "https://", 8)) {
8198dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            return ERROR_UNSUPPORTED;
8208dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        } else {
8218dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            KeyedVector<String8, String8> headers = mExtraHeaders;
8228dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            if (range_offset > 0 || range_length >= 0) {
8238dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                headers.add(
8248dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                        String8("Range"),
8258dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                        String8(
8268dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                            StringPrintf(
8278dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                                "bytes=%lld-%s",
8288dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                                range_offset,
8298dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                                range_length < 0
8308dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                                    ? "" : StringPrintf("%lld",
8318dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                                            range_offset + range_length - 1).c_str()).c_str()));
8328dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            }
8338dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            status_t err = mHTTPDataSource->connect(url, &headers);
834a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
8358dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            if (err != OK) {
8368dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                return err;
8378dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            }
838a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
8398dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            *source = mHTTPDataSource;
840a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
841a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
842a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
8438dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    status_t getSizeErr = (*source)->getSize(&size);
8448dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    if (getSizeErr != OK) {
845a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        size = 65536;
846a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
847a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
8488dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    sp<ABuffer> buffer = *out != NULL ? *out : new ABuffer(size);
8498dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    if (*out == NULL) {
8508dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        buffer->setRange(0, 0);
8518dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    }
852a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
85343ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih    ssize_t bytesRead = 0;
8548dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    // adjust range_length if only reading partial block
855b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross    if (block_size > 0 && (range_length == -1 || (int64_t)(buffer->size() + block_size) < range_length)) {
8568dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        range_length = buffer->size() + block_size;
8578dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    }
858a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    for (;;) {
8598dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        // Only resize when we don't know the size.
860a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        size_t bufferRemaining = buffer->capacity() - buffer->size();
8618dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        if (bufferRemaining == 0 && getSizeErr != OK) {
862a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            bufferRemaining = 32768;
863a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
864b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross            ALOGV("increasing download buffer to %zu bytes",
865a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                 buffer->size() + bufferRemaining);
866a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
867a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            sp<ABuffer> copy = new ABuffer(buffer->size() + bufferRemaining);
868a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            memcpy(copy->data(), buffer->data(), buffer->size());
869a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            copy->setRange(0, buffer->size());
870a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
871a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            buffer = copy;
872a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
873a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
8742aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        size_t maxBytesToRead = bufferRemaining;
8752aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        if (range_length >= 0) {
8762aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber            int64_t bytesLeftInRange = range_length - buffer->size();
877b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross            if (bytesLeftInRange < (int64_t)maxBytesToRead) {
8782aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                maxBytesToRead = bytesLeftInRange;
8792aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber
8802aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                if (bytesLeftInRange == 0) {
8812aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                    break;
8822aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                }
8832aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber            }
8842aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        }
8852aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber
8868dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        // The DataSource is responsible for informing us of error (n < 0) or eof (n == 0)
8878dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        // to help us break out of the loop.
8888dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        ssize_t n = (*source)->readAt(
889a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                buffer->size(), buffer->data() + buffer->size(),
8902aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                maxBytesToRead);
891a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
892a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (n < 0) {
89320ad3a341a96e7746015ccb7369fa567897e11f6Andreas Huber            return n;
894a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
895a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
896a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (n == 0) {
897a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
898a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
899a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
900a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        buffer->setRange(0, buffer->size() + (size_t)n);
90143ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih        bytesRead += n;
902a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
903a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
904a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    *out = buffer;
905784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo    if (actualUrl != NULL) {
90697194cdf8d67f362ef8c6dfdf607298c7e102b3bMarco Nelissen        *actualUrl = (*source)->getUri();
907784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo        if (actualUrl->isEmpty()) {
908784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo            *actualUrl = url;
909784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo        }
910784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo    }
911a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
91243ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih    return bytesRead;
913a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
914a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
91514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubersp<M3UParser> LiveSession::fetchPlaylist(
91614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        const char *url, uint8_t *curPlaylistHash, bool *unchanged) {
917b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber    ALOGV("fetchPlaylist '%s'", url);
918b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
9197e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    *unchanged = false;
9207e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
921a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<ABuffer> buffer;
922784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo    String8 actualUrl;
92343ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih    ssize_t  err = fetchFile(url, &buffer, 0, -1, 0, NULL, &actualUrl);
924a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
92543ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih    if (err <= 0) {
926a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return NULL;
927a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
928a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
9297e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    // MD5 functionality is not available on the simulator, treat all
9307e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    // playlists as changed.
9317e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
9327e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber#if defined(HAVE_ANDROID_OS)
9337e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    uint8_t hash[16];
9347e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
9357e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    MD5_CTX m;
9367e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    MD5_Init(&m);
9377e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    MD5_Update(&m, buffer->data(), buffer->size());
9387e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
9397e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    MD5_Final(hash, &m);
9407e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
94114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (curPlaylistHash != NULL && !memcmp(hash, curPlaylistHash, 16)) {
9427e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        // playlist unchanged
9437e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        *unchanged = true;
9447e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
9457e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        return NULL;
9467e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    }
9477e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
94814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (curPlaylistHash != NULL) {
94914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        memcpy(curPlaylistHash, hash, sizeof(hash));
95014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
9517e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber#endif
9527e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
953a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<M3UParser> playlist =
954784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo        new M3UParser(actualUrl.string(), buffer->data(), buffer->size());
955a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
956a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (playlist->initCheck() != OK) {
95729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("failed to parse .m3u8 playlist");
9589067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber
959a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return NULL;
960a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
961a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
962a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return playlist;
963a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
964a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
965a44153c1a57202fb538659eb50706e60454d6273Andreas Huberstatic double uniformRand() {
966a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return (double)rand() / RAND_MAX;
967a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
968a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
969a44153c1a57202fb538659eb50706e60454d6273Andreas Hubersize_t LiveSession::getBandwidthIndex() {
970a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (mBandwidthItems.size() == 0) {
971a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return 0;
972a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
973a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
974a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#if 1
975a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    char value[PROPERTY_VALUE_MAX];
976673158582c9589cee1d5e4d7c79622609938b8f8Andreas Huber    ssize_t index = -1;
97714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (property_get("media.httplive.bw-index", value, NULL)) {
978a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        char *end;
97914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        index = strtol(value, &end, 10);
98014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        CHECK(end > value && *end == '\0');
98114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
98214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (index >= 0 && (size_t)index >= mBandwidthItems.size()) {
98314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            index = mBandwidthItems.size() - 1;
984a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
985a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
986a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
98714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (index < 0) {
98814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        int32_t bandwidthBps;
98914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (mHTTPDataSource != NULL
99014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                && mHTTPDataSource->estimateBandwidth(&bandwidthBps)) {
99114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            ALOGV("bandwidth estimated at %.2f kbps", bandwidthBps / 1024.0f);
99214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        } else {
99314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            ALOGV("no bandwidth estimate.");
99414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            return 0;  // Pick the lowest bandwidth stream by default.
99514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
996a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
99714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        char value[PROPERTY_VALUE_MAX];
99814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (property_get("media.httplive.max-bw", value, NULL)) {
99914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            char *end;
100014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            long maxBw = strtoul(value, &end, 10);
100114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            if (end > value && *end == '\0') {
100214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                if (maxBw > 0 && bandwidthBps > maxBw) {
100314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    ALOGV("bandwidth capped to %ld bps", maxBw);
100414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    bandwidthBps = maxBw;
100514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                }
100614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            }
100714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
1008a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
100914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        // Pick the highest bandwidth stream below or equal to estimated bandwidth.
101014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
101114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        index = mBandwidthItems.size() - 1;
101200598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih        while (index > 0) {
101300598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih            // consider only 80% of the available bandwidth, but if we are switching up,
101400598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih            // be even more conservative (70%) to avoid overestimating and immediately
101500598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih            // switching back.
101600598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih            size_t adjustedBandwidthBps = bandwidthBps;
101700598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih            if (index > mCurBandwidthIndex) {
101800598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih                adjustedBandwidthBps = adjustedBandwidthBps * 7 / 10;
101900598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih            } else {
102000598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih                adjustedBandwidthBps = adjustedBandwidthBps * 8 / 10;
102100598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih            }
102200598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih            if (mBandwidthItems.itemAt(index).mBandwidth <= adjustedBandwidthBps) {
102300598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih                break;
102400598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih            }
102514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            --index;
102614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
1027a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1028a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0
1029a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // Change bandwidth at random()
1030a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index = uniformRand() * mBandwidthItems.size();
1031a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0
1032a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // There's a 50% chance to stay on the current bandwidth and
1033a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // a 50% chance to switch to the next higher bandwidth (wrapping around
1034a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // to lowest)
1035a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    const size_t kMinIndex = 0;
1036a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1037309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    static ssize_t mCurBandwidthIndex = -1;
103814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
1039a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index;
1040309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    if (mCurBandwidthIndex < 0) {
1041a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        index = kMinIndex;
1042a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else if (uniformRand() < 0.5) {
1043309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        index = (size_t)mCurBandwidthIndex;
1044a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else {
1045309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        index = mCurBandwidthIndex + 1;
1046a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (index == mBandwidthItems.size()) {
1047a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            index = kMinIndex;
1048a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
1049a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1050309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    mCurBandwidthIndex = index;
1051a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0
1052a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // Pick the highest bandwidth stream below or equal to 1.2 Mbit/sec
1053a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1054a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index = mBandwidthItems.size() - 1;
1055a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    while (index > 0 && mBandwidthItems.itemAt(index).mBandwidth > 1200000) {
1056a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        --index;
1057a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
105814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#elif 1
105914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    char value[PROPERTY_VALUE_MAX];
106014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    size_t index;
106114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (property_get("media.httplive.bw-index", value, NULL)) {
106214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        char *end;
106314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        index = strtoul(value, &end, 10);
106414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        CHECK(end > value && *end == '\0');
106514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
106614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (index >= mBandwidthItems.size()) {
106714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            index = mBandwidthItems.size() - 1;
106814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
106914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    } else {
107014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        index = 0;
107114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
1072a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#else
1073a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index = mBandwidthItems.size() - 1;  // Highest bandwidth stream
1074a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#endif
1075a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
107614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK_GE(index, 0);
107714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
1078a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return index;
1079a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
1080a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1081b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shihint64_t LiveSession::latestMediaSegmentStartTimeUs() {
1082b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    sp<AMessage> audioMeta = mPacketSources.valueFor(STREAMTYPE_AUDIO)->getLatestDequeuedMeta();
1083b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    int64_t minSegmentStartTimeUs = -1, videoSegmentStartTimeUs = -1;
1084b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    if (audioMeta != NULL) {
1085b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih        audioMeta->findInt64("segmentStartTimeUs", &minSegmentStartTimeUs);
1086b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    }
1087b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih
1088b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    sp<AMessage> videoMeta = mPacketSources.valueFor(STREAMTYPE_VIDEO)->getLatestDequeuedMeta();
1089b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    if (videoMeta != NULL
1090b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih            && videoMeta->findInt64("segmentStartTimeUs", &videoSegmentStartTimeUs)) {
1091b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih        if (minSegmentStartTimeUs < 0 || videoSegmentStartTimeUs < minSegmentStartTimeUs) {
1092b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih            minSegmentStartTimeUs = videoSegmentStartTimeUs;
1093b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih        }
1094b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih
1095b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    }
1096b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    return minSegmentStartTimeUs;
1097b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih}
1098b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih
109914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::onSeek(const sp<AMessage> &msg) {
110014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    int64_t timeUs;
110114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(msg->findInt64("timeUs", &timeUs));
11027e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
110314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (!mReconfigurationInProgress) {
1104800599cdd50737de1cde483a34b39923750b0658Robert Shih        changeConfiguration(timeUs, mCurBandwidthIndex);
1105800599cdd50737de1cde483a34b39923750b0658Robert Shih        return OK;
1106800599cdd50737de1cde483a34b39923750b0658Robert Shih    } else {
1107800599cdd50737de1cde483a34b39923750b0658Robert Shih        return -EWOULDBLOCK;
11087e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    }
11097e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber}
11107e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
111114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::getDuration(int64_t *durationUs) const {
1112895651b07fec30b0f9b0d2499599a179d95c9be4Wei Jia    int64_t maxDurationUs = -1ll;
111314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
111414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        int64_t fetcherDurationUs = mFetcherInfos.valueAt(i).mDurationUs;
1115b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
1116895651b07fec30b0f9b0d2499599a179d95c9be4Wei Jia        if (fetcherDurationUs > maxDurationUs) {
111714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            maxDurationUs = fetcherDurationUs;
1118a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
1119a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1120a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
112114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    *durationUs = maxDurationUs;
1122a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
112314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return OK;
112414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
11250f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber
112614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberbool LiveSession::isSeekable() const {
112714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    int64_t durationUs;
112814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return getDuration(&durationUs) == OK && durationUs >= 0;
112914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
11300f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber
113114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberbool LiveSession::hasDynamicDuration() const {
113214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return false;
113314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
11340f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber
1135404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhangsize_t LiveSession::getTrackCount() const {
11369d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih    if (mPlaylist == NULL) {
11379d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih        return 0;
11389d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih    } else {
11399d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih        return mPlaylist->getTrackCount();
11409d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih    }
1141404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang}
1142404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang
1143404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhangsp<AMessage> LiveSession::getTrackInfo(size_t trackIndex) const {
11449d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih    if (mPlaylist == NULL) {
11459d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih        return NULL;
11469d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih    } else {
11479d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih        return mPlaylist->getTrackInfo(trackIndex);
11489d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih    }
1149dcb89b3b505522efde173c105a851c412f947178Chong Zhang}
1150dcb89b3b505522efde173c105a851c412f947178Chong Zhang
1151dcb89b3b505522efde173c105a851c412f947178Chong Zhangstatus_t LiveSession::selectTrack(size_t index, bool select) {
1152b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    if (mPlaylist == NULL) {
1153b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih        return INVALID_OPERATION;
1154b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    }
1155b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih
1156b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    ++mSubtitleGeneration;
1157dcb89b3b505522efde173c105a851c412f947178Chong Zhang    status_t err = mPlaylist->selectTrack(index, select);
1158dcb89b3b505522efde173c105a851c412f947178Chong Zhang    if (err == OK) {
1159309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        sp<AMessage> msg = new AMessage(kWhatChangeConfiguration, id());
1160309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        msg->setInt32("bandwidthIndex", mCurBandwidthIndex);
1161309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        msg->setInt32("pickTrack", select);
1162309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        msg->post();
1163dcb89b3b505522efde173c105a851c412f947178Chong Zhang    }
1164dcb89b3b505522efde173c105a851c412f947178Chong Zhang    return err;
1165dcb89b3b505522efde173c105a851c412f947178Chong Zhang}
1166dcb89b3b505522efde173c105a851c412f947178Chong Zhang
116789bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shihssize_t LiveSession::getSelectedTrack(media_track_type type) const {
116889bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih    if (mPlaylist == NULL) {
116989bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih        return -1;
117089bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih    } else {
117189bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih        return mPlaylist->getSelectedTrack(type);
117289bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih    }
117389bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih}
117489bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih
11751543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shihbool LiveSession::canSwitchUp() {
11761543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // Allow upwards bandwidth switch when a stream has buffered at least 10 seconds.
11771543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    status_t err = OK;
11781543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    for (size_t i = 0; i < mPacketSources.size(); ++i) {
11791543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        sp<AnotherPacketSource> source = mPacketSources.valueAt(i);
11801543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        int64_t dur = source->getBufferedDurationUs(&err);
11811543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        if (err == OK && dur > 10000000) {
11821543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            return true;
11831543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        }
11841543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
11851543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    return false;
11861543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
11871543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
1188dcb89b3b505522efde173c105a851c412f947178Chong Zhangvoid LiveSession::changeConfiguration(
1189dcb89b3b505522efde173c105a851c412f947178Chong Zhang        int64_t timeUs, size_t bandwidthIndex, bool pickTrack) {
11901543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // Protect mPacketSources from a swapPacketSource race condition through reconfiguration.
11911543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // (changeConfiguration, onChangeConfiguration2, onChangeConfiguration3).
11921543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    cancelBandwidthSwitch();
11931543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
119414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(!mReconfigurationInProgress);
119514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mReconfigurationInProgress = true;
1196a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1197309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    mCurBandwidthIndex = bandwidthIndex;
119843c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
1199b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross    ALOGV("changeConfiguration => timeUs:%" PRId64 " us, bwIndex:%zu, pickTrack:%d",
1200dcb89b3b505522efde173c105a851c412f947178Chong Zhang          timeUs, bandwidthIndex, pickTrack);
120143c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
120214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK_LT(bandwidthIndex, mBandwidthItems.size());
120314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    const BandwidthItem &item = mBandwidthItems.itemAt(bandwidthIndex);
1204a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
12051543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    uint32_t streamMask = 0; // streams that should be fetched by the new fetcher
12061543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    uint32_t resumeMask = 0; // streams that should be fetched by the original fetcher
1207a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
12088ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    AString URIs[kMaxStreams];
12098ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
12108ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        if (mPlaylist->getTypeURI(item.mPlaylistIndex, mStreams[i].mType, &URIs[i])) {
12118ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            streamMask |= indexToType(i);
12128ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        }
121314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
1214aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber
121514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Step 1, stop and discard fetchers that are no longer needed.
121614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Pause those that we'll reuse.
121714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
121814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        const AString &uri = mFetcherInfos.keyAt(i);
1219aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber
122014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        bool discardFetcher = true;
1221aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber
122214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        // If we're seeking all current fetchers are discarded.
122314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (timeUs < 0ll) {
1224309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            // delay fetcher removal if not picking tracks
1225309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            discardFetcher = pickTrack;
12261543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
12278ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            for (size_t j = 0; j < kMaxStreams; ++j) {
12281543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                StreamType type = indexToType(j);
12291543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                if ((streamMask & type) && uri == URIs[j]) {
12301543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    resumeMask |= type;
12311543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    streamMask &= ~type;
1232309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    discardFetcher = false;
12338ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                }
12346801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber            }
123514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
1236a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
123714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (discardFetcher) {
123814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            mFetcherInfos.valueAt(i).mFetcher->stopAsync();
12396801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber        } else {
124014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            mFetcherInfos.valueAt(i).mFetcher->pauseAsync();
12416801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber        }
1242a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1243a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
12441543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    sp<AMessage> msg;
12451543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    if (timeUs < 0ll) {
1246309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        // skip onChangeConfiguration2 (decoder destruction) if not seeking.
12471543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        msg = new AMessage(kWhatChangeConfiguration3, id());
12481543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    } else {
12491543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        msg = new AMessage(kWhatChangeConfiguration2, id());
12501543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
125114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    msg->setInt32("streamMask", streamMask);
12521543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    msg->setInt32("resumeMask", resumeMask);
1253309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    msg->setInt32("pickTrack", pickTrack);
125414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    msg->setInt64("timeUs", timeUs);
12558ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
1256309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        if ((streamMask | resumeMask) & indexToType(i)) {
12578ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            msg->setString(mStreams[i].uriKey().c_str(), URIs[i].c_str());
12588ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        }
12596e6b1cae2bac1b78205cefab8e4e9e9538982965Andreas Huber    }
1260a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
126114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Every time a fetcher acknowledges the stopAsync or pauseAsync request
126214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // we'll decrement mContinuationCounter, once it reaches zero, i.e. all
126314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // fetchers have completed their asynchronous operation, we'll post
126414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // mContinuation, which then is handled below in onChangeConfiguration2.
126514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mContinuationCounter = mFetcherInfos.size();
126614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mContinuation = msg;
126788b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber
126814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (mContinuationCounter == 0) {
126914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        msg->post();
12705ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih
12715ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih        if (mSeekReplyID != 0) {
12725ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih            CHECK(mSeekReply != NULL);
1273800599cdd50737de1cde483a34b39923750b0658Robert Shih            mSeekReply->setInt32("err", OK);
12745ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih            mSeekReply->postReply(mSeekReplyID);
1275800599cdd50737de1cde483a34b39923750b0658Robert Shih            mSeekReplyID = 0;
1276800599cdd50737de1cde483a34b39923750b0658Robert Shih            mSeekReply.clear();
12775ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih        }
127888b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber    }
127914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
1280a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1281dcb89b3b505522efde173c105a851c412f947178Chong Zhangvoid LiveSession::onChangeConfiguration(const sp<AMessage> &msg) {
1282dcb89b3b505522efde173c105a851c412f947178Chong Zhang    if (!mReconfigurationInProgress) {
1283309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        int32_t pickTrack = 0, bandwidthIndex = mCurBandwidthIndex;
1284309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        msg->findInt32("pickTrack", &pickTrack);
1285309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        msg->findInt32("bandwidthIndex", &bandwidthIndex);
1286309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        changeConfiguration(-1ll /* timeUs */, bandwidthIndex, pickTrack);
1287dcb89b3b505522efde173c105a851c412f947178Chong Zhang    } else {
1288dcb89b3b505522efde173c105a851c412f947178Chong Zhang        msg->post(1000000ll); // retry in 1 sec
1289dcb89b3b505522efde173c105a851c412f947178Chong Zhang    }
1290dcb89b3b505522efde173c105a851c412f947178Chong Zhang}
1291dcb89b3b505522efde173c105a851c412f947178Chong Zhang
129214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::onChangeConfiguration2(const sp<AMessage> &msg) {
129314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mContinuation.clear();
1294bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
129514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // All fetchers are either suspended or have been removed now.
1296bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
1297309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    uint32_t streamMask, resumeMask;
129814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(msg->findInt32("streamMask", (int32_t *)&streamMask));
1299309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    CHECK(msg->findInt32("resumeMask", (int32_t *)&resumeMask));
1300309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
1301309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    // currently onChangeConfiguration2 is only called for seeking;
1302309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    // remove the following CHECK if using it else where.
1303309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    CHECK_EQ(resumeMask, 0);
1304309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    streamMask |= resumeMask;
1305bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
13068ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    AString URIs[kMaxStreams];
13078ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
13088ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        if (streamMask & indexToType(i)) {
13098ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            const AString &uriKey = mStreams[i].uriKey();
13108ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            CHECK(msg->findString(uriKey.c_str(), &URIs[i]));
13118ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            ALOGV("%s = '%s'", uriKey.c_str(), URIs[i].c_str());
13128ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        }
131322fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber    }
13143831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber
131514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Determine which decoders to shutdown on the player side,
131614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // a decoder has to be shutdown if either
131714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // 1) its streamtype was active before but now longer isn't.
131814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // or
131914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // 2) its streamtype was already active and still is but the URI
132014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    //    has changed.
132114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    uint32_t changedMask = 0;
13228ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams && i != kSubtitleIndex; ++i) {
13238ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        if (((mStreamMask & streamMask & indexToType(i))
13248ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                && !(URIs[i] == mStreams[i].mUri))
13258ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                || (mStreamMask & ~streamMask & indexToType(i))) {
13268ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            changedMask |= indexToType(i);
13278ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        }
1328b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber    }
1329b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
133014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (changedMask == 0) {
133114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        // If nothing changed as far as the audio/video decoders
133214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        // are concerned we can proceed.
133314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        onChangeConfiguration3(msg);
133414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        return;
133514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
133643c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
133714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Something changed, inform the player which will shutdown the
133814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // corresponding decoders and will post the reply once that's done.
133914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Handling the reply will continue executing below in
134014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // onChangeConfiguration3.
134114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> notify = mNotify->dup();
134214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->setInt32("what", kWhatStreamsChanged);
134314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->setInt32("changedMask", changedMask);
134420f725ebcef13ded1b4b85c61c8a4b37cd030656Andreas Huber
134514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    msg->setWhat(kWhatChangeConfiguration3);
134614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    msg->setTarget(id());
1347b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
134814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->setMessage("reply", msg);
134914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->post();
135014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
1351b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
135214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::onChangeConfiguration3(const sp<AMessage> &msg) {
13531543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    mContinuation.clear();
135414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // All remaining fetchers are still suspended, the player has shutdown
135514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // any decoders that needed it.
1356b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
13571543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    uint32_t streamMask, resumeMask;
135814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(msg->findInt32("streamMask", (int32_t *)&streamMask));
13591543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    CHECK(msg->findInt32("resumeMask", (int32_t *)&resumeMask));
1360a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
136114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    int64_t timeUs;
1362309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    int32_t pickTrack;
13631543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    bool switching = false;
136414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(msg->findInt64("timeUs", &timeUs));
1365309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    CHECK(msg->findInt32("pickTrack", &pickTrack));
1366a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
136714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (timeUs < 0ll) {
1368309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        if (!pickTrack) {
1369309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            switching = true;
1370309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        }
1371309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        mRealTimeBaseUs = ALooper::GetNowUs() - mLastDequeuedTimeUs;
1372309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    } else {
1373309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        mRealTimeBaseUs = ALooper::GetNowUs() - timeUs;
137414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
1375a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1376f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
1377f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        if (streamMask & indexToType(i)) {
1378f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            if (switching) {
1379f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih                CHECK(msg->findString(mStreams[i].uriKey().c_str(), &mStreams[i].mNewUri));
1380f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            } else {
1381f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih                CHECK(msg->findString(mStreams[i].uriKey().c_str(), &mStreams[i].mUri));
1382f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            }
1383f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        }
1384f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    }
1385f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih
1386309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    mNewStreamMask = streamMask | resumeMask;
1387f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    if (switching) {
1388f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        mSwapMask = mStreamMask & ~resumeMask;
1389f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    }
1390a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
13911543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // Of all existing fetchers:
13921543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // * Resume fetchers that are still needed and assign them original packet sources.
13931543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // * Mark otherwise unneeded fetchers for removal.
13941543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    ALOGV("resuming fetchers for mask 0x%08x", resumeMask);
139514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
139614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        const AString &uri = mFetcherInfos.keyAt(i);
13970df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas Huber
13988ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        sp<AnotherPacketSource> sources[kMaxStreams];
1399dc793ce8c0ead27ab43e40ce09f27fe338323502Robert Shih        for (size_t j = 0; j < kMaxStreams; ++j) {
14001543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            if ((resumeMask & indexToType(j)) && uri == mStreams[j].mUri) {
14018ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                sources[j] = mPacketSources.valueFor(indexToType(j));
1402309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
1403309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                if (j != kSubtitleIndex) {
1404309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    ALOGV("queueing dummy discontinuity for stream type %d", indexToType(j));
1405309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    sp<AnotherPacketSource> discontinuityQueue;
1406309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    discontinuityQueue = mDiscontinuities.valueFor(indexToType(j));
1407309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    discontinuityQueue->queueDiscontinuity(
1408309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                            ATSParser::DISCONTINUITY_NONE,
1409309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                            NULL,
1410309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                            true);
1411309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                }
14128ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            }
141314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
1414a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
14151543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        FetcherInfo &info = mFetcherInfos.editValueAt(i);
14161543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        if (sources[kAudioIndex] != NULL || sources[kVideoIndex] != NULL
14171543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                || sources[kSubtitleIndex] != NULL) {
14181543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            info.mFetcher->startAsync(
14191543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    sources[kAudioIndex], sources[kVideoIndex], sources[kSubtitleIndex]);
14201543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        } else {
14211543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            info.mToBeRemoved = true;
14221543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        }
1423a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1424a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
142514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // streamMask now only contains the types that need a new fetcher created.
1426a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
142714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (streamMask != 0) {
142814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        ALOGV("creating new fetchers for mask 0x%08x", streamMask);
1429a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1430a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
14311543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // Find out when the original fetchers have buffered up to and start the new fetchers
14321543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // at a later timestamp.
14338ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams; i++) {
14348ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        if (!(indexToType(i) & streamMask)) {
14358ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            continue;
14368ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        }
14371156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
143814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        AString uri;
1439f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        uri = switching ? mStreams[i].mNewUri : mStreams[i].mUri;
14409b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber
144114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        sp<PlaylistFetcher> fetcher = addFetcher(uri.c_str());
144214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        CHECK(fetcher != NULL);
1443a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
14441543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        int32_t latestSeq = -1;
1445309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        int64_t startTimeUs = -1;
1446309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        int64_t segmentStartTimeUs = -1ll;
1447309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        int32_t discontinuitySeq = -1;
14488ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        sp<AnotherPacketSource> sources[kMaxStreams];
14491543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
1450b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih        if (i == kSubtitleIndex) {
1451b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih            segmentStartTimeUs = latestMediaSegmentStartTimeUs();
1452b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih        }
1453b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih
14548ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        // TRICKY: looping from i as earlier streams are already removed from streamMask
14558ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        for (size_t j = i; j < kMaxStreams; ++j) {
1456f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            const AString &streamUri = switching ? mStreams[j].mNewUri : mStreams[j].mUri;
1457f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            if ((streamMask & indexToType(j)) && uri == streamUri) {
14588ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                sources[j] = mPacketSources.valueFor(indexToType(j));
14591543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
1460309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                if (timeUs >= 0) {
14611543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    sources[j]->clear();
1462309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    startTimeUs = timeUs;
1463309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
1464309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    sp<AnotherPacketSource> discontinuityQueue;
1465309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    sp<AMessage> extra = new AMessage;
1466309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    extra->setInt64("timeUs", timeUs);
1467309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    discontinuityQueue = mDiscontinuities.valueFor(indexToType(j));
1468309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    discontinuityQueue->queueDiscontinuity(
1469fef808d42a9c94b0b5ef3c3d5fb0a090edbc42daWei Jia                            ATSParser::DISCONTINUITY_TIME, extra, true);
14701543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                } else {
1471309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    int32_t type;
1472309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    int64_t srcSegmentStartTimeUs;
1473309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    sp<AMessage> meta;
1474309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    if (pickTrack) {
1475309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        // selecting
1476309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        meta = sources[j]->getLatestDequeuedMeta();
1477309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    } else {
1478309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        // adapting
1479309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        meta = sources[j]->getLatestEnqueuedMeta();
1480309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    }
14811543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
14821543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    if (meta != NULL && !meta->findInt32("discontinuity", &type)) {
1483309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        int64_t tmpUs;
1484309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        CHECK(meta->findInt64("timeUs", &tmpUs));
1485309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        if (startTimeUs < 0 || tmpUs < startTimeUs) {
1486309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                            startTimeUs = tmpUs;
1487309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        }
1488309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
1489309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        CHECK(meta->findInt64("segmentStartTimeUs", &tmpUs));
1490309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        if (segmentStartTimeUs < 0 || tmpUs < segmentStartTimeUs) {
1491309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                            segmentStartTimeUs = tmpUs;
14921543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        }
1493309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
1494309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        int32_t seq;
1495309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        CHECK(meta->findInt32("discontinuitySeq", &seq));
1496309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        if (discontinuitySeq < 0 || seq < discontinuitySeq) {
1497309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                            discontinuitySeq = seq;
14981543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        }
14991543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    }
15001543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
1501309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    if (pickTrack) {
1502309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        // selecting track, queue discontinuities before content
1503309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        sources[j]->clear();
1504309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        if (j == kSubtitleIndex) {
1505309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                            break;
1506309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        }
1507309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        sp<AnotherPacketSource> discontinuityQueue;
1508309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        discontinuityQueue = mDiscontinuities.valueFor(indexToType(j));
1509309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        discontinuityQueue->queueDiscontinuity(
1510309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                                ATSParser::DISCONTINUITY_FORMATCHANGE, NULL, true);
1511309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    } else {
1512309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        // adapting, queue discontinuities after resume
1513309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        sources[j] = mPacketSources2.valueFor(indexToType(j));
1514309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        sources[j]->clear();
1515309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        uint32_t extraStreams = mNewStreamMask & (~mStreamMask);
1516309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        if (extraStreams & indexToType(j)) {
1517309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                            sources[j]->queueAccessUnit(createFormatChangeBuffer(/*swap*/ false));
1518309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        }
15191543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    }
15201543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                }
1521a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
15228ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                streamMask &= ~indexToType(j);
15238ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            }
1524a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
152514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
15268ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        fetcher->startAsync(
15278ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                sources[kAudioIndex],
15288ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                sources[kVideoIndex],
15298ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                sources[kSubtitleIndex],
1530309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                startTimeUs < 0 ? mLastSeekTimeUs : startTimeUs,
1531309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                segmentStartTimeUs,
1532309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                discontinuitySeq,
1533309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                switching);
1534a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1535a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
153614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // All fetchers have now been started, the configuration change
153714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // has completed.
1538a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
153900598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih    cancelCheckBandwidthEvent();
154014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    scheduleCheckBandwidthEvent();
1541a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
154214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    ALOGV("XXX configuration change completed.");
154314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mReconfigurationInProgress = false;
15441543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    if (switching) {
15451543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        mSwitchInProgress = true;
15461543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    } else {
15471543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        mStreamMask = mNewStreamMask;
15481543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
1549a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
155014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (mDisconnectReplyID != 0) {
155114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        finishDisconnect();
1552a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
155314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
1554a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
15551543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shihvoid LiveSession::onSwapped(const sp<AMessage> &msg) {
15561543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    int32_t switchGeneration;
15571543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    CHECK(msg->findInt32("switchGeneration", &switchGeneration));
15581543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    if (switchGeneration != mSwitchGeneration) {
15591543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return;
15601543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
15611543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
15621543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    int32_t stream;
15631543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    CHECK(msg->findInt32("stream", &stream));
1564f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih
1565f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    ssize_t idx = typeToIndex(stream);
1566f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    CHECK(idx >= 0);
1567f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    if ((mNewStreamMask & stream) && mStreams[idx].mNewUri.empty()) {
1568f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        ALOGW("swapping stream type %d %s to empty stream", stream, mStreams[idx].mUri.c_str());
1569f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    }
1570f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    mStreams[idx].mUri = mStreams[idx].mNewUri;
1571f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    mStreams[idx].mNewUri.clear();
1572f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih
1573309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    mSwapMask &= ~stream;
1574309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    if (mSwapMask != 0) {
15751543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return;
15761543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
15771543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
15781543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // Check if new variant contains extra streams.
15791543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    uint32_t extraStreams = mNewStreamMask & (~mStreamMask);
15801543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    while (extraStreams) {
15811543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        StreamType extraStream = (StreamType) (extraStreams & ~(extraStreams - 1));
15821543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        swapPacketSource(extraStream);
15831543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        extraStreams &= ~extraStream;
1584f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih
1585f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        idx = typeToIndex(extraStream);
1586f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        CHECK(idx >= 0);
1587f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        if (mStreams[idx].mNewUri.empty()) {
1588f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            ALOGW("swapping extra stream type %d %s to empty stream",
1589f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih                    extraStream, mStreams[idx].mUri.c_str());
1590f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        }
1591f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        mStreams[idx].mUri = mStreams[idx].mNewUri;
1592f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        mStreams[idx].mNewUri.clear();
15931543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
15941543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
15951543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    tryToFinishBandwidthSwitch();
15961543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
15971543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
15980ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shihvoid LiveSession::onCheckSwitchDown() {
15990ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    if (mSwitchDownMonitor == NULL) {
16000ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        return;
16010ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    }
16020ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
16030ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
16040ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        int32_t targetDuration;
16050ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        sp<AnotherPacketSource> packetSource = mPacketSources.valueFor(indexToType(i));
16060ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        sp<AMessage> meta = packetSource->getLatestDequeuedMeta();
16070ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
16080ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        if (meta != NULL && meta->findInt32("targetDuration", &targetDuration) ) {
16090ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih            int64_t bufferedDurationUs = packetSource->getEstimatedDurationUs();
16100ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih            int64_t targetDurationUs = targetDuration * 1000000ll;
16110ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
16120ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih            if (bufferedDurationUs < targetDurationUs / 3) {
16130ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih                (new AMessage(kWhatSwitchDown, id()))->post();
16140ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih                break;
16150ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih            }
16160ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        }
16170ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    }
16180ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
16190ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    mSwitchDownMonitor->post(1000000ll);
16200ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih}
16210ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
16220ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shihvoid LiveSession::onSwitchDown() {
16230ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    if (mReconfigurationInProgress || mSwitchInProgress || mCurBandwidthIndex == 0) {
16240ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        return;
16250ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    }
16260ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
16270ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    ssize_t bandwidthIndex = getBandwidthIndex();
16280ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    if (bandwidthIndex < mCurBandwidthIndex) {
16290ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        changeConfiguration(-1, bandwidthIndex, false);
16300ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        return;
16310ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    }
16320ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
16330ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    changeConfiguration(-1, mCurBandwidthIndex - 1, false);
16340ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih}
16350ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
16361543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih// Mark switch done when:
1637309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih//   1. all old buffers are swapped out
16381543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shihvoid LiveSession::tryToFinishBandwidthSwitch() {
1639309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    if (!mSwitchInProgress) {
1640309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        return;
1641309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    }
1642309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
16431543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    bool needToRemoveFetchers = false;
16441543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
16451543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        if (mFetcherInfos.valueAt(i).mToBeRemoved) {
16461543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            needToRemoveFetchers = true;
16471543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            break;
16481543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        }
16491543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
1650309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
1651309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    if (!needToRemoveFetchers && mSwapMask == 0) {
1652309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        ALOGI("mSwitchInProgress = false");
16531543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        mStreamMask = mNewStreamMask;
16541543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        mSwitchInProgress = false;
16551543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
16561543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
16571543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
165814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::scheduleCheckBandwidthEvent() {
165914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> msg = new AMessage(kWhatCheckBandwidth, id());
166014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    msg->setInt32("generation", mCheckBandwidthGeneration);
166114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    msg->post(10000000ll);
1662a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
1663a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
166414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::cancelCheckBandwidthEvent() {
166514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    ++mCheckBandwidthGeneration;
1666a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
1667a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
16681543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shihvoid LiveSession::cancelBandwidthSwitch() {
16691543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    Mutex::Autolock lock(mSwapMutex);
16701543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    mSwitchGeneration++;
16711543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    mSwitchInProgress = false;
16721543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    mSwapMask = 0;
1673f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih
1674f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
1675f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        FetcherInfo& info = mFetcherInfos.editValueAt(i);
1676f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        if (info.mToBeRemoved) {
1677f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            info.mToBeRemoved = false;
1678f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        }
1679f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    }
1680f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih
1681f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
1682f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        if (!mStreams[i].mNewUri.empty()) {
1683f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            ssize_t j = mFetcherInfos.indexOfKey(mStreams[i].mNewUri);
1684f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            if (j < 0) {
1685f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih                mStreams[i].mNewUri.clear();
1686f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih                continue;
1687f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            }
1688f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih
1689f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            const FetcherInfo &info = mFetcherInfos.valueAt(j);
1690f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            info.mFetcher->stopAsync();
1691f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            mFetcherInfos.removeItemsAt(j);
1692f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            mStreams[i].mNewUri.clear();
1693f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        }
1694f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    }
16951543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
16961543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
16971543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shihbool LiveSession::canSwitchBandwidthTo(size_t bandwidthIndex) {
16981543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    if (mReconfigurationInProgress || mSwitchInProgress) {
16991543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return false;
17001543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
17011543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
1702309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    if (mCurBandwidthIndex < 0) {
17031543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return true;
170414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
170514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
1706309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    if (bandwidthIndex == (size_t)mCurBandwidthIndex) {
17071543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return false;
1708309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    } else if (bandwidthIndex > (size_t)mCurBandwidthIndex) {
17091543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return canSwitchUp();
17101543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    } else {
17111543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return true;
17121543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
17131543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
17141543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
171500598ec0b15426197494aaf9e5ec0bc88507c762Robert Shihvoid LiveSession::onCheckBandwidth(const sp<AMessage> &msg) {
171614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    size_t bandwidthIndex = getBandwidthIndex();
17171543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    if (canSwitchBandwidthTo(bandwidthIndex)) {
171814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        changeConfiguration(-1ll /* timeUs */, bandwidthIndex);
17191543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    } else {
172000598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih        // Come back and check again 10 seconds later in case there is nothing to do now.
172100598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih        // If we DO change configuration, once that completes it'll schedule a new
172200598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih        // check bandwidth event with an incremented mCheckBandwidthGeneration.
172300598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih        msg->post(10000000ll);
172414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
1725a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
1726a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
172714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::postPrepared(status_t err) {
172814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(mInPreparationPhase);
1729a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
173014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> notify = mNotify->dup();
173114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (err == OK || err == ERROR_END_OF_STREAM) {
173214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        notify->setInt32("what", kWhatPrepared);
173314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    } else {
173414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        notify->setInt32("what", kWhatPreparationFailed);
173514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        notify->setInt32("err", err);
173614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
1737a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
173814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->post();
1739a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
174014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mInPreparationPhase = false;
17410ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
17420ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    mSwitchDownMonitor = new AMessage(kWhatCheckSwitchDown, id());
17430ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    mSwitchDownMonitor->post();
1744b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber}
1745b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
1746a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}  // namespace android
1747a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1748