LiveSession.cpp revision 678bcdc852dd8f801f5c46fdc85db587b721d83d
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
52a93fd2be99d21629bed504b9b7df035fc2f54562Leena Winterrowd// Number of recently-read bytes to use for bandwidth estimation
53a93fd2be99d21629bed504b9b7df035fc2f54562Leena Winterrowdconst size_t LiveSession::kBandwidthHistoryBytes = 200 * 1024;
54a93fd2be99d21629bed504b9b7df035fc2f54562Leena Winterrowd
550df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas HuberLiveSession::LiveSession(
561b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        const sp<AMessage> &notify, uint32_t flags,
5781e68448f3361eaf8618930471fdc3c21bdf5cbcAndreas Huber        const sp<IMediaHTTPService> &httpService)
580df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas Huber    : mNotify(notify),
590df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas Huber      mFlags(flags),
601b86fe063badb5f28c467ade39be0f4008688947Andreas Huber      mHTTPService(httpService),
610df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas Huber      mInPreparationPhase(true),
621b86fe063badb5f28c467ade39be0f4008688947Andreas Huber      mHTTPDataSource(new MediaHTTP(mHTTPService->makeHTTPConnection())),
63309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih      mCurBandwidthIndex(-1),
6414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber      mStreamMask(0),
651543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih      mNewStreamMask(0),
661543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih      mSwapMask(0),
6714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber      mCheckBandwidthGeneration(0),
681543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih      mSwitchGeneration(0),
69b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih      mSubtitleGeneration(0),
7014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber      mLastDequeuedTimeUs(0ll),
71dcb89b3b505522efde173c105a851c412f947178Chong Zhang      mRealTimeBaseUs(0ll),
7214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber      mReconfigurationInProgress(false),
731543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih      mSwitchInProgress(false),
745ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih      mDisconnectReplyID(0),
75309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih      mSeekReplyID(0),
76309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih      mFirstTimeUsValid(false),
77309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih      mFirstTimeUs(0),
78309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih      mLastSeekTimeUs(0) {
7914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
808ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    mStreams[kAudioIndex] = StreamItem("audio");
818ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    mStreams[kVideoIndex] = StreamItem("video");
82e4f25c280a8f1655c31a745978e0fcbc61f91deeRobert Shih    mStreams[kSubtitleIndex] = StreamItem("subtitles");
8314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
848ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
85309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        mDiscontinuities.add(indexToType(i), new AnotherPacketSource(NULL /* meta */));
868ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        mPacketSources.add(indexToType(i), new AnotherPacketSource(NULL /* meta */));
871543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        mPacketSources2.add(indexToType(i), new AnotherPacketSource(NULL /* meta */));
88f69c996864844e8f669308af8412cede043062a2Robert Shih        mBuffering[i] = false;
898ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    }
90a93fd2be99d21629bed504b9b7df035fc2f54562Leena Winterrowd
91a93fd2be99d21629bed504b9b7df035fc2f54562Leena Winterrowd    size_t numHistoryItems = kBandwidthHistoryBytes /
92a93fd2be99d21629bed504b9b7df035fc2f54562Leena Winterrowd            PlaylistFetcher::kDownloadBlockSize + 1;
93a93fd2be99d21629bed504b9b7df035fc2f54562Leena Winterrowd    if (numHistoryItems < 5) {
94a93fd2be99d21629bed504b9b7df035fc2f54562Leena Winterrowd        numHistoryItems = 5;
95a93fd2be99d21629bed504b9b7df035fc2f54562Leena Winterrowd    }
96a93fd2be99d21629bed504b9b7df035fc2f54562Leena Winterrowd    mHTTPDataSource->setBandwidthHistorySize(numHistoryItems);
97a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
98a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
99a44153c1a57202fb538659eb50706e60454d6273Andreas HuberLiveSession::~LiveSession() {
100a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
101a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1021543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shihsp<ABuffer> LiveSession::createFormatChangeBuffer(bool swap) {
1031543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    ABuffer *discontinuity = new ABuffer(0);
1041543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    discontinuity->meta()->setInt32("discontinuity", ATSParser::DISCONTINUITY_FORMATCHANGE);
1051543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    discontinuity->meta()->setInt32("swapPacketSource", swap);
1061543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    discontinuity->meta()->setInt32("switchGeneration", mSwitchGeneration);
1071543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    discontinuity->meta()->setInt64("timeUs", -1);
1081543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    return discontinuity;
1091543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
1101543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
1111543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shihvoid LiveSession::swapPacketSource(StreamType stream) {
1121543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    sp<AnotherPacketSource> &aps = mPacketSources.editValueFor(stream);
1131543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    sp<AnotherPacketSource> &aps2 = mPacketSources2.editValueFor(stream);
1141543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    sp<AnotherPacketSource> tmp = aps;
1151543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    aps = aps2;
1161543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    aps2 = tmp;
1171543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    aps2->clear();
1181543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
1191543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
12014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::dequeueAccessUnit(
12114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        StreamType stream, sp<ABuffer> *accessUnit) {
12214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (!(mStreamMask & stream)) {
1231543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        // return -EWOULDBLOCK to avoid halting the decoder
1241543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        // when switching between audio/video and audio only.
1251543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return -EWOULDBLOCK;
12614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
12714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
128309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    status_t finalResult;
129309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    sp<AnotherPacketSource> discontinuityQueue  = mDiscontinuities.valueFor(stream);
130309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    if (discontinuityQueue->hasBufferAvailable(&finalResult)) {
131309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        discontinuityQueue->dequeueAccessUnit(accessUnit);
132309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        // seeking, track switching
133309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        sp<AMessage> extra;
134309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        int64_t timeUs;
135309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        if ((*accessUnit)->meta()->findMessage("extra", &extra)
136309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                && extra != NULL
137309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                && extra->findInt64("timeUs", &timeUs)) {
138309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            // seeking only
139309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            mLastSeekTimeUs = timeUs;
140309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            mDiscontinuityOffsetTimesUs.clear();
141309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            mDiscontinuityAbsStartTimesUs.clear();
142309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        }
143309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        return INFO_DISCONTINUITY;
144309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    }
145309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
14614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AnotherPacketSource> packetSource = mPacketSources.valueFor(stream);
14714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
148f69c996864844e8f669308af8412cede043062a2Robert Shih    ssize_t idx = typeToIndex(stream);
14914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (!packetSource->hasBufferAvailable(&finalResult)) {
150f69c996864844e8f669308af8412cede043062a2Robert Shih        if (finalResult == OK) {
151f69c996864844e8f669308af8412cede043062a2Robert Shih            mBuffering[idx] = true;
152f69c996864844e8f669308af8412cede043062a2Robert Shih            return -EAGAIN;
153f69c996864844e8f669308af8412cede043062a2Robert Shih        } else {
154f69c996864844e8f669308af8412cede043062a2Robert Shih            return finalResult;
155f69c996864844e8f669308af8412cede043062a2Robert Shih        }
156f69c996864844e8f669308af8412cede043062a2Robert Shih    }
157f69c996864844e8f669308af8412cede043062a2Robert Shih
158174609765fb9c8cbd6aeb61f489746c3570bfee2Leena Winterrowd    int32_t targetDuration = 0;
159174609765fb9c8cbd6aeb61f489746c3570bfee2Leena Winterrowd    sp<AMessage> meta = packetSource->getLatestEnqueuedMeta();
160174609765fb9c8cbd6aeb61f489746c3570bfee2Leena Winterrowd    if (meta != NULL) {
161174609765fb9c8cbd6aeb61f489746c3570bfee2Leena Winterrowd        meta->findInt32("targetDuration", &targetDuration);
162174609765fb9c8cbd6aeb61f489746c3570bfee2Leena Winterrowd    }
163174609765fb9c8cbd6aeb61f489746c3570bfee2Leena Winterrowd
164174609765fb9c8cbd6aeb61f489746c3570bfee2Leena Winterrowd    int64_t targetDurationUs = targetDuration * 1000000ll;
165174609765fb9c8cbd6aeb61f489746c3570bfee2Leena Winterrowd    if (targetDurationUs == 0 ||
166174609765fb9c8cbd6aeb61f489746c3570bfee2Leena Winterrowd            targetDurationUs > PlaylistFetcher::kMinBufferedDurationUs) {
167174609765fb9c8cbd6aeb61f489746c3570bfee2Leena Winterrowd        // Fetchers limit buffering to
168174609765fb9c8cbd6aeb61f489746c3570bfee2Leena Winterrowd        // min(3 * targetDuration, kMinBufferedDurationUs)
169174609765fb9c8cbd6aeb61f489746c3570bfee2Leena Winterrowd        targetDurationUs = PlaylistFetcher::kMinBufferedDurationUs;
170174609765fb9c8cbd6aeb61f489746c3570bfee2Leena Winterrowd    }
171174609765fb9c8cbd6aeb61f489746c3570bfee2Leena Winterrowd
172f69c996864844e8f669308af8412cede043062a2Robert Shih    if (mBuffering[idx]) {
173f69c996864844e8f669308af8412cede043062a2Robert Shih        if (mSwitchInProgress
174f69c996864844e8f669308af8412cede043062a2Robert Shih                || packetSource->isFinished(0)
175174609765fb9c8cbd6aeb61f489746c3570bfee2Leena Winterrowd                || packetSource->getEstimatedDurationUs() > targetDurationUs) {
176f69c996864844e8f669308af8412cede043062a2Robert Shih            mBuffering[idx] = false;
177f69c996864844e8f669308af8412cede043062a2Robert Shih        }
178f69c996864844e8f669308af8412cede043062a2Robert Shih    }
179f69c996864844e8f669308af8412cede043062a2Robert Shih
180f69c996864844e8f669308af8412cede043062a2Robert Shih    if (mBuffering[idx]) {
181f69c996864844e8f669308af8412cede043062a2Robert Shih        return -EAGAIN;
18214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
18314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
184309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    // wait for counterpart
185309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    sp<AnotherPacketSource> otherSource;
18673d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih    uint32_t mask = mNewStreamMask & mStreamMask;
18773d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih    uint32_t fetchersMask  = 0;
18873d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
18973d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih        uint32_t fetcherMask = mFetcherInfos.valueAt(i).mFetcher->getStreamTypeMask();
19073d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih        fetchersMask |= fetcherMask;
19173d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih    }
19273d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih    mask &= fetchersMask;
19373d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih    if (stream == STREAMTYPE_AUDIO && (mask & STREAMTYPE_VIDEO)) {
194309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        otherSource = mPacketSources.valueFor(STREAMTYPE_VIDEO);
19573d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih    } else if (stream == STREAMTYPE_VIDEO && (mask & STREAMTYPE_AUDIO)) {
196309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        otherSource = mPacketSources.valueFor(STREAMTYPE_AUDIO);
197309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    }
198309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    if (otherSource != NULL && !otherSource->hasBufferAvailable(&finalResult)) {
199309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        return finalResult == OK ? -EAGAIN : finalResult;
200309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    }
201309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
20214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    status_t err = packetSource->dequeueAccessUnit(accessUnit);
20314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
204309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    size_t streamIdx;
20514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    const char *streamStr;
20614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    switch (stream) {
20714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case STREAMTYPE_AUDIO:
208309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            streamIdx = kAudioIndex;
20914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            streamStr = "audio";
21014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            break;
21114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case STREAMTYPE_VIDEO:
212309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            streamIdx = kVideoIndex;
21314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            streamStr = "video";
21414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            break;
21514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case STREAMTYPE_SUBTITLES:
216309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            streamIdx = kSubtitleIndex;
21714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            streamStr = "subs";
21814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            break;
21914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        default:
22014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            TRESPASS();
22114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
22214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
223309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    StreamItem& strm = mStreams[streamIdx];
22414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (err == INFO_DISCONTINUITY) {
225309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        // adaptive streaming, discontinuities in the playlist
22614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        int32_t type;
22714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        CHECK((*accessUnit)->meta()->findInt32("discontinuity", &type));
22814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
22914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        sp<AMessage> extra;
23014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (!(*accessUnit)->meta()->findMessage("extra", &extra)) {
23114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            extra.clear();
23214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
23314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
23414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        ALOGI("[%s] read discontinuity of type %d, extra = %s",
23514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber              streamStr,
23614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber              type,
23714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber              extra == NULL ? "NULL" : extra->debugString().c_str());
2381543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
2391543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        int32_t swap;
240309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        if ((*accessUnit)->meta()->findInt32("swapPacketSource", &swap) && swap) {
2411543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            int32_t switchGeneration;
2421543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            CHECK((*accessUnit)->meta()->findInt32("switchGeneration", &switchGeneration));
2431543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            {
2441543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                Mutex::Autolock lock(mSwapMutex);
2451543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                if (switchGeneration == mSwitchGeneration) {
2461543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    swapPacketSource(stream);
2471543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    sp<AMessage> msg = new AMessage(kWhatSwapped, id());
2481543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    msg->setInt32("stream", stream);
2491543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    msg->setInt32("switchGeneration", switchGeneration);
2501543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    msg->post();
2511543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                }
2521543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            }
253309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        } else {
254309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            size_t seq = strm.mCurDiscontinuitySeq;
255309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            int64_t offsetTimeUs;
256309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            if (mDiscontinuityOffsetTimesUs.indexOfKey(seq) >= 0) {
257309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                offsetTimeUs = mDiscontinuityOffsetTimesUs.valueFor(seq);
258309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            } else {
259309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                offsetTimeUs = 0;
260309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            }
261309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
262309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            seq += 1;
263309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            if (mDiscontinuityAbsStartTimesUs.indexOfKey(strm.mCurDiscontinuitySeq) >= 0) {
264309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                int64_t firstTimeUs;
265309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                firstTimeUs = mDiscontinuityAbsStartTimesUs.valueFor(strm.mCurDiscontinuitySeq);
266309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                offsetTimeUs += strm.mLastDequeuedTimeUs - firstTimeUs;
267309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                offsetTimeUs += strm.mLastSampleDurationUs;
268309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            } else {
269309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                offsetTimeUs += strm.mLastSampleDurationUs;
270309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            }
271309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
272309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            mDiscontinuityOffsetTimesUs.add(seq, offsetTimeUs);
2731543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        }
27414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    } else if (err == OK) {
275309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
276dcb89b3b505522efde173c105a851c412f947178Chong Zhang        if (stream == STREAMTYPE_AUDIO || stream == STREAMTYPE_VIDEO) {
277dcb89b3b505522efde173c105a851c412f947178Chong Zhang            int64_t timeUs;
278309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            int32_t discontinuitySeq = 0;
279dcb89b3b505522efde173c105a851c412f947178Chong Zhang            CHECK((*accessUnit)->meta()->findInt64("timeUs",  &timeUs));
280309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            (*accessUnit)->meta()->findInt32("discontinuitySeq", &discontinuitySeq);
281309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            strm.mCurDiscontinuitySeq = discontinuitySeq;
282309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
283309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            int32_t discard = 0;
284309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            int64_t firstTimeUs;
285309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            if (mDiscontinuityAbsStartTimesUs.indexOfKey(strm.mCurDiscontinuitySeq) >= 0) {
286309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                int64_t durUs; // approximate sample duration
287309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                if (timeUs > strm.mLastDequeuedTimeUs) {
288309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    durUs = timeUs - strm.mLastDequeuedTimeUs;
289309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                } else {
290309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    durUs = strm.mLastDequeuedTimeUs - timeUs;
291309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                }
292309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                strm.mLastSampleDurationUs = durUs;
293309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                firstTimeUs = mDiscontinuityAbsStartTimesUs.valueFor(strm.mCurDiscontinuitySeq);
294309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            } else if ((*accessUnit)->meta()->findInt32("discard", &discard) && discard) {
295309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                firstTimeUs = timeUs;
296309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            } else {
297309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                mDiscontinuityAbsStartTimesUs.add(strm.mCurDiscontinuitySeq, timeUs);
298309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                firstTimeUs = timeUs;
299309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            }
300309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
301309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            strm.mLastDequeuedTimeUs = timeUs;
302309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            if (timeUs >= firstTimeUs) {
303309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                timeUs -= firstTimeUs;
304309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            } else {
305309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                timeUs = 0;
306309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            }
307309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            timeUs += mLastSeekTimeUs;
308309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            if (mDiscontinuityOffsetTimesUs.indexOfKey(discontinuitySeq) >= 0) {
309309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                timeUs += mDiscontinuityOffsetTimesUs.valueFor(discontinuitySeq);
310309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            }
311dcb89b3b505522efde173c105a851c412f947178Chong Zhang
312309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            ALOGV("[%s] read buffer at time %" PRId64 " us", streamStr, timeUs);
313309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            (*accessUnit)->meta()->setInt64("timeUs",  timeUs);
314dcb89b3b505522efde173c105a851c412f947178Chong Zhang            mLastDequeuedTimeUs = timeUs;
315dcb89b3b505522efde173c105a851c412f947178Chong Zhang            mRealTimeBaseUs = ALooper::GetNowUs() - timeUs;
316dcb89b3b505522efde173c105a851c412f947178Chong Zhang        } else if (stream == STREAMTYPE_SUBTITLES) {
317b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih            int32_t subtitleGeneration;
318b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih            if ((*accessUnit)->meta()->findInt32("subtitleGeneration", &subtitleGeneration)
319b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih                    && subtitleGeneration != mSubtitleGeneration) {
320b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih               return -EAGAIN;
321b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih            };
322dcb89b3b505522efde173c105a851c412f947178Chong Zhang            (*accessUnit)->meta()->setInt32(
323dcb89b3b505522efde173c105a851c412f947178Chong Zhang                    "trackIndex", mPlaylist->getSelectedIndex());
324dcb89b3b505522efde173c105a851c412f947178Chong Zhang            (*accessUnit)->meta()->setInt64("baseUs", mRealTimeBaseUs);
325dcb89b3b505522efde173c105a851c412f947178Chong Zhang        }
32614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    } else {
32714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        ALOGI("[%s] encountered error %d", streamStr, err);
32814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
32914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
33014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return err;
33114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
33214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
33314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::getStreamFormat(StreamType stream, sp<AMessage> *format) {
3341543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // No swapPacketSource race condition; called from the same thread as dequeueAccessUnit.
33514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (!(mStreamMask & stream)) {
33614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        return UNKNOWN_ERROR;
33714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
33814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
33914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AnotherPacketSource> packetSource = mPacketSources.valueFor(stream);
34014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
34114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<MetaData> meta = packetSource->getFormat();
34214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
34314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (meta == NULL) {
34414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        return -EAGAIN;
34514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
34614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
34714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return convertMetaDataToMessage(meta, format);
348a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
349a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
35014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::connectAsync(
351ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        const char *url, const KeyedVector<String8, String8> *headers) {
352a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<AMessage> msg = new AMessage(kWhatConnect, id());
353a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    msg->setString("url", url);
354ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber
355ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    if (headers != NULL) {
356ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        msg->setPointer(
357ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber                "headers",
358ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber                new KeyedVector<String8, String8>(*headers));
359ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    }
360ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber
361a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    msg->post();
362a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
363a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
36414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::disconnect() {
36514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> msg = new AMessage(kWhatDisconnect, id());
366ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
36714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> response;
36814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    status_t err = msg->postAndAwaitResponse(&response);
369ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
37014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return err;
371a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
372a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
37314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::seekTo(int64_t timeUs) {
374a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<AMessage> msg = new AMessage(kWhatSeek, id());
375a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    msg->setInt64("timeUs", timeUs);
376a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
37714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> response;
37814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    status_t err = msg->postAndAwaitResponse(&response);
37914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
38014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return err;
381a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
382a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
383a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onMessageReceived(const sp<AMessage> &msg) {
384a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    switch (msg->what()) {
385a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        case kWhatConnect:
38614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
387a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            onConnect(msg);
388a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
38914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
390a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
391a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        case kWhatDisconnect:
39214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
39314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            CHECK(msg->senderAwaitsResponse(&mDisconnectReplyID));
39414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
39514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            if (mReconfigurationInProgress) {
39614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                break;
39714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            }
39814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
39914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            finishDisconnect();
400a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
40114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
402a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
40314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case kWhatSeek:
40414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
405800599cdd50737de1cde483a34b39923750b0658Robert Shih            uint32_t seekReplyID;
406800599cdd50737de1cde483a34b39923750b0658Robert Shih            CHECK(msg->senderAwaitsResponse(&seekReplyID));
407800599cdd50737de1cde483a34b39923750b0658Robert Shih            mSeekReplyID = seekReplyID;
408800599cdd50737de1cde483a34b39923750b0658Robert Shih            mSeekReply = new AMessage;
40914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
41014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            status_t err = onSeek(msg);
41114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
412800599cdd50737de1cde483a34b39923750b0658Robert Shih            if (err != OK) {
413800599cdd50737de1cde483a34b39923750b0658Robert Shih                msg->post(50000);
414800599cdd50737de1cde483a34b39923750b0658Robert Shih            }
41514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            break;
41614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
41714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
41814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case kWhatFetcherNotify:
41914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
42014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            int32_t what;
42114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            CHECK(msg->findInt32("what", &what));
42214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
42314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            switch (what) {
42414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                case PlaylistFetcher::kWhatStarted:
42514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    break;
42614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                case PlaylistFetcher::kWhatPaused:
42714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                case PlaylistFetcher::kWhatStopped:
42814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                {
42914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    if (what == PlaylistFetcher::kWhatStopped) {
43014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        AString uri;
43114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        CHECK(msg->findString("uri", &uri));
4321543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        if (mFetcherInfos.removeItem(uri) < 0) {
4331543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                            // ignore duplicated kWhatStopped messages.
4341543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                            break;
4351543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        }
4361543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
437309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        if (mSwitchInProgress) {
438309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                            tryToFinishBandwidthSwitch();
439309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        }
44014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    }
44114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
44214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    if (mContinuation != NULL) {
44314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        CHECK_GT(mContinuationCounter, 0);
44414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        if (--mContinuationCounter == 0) {
44514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                            mContinuation->post();
4465ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih
4475ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih                            if (mSeekReplyID != 0) {
4485ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih                                CHECK(mSeekReply != NULL);
449800599cdd50737de1cde483a34b39923750b0658Robert Shih                                mSeekReply->setInt32("err", OK);
4505ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih                                mSeekReply->postReply(mSeekReplyID);
451800599cdd50737de1cde483a34b39923750b0658Robert Shih                                mSeekReplyID = 0;
452800599cdd50737de1cde483a34b39923750b0658Robert Shih                                mSeekReply.clear();
4535ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih                            }
45414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        }
45514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    }
45614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    break;
45714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                }
45814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
45914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                case PlaylistFetcher::kWhatDurationUpdate:
46014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                {
46114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    AString uri;
46214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    CHECK(msg->findString("uri", &uri));
46314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
46414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    int64_t durationUs;
46514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    CHECK(msg->findInt64("durationUs", &durationUs));
46614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
46714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    FetcherInfo *info = &mFetcherInfos.editValueFor(uri);
46814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    info->mDurationUs = durationUs;
46914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    break;
47014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                }
47114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
47214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                case PlaylistFetcher::kWhatError:
47314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                {
47414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    status_t err;
47514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    CHECK(msg->findInt32("err", &err));
47614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
47714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    ALOGE("XXX Received error %d from PlaylistFetcher.", err);
47814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
47915f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                    // handle EOS on subtitle tracks independently
48015f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                    AString uri;
48115f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                    if (err == ERROR_END_OF_STREAM && msg->findString("uri", &uri)) {
48215f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                        ssize_t i = mFetcherInfos.indexOfKey(uri);
48315f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                        if (i >= 0) {
48415f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                            const sp<PlaylistFetcher> &fetcher = mFetcherInfos.valueAt(i).mFetcher;
48515f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                            if (fetcher != NULL) {
48615f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                                uint32_t type = fetcher->getStreamTypeMask();
48715f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                                if (type == STREAMTYPE_SUBTITLES) {
48815f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                                    mPacketSources.valueFor(
48915f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                                            STREAMTYPE_SUBTITLES)->signalEOS(err);;
49015f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                                    break;
49115f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                                }
49215f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                            }
49315f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                        }
49415f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                    }
49515f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih
49614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    if (mInPreparationPhase) {
49714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        postPrepared(err);
49814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    }
49914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
5001543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    cancelBandwidthSwitch();
5011543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
50214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    mPacketSources.valueFor(STREAMTYPE_AUDIO)->signalEOS(err);
50314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
50414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    mPacketSources.valueFor(STREAMTYPE_VIDEO)->signalEOS(err);
50514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
50614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    mPacketSources.valueFor(
50714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                            STREAMTYPE_SUBTITLES)->signalEOS(err);
50814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
50914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    sp<AMessage> notify = mNotify->dup();
51014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    notify->setInt32("what", kWhatError);
51114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    notify->setInt32("err", err);
51214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    notify->post();
51314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    break;
51414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                }
51514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
51614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                case PlaylistFetcher::kWhatTemporarilyDoneFetching:
51714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                {
51814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    AString uri;
51914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    CHECK(msg->findString("uri", &uri));
52014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
5216300cbe99899da0103c910ba6a35c785261ce433Marco Nelissen                    if (mFetcherInfos.indexOfKey(uri) < 0) {
5226300cbe99899da0103c910ba6a35c785261ce433Marco Nelissen                        ALOGE("couldn't find uri");
5236300cbe99899da0103c910ba6a35c785261ce433Marco Nelissen                        break;
5246300cbe99899da0103c910ba6a35c785261ce433Marco Nelissen                    }
52514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    FetcherInfo *info = &mFetcherInfos.editValueFor(uri);
52614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    info->mIsPrepared = true;
52714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
52814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    if (mInPreparationPhase) {
52914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        bool allFetchersPrepared = true;
53014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
53114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                            if (!mFetcherInfos.valueAt(i).mIsPrepared) {
53214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                                allFetchersPrepared = false;
53314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                                break;
53414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                            }
53514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        }
53614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
53714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        if (allFetchersPrepared) {
53814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                            postPrepared(OK);
53914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        }
54014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    }
54114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    break;
54214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                }
54314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
5441543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                case PlaylistFetcher::kWhatStartedAt:
5451543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                {
5461543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    int32_t switchGeneration;
5471543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    CHECK(msg->findInt32("switchGeneration", &switchGeneration));
5481543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
5491543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    if (switchGeneration != mSwitchGeneration) {
5501543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        break;
5511543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    }
5521543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
5531543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    // Resume fetcher for the original variant; the resumed fetcher should
5541543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    // continue until the timestamps found in msg, which is stored by the
5551543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    // new fetcher to indicate where the new variant has started buffering.
5561543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    for (size_t i = 0; i < mFetcherInfos.size(); i++) {
5571543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        const FetcherInfo info = mFetcherInfos.valueAt(i);
5581543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        if (info.mToBeRemoved) {
5591543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                            info.mFetcher->resumeUntilAsync(msg);
5601543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        }
5611543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    }
5621543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    break;
5631543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                }
5641543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
56514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                default:
56614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    TRESPASS();
56714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            }
56814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
56914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            break;
57014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
57114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
57214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case kWhatCheckBandwidth:
573a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        {
574a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            int32_t generation;
575a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            CHECK(msg->findInt32("generation", &generation));
576a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
57714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            if (generation != mCheckBandwidthGeneration) {
578a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                break;
579a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            }
580a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
58100598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih            onCheckBandwidth(msg);
582a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
583a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
584a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
585dcb89b3b505522efde173c105a851c412f947178Chong Zhang        case kWhatChangeConfiguration:
586dcb89b3b505522efde173c105a851c412f947178Chong Zhang        {
587dcb89b3b505522efde173c105a851c412f947178Chong Zhang            onChangeConfiguration(msg);
588dcb89b3b505522efde173c105a851c412f947178Chong Zhang            break;
589dcb89b3b505522efde173c105a851c412f947178Chong Zhang        }
590dcb89b3b505522efde173c105a851c412f947178Chong Zhang
59114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case kWhatChangeConfiguration2:
59214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
59314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            onChangeConfiguration2(msg);
59414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            break;
59514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
59614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
59714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case kWhatChangeConfiguration3:
59814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
59914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            onChangeConfiguration3(msg);
60014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            break;
60114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
60214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
60314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case kWhatFinishDisconnect2:
60414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
60514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            onFinishDisconnect2();
606a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
60714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
608a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
6091543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        case kWhatSwapped:
6101543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        {
6111543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            onSwapped(msg);
6121543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            break;
6131543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        }
6140ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
6150ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        case kWhatCheckSwitchDown:
6160ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        {
6170ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih            onCheckSwitchDown();
6180ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih            break;
6190ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        }
6200ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
6210ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        case kWhatSwitchDown:
6220ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        {
6230ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih            onSwitchDown();
6240ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih            break;
6250ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        }
6260ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
627a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        default:
628a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            TRESPASS();
629a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
630a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
631a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
632a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
633a44153c1a57202fb538659eb50706e60454d6273Andreas Huber// static
634a44153c1a57202fb538659eb50706e60454d6273Andreas Huberint LiveSession::SortByBandwidth(const BandwidthItem *a, const BandwidthItem *b) {
635a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (a->mBandwidth < b->mBandwidth) {
636a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return -1;
637a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else if (a->mBandwidth == b->mBandwidth) {
638a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return 0;
639a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
640a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
641a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return 1;
642a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
643a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
6448ca002eedc747dd854b61cbe364b52c06869273fRobert Shih// static
6458ca002eedc747dd854b61cbe364b52c06869273fRobert ShihLiveSession::StreamType LiveSession::indexToType(int idx) {
6468ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    CHECK(idx >= 0 && idx < kMaxStreams);
6478ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    return (StreamType)(1 << idx);
6488ca002eedc747dd854b61cbe364b52c06869273fRobert Shih}
6498ca002eedc747dd854b61cbe364b52c06869273fRobert Shih
650f69c996864844e8f669308af8412cede043062a2Robert Shih// static
651f69c996864844e8f669308af8412cede043062a2Robert Shihssize_t LiveSession::typeToIndex(int32_t type) {
652f69c996864844e8f669308af8412cede043062a2Robert Shih    switch (type) {
653f69c996864844e8f669308af8412cede043062a2Robert Shih        case STREAMTYPE_AUDIO:
654f69c996864844e8f669308af8412cede043062a2Robert Shih            return 0;
655f69c996864844e8f669308af8412cede043062a2Robert Shih        case STREAMTYPE_VIDEO:
656f69c996864844e8f669308af8412cede043062a2Robert Shih            return 1;
657f69c996864844e8f669308af8412cede043062a2Robert Shih        case STREAMTYPE_SUBTITLES:
658f69c996864844e8f669308af8412cede043062a2Robert Shih            return 2;
659f69c996864844e8f669308af8412cede043062a2Robert Shih        default:
660f69c996864844e8f669308af8412cede043062a2Robert Shih            return -1;
661f69c996864844e8f669308af8412cede043062a2Robert Shih    };
662f69c996864844e8f669308af8412cede043062a2Robert Shih    return -1;
663f69c996864844e8f669308af8412cede043062a2Robert Shih}
664f69c996864844e8f669308af8412cede043062a2Robert Shih
665a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onConnect(const sp<AMessage> &msg) {
666a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    AString url;
667a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    CHECK(msg->findString("url", &url));
668a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
669ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    KeyedVector<String8, String8> *headers = NULL;
670ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    if (!msg->findPointer("headers", (void **)&headers)) {
671ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        mExtraHeaders.clear();
672ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    } else {
673ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        mExtraHeaders = *headers;
674ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber
675ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        delete headers;
676ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        headers = NULL;
677ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    }
678ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber
679a1df816c0677185534babba6ffc29970b048e52eLajos Molnar    // TODO currently we don't know if we are coming here from incognito mode
680a1df816c0677185534babba6ffc29970b048e52eLajos Molnar    ALOGI("onConnect %s", uriDebugString(url).c_str());
681a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
682a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    mMasterURL = url;
683a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
6847e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    bool dummy;
68514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mPlaylist = fetchPlaylist(url.c_str(), NULL /* curPlaylistHash */, &dummy);
686ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
68714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (mPlaylist == NULL) {
688a1df816c0677185534babba6ffc29970b048e52eLajos Molnar        ALOGE("unable to fetch master playlist %s.", uriDebugString(url).c_str());
689ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
69014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        postPrepared(ERROR_IO);
691ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber        return;
692ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber    }
693a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
69414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // We trust the content provider to make a reasonable choice of preferred
69514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // initial bandwidth by listing it first in the variant playlist.
69614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // At startup we really don't have a good estimate on the available
69714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // network bandwidth since we haven't tranferred any data yet. Once
69814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // we have we can make a better informed choice.
69914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    size_t initialBandwidth = 0;
70014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    size_t initialBandwidthIndex = 0;
70114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
70214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (mPlaylist->isVariantPlaylist()) {
70314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        for (size_t i = 0; i < mPlaylist->size(); ++i) {
704a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            BandwidthItem item;
705a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
70614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            item.mPlaylistIndex = i;
70714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
708a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            sp<AMessage> meta;
70914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            AString uri;
71014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            mPlaylist->itemAt(i, &uri, &meta);
711a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
712a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            unsigned long bandwidth;
713a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            CHECK(meta->findInt32("bandwidth", (int32_t *)&item.mBandwidth));
714a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
71514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            if (initialBandwidth == 0) {
71614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                initialBandwidth = item.mBandwidth;
71714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            }
71814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
719a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            mBandwidthItems.push(item);
720a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
721a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
722a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        CHECK_GT(mBandwidthItems.size(), 0u);
723a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
724a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        mBandwidthItems.sort(SortByBandwidth);
72514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
72614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        for (size_t i = 0; i < mBandwidthItems.size(); ++i) {
72714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            if (mBandwidthItems.itemAt(i).mBandwidth == initialBandwidth) {
72814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                initialBandwidthIndex = i;
72914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                break;
73014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            }
73114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
73214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    } else {
73314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        // dummy item.
73414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        BandwidthItem item;
73514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        item.mPlaylistIndex = 0;
73614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        item.mBandwidth = 0;
73714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        mBandwidthItems.push(item);
738a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
739a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
740309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    mPlaylist->pickRandomMediaItems();
741dcb89b3b505522efde173c105a851c412f947178Chong Zhang    changeConfiguration(
742309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            0ll /* timeUs */, initialBandwidthIndex, false /* pickTrack */);
743a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
744a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
74514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::finishDisconnect() {
74614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // No reconfiguration is currently pending, make sure none will trigger
74714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // during disconnection either.
74814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    cancelCheckBandwidthEvent();
74914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
7501543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // Protect mPacketSources from a swapPacketSource race condition through disconnect.
7511543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // (finishDisconnect, onFinishDisconnect2)
7521543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    cancelBandwidthSwitch();
7531543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
7540ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    // cancel switch down monitor
7550ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    mSwitchDownMonitor.clear();
7560ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
75714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
75814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        mFetcherInfos.valueAt(i).mFetcher->stopAsync();
75914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
76014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
76114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> msg = new AMessage(kWhatFinishDisconnect2, id());
762a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
76314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mContinuationCounter = mFetcherInfos.size();
76414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mContinuation = msg;
765ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
76614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (mContinuationCounter == 0) {
76714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        msg->post();
76814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
76914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
77014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
77114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::onFinishDisconnect2() {
77214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mContinuation.clear();
77314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
77414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mPacketSources.valueFor(STREAMTYPE_AUDIO)->signalEOS(ERROR_END_OF_STREAM);
77514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mPacketSources.valueFor(STREAMTYPE_VIDEO)->signalEOS(ERROR_END_OF_STREAM);
77614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
77714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mPacketSources.valueFor(
77814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            STREAMTYPE_SUBTITLES)->signalEOS(ERROR_END_OF_STREAM);
77914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
78014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> response = new AMessage;
78114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    response->setInt32("err", OK);
78214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
78314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    response->postReply(mDisconnectReplyID);
78414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mDisconnectReplyID = 0;
78514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
78614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
78714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubersp<PlaylistFetcher> LiveSession::addFetcher(const char *uri) {
78814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    ssize_t index = mFetcherInfos.indexOfKey(uri);
78914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
79014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (index >= 0) {
79114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        return NULL;
79214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
79314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
79414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> notify = new AMessage(kWhatFetcherNotify, id());
79514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->setString("uri", uri);
7961543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    notify->setInt32("switchGeneration", mSwitchGeneration);
79714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
79814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    FetcherInfo info;
799b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    info.mFetcher = new PlaylistFetcher(notify, this, uri, mSubtitleGeneration);
80014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    info.mDurationUs = -1ll;
80114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    info.mIsPrepared = false;
8021543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    info.mToBeRemoved = false;
80314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    looper()->registerHandler(info.mFetcher);
80414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
80514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mFetcherInfos.add(uri, info);
80614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
80714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return info.mFetcher;
808a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
809a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
8108dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih/*
8118dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * Illustration of parameters:
8128dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih *
8138dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * 0      `range_offset`
8148dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * +------------+-------------------------------------------------------+--+--+
8158dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * |            |                                 | next block to fetch |  |  |
8168dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * |            | `source` handle => `out` buffer |                     |  |  |
8178dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * | `url` file |<--------- buffer size --------->|<--- `block_size` -->|  |  |
8188dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * |            |<----------- `range_length` / buffer capacity ----------->|  |
8198dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * |<------------------------------ file_size ------------------------------->|
8208dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih *
8218dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * Special parameter values:
8228dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * - range_length == -1 means entire file
8238dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * - block_size == 0 means entire range
8248dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih *
8258dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih */
82643ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shihssize_t LiveSession::fetchFile(
8272aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        const char *url, sp<ABuffer> *out,
8288dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        int64_t range_offset, int64_t range_length,
8298dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        uint32_t block_size, /* download block size */
83097194cdf8d67f362ef8c6dfdf607298c7e102b3bMarco Nelissen        sp<DataSource> *source, /* to return and reuse source */
831784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo        String8 *actualUrl) {
8328dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    off64_t size;
8338dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    sp<DataSource> temp_source;
8348dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    if (source == NULL) {
8358dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        source = &temp_source;
8368dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    }
837a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
8388dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    if (*source == NULL) {
8398dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        if (!strncasecmp(url, "file://", 7)) {
8408dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            *source = new FileSource(url + 7);
8418dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        } else if (strncasecmp(url, "http://", 7)
8428dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                && strncasecmp(url, "https://", 8)) {
8438dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            return ERROR_UNSUPPORTED;
8448dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        } else {
8458dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            KeyedVector<String8, String8> headers = mExtraHeaders;
8468dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            if (range_offset > 0 || range_length >= 0) {
8478dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                headers.add(
8488dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                        String8("Range"),
8498dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                        String8(
8508dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                            StringPrintf(
8518dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                                "bytes=%lld-%s",
8528dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                                range_offset,
8538dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                                range_length < 0
8548dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                                    ? "" : StringPrintf("%lld",
8558dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                                            range_offset + range_length - 1).c_str()).c_str()));
8568dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            }
8578dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            status_t err = mHTTPDataSource->connect(url, &headers);
858a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
8598dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            if (err != OK) {
8608dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                return err;
8618dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            }
862a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
8638dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            *source = mHTTPDataSource;
864a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
865a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
866a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
8678dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    status_t getSizeErr = (*source)->getSize(&size);
8688dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    if (getSizeErr != OK) {
869a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        size = 65536;
870a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
871a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
8728dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    sp<ABuffer> buffer = *out != NULL ? *out : new ABuffer(size);
8738dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    if (*out == NULL) {
8748dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        buffer->setRange(0, 0);
8758dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    }
876a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
87743ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih    ssize_t bytesRead = 0;
8788dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    // adjust range_length if only reading partial block
879b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross    if (block_size > 0 && (range_length == -1 || (int64_t)(buffer->size() + block_size) < range_length)) {
8808dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        range_length = buffer->size() + block_size;
8818dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    }
882a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    for (;;) {
8838dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        // Only resize when we don't know the size.
884a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        size_t bufferRemaining = buffer->capacity() - buffer->size();
8858dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        if (bufferRemaining == 0 && getSizeErr != OK) {
8869aff25fb41f516ac26f9d1983a25402909f1e77aLeena Winterrowd            size_t bufferIncrement = buffer->size() / 2;
8879aff25fb41f516ac26f9d1983a25402909f1e77aLeena Winterrowd            if (bufferIncrement < 32768) {
8889aff25fb41f516ac26f9d1983a25402909f1e77aLeena Winterrowd                bufferIncrement = 32768;
8899aff25fb41f516ac26f9d1983a25402909f1e77aLeena Winterrowd            }
8909aff25fb41f516ac26f9d1983a25402909f1e77aLeena Winterrowd            bufferRemaining = bufferIncrement;
891a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
892b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross            ALOGV("increasing download buffer to %zu bytes",
893a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                 buffer->size() + bufferRemaining);
894a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
895a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            sp<ABuffer> copy = new ABuffer(buffer->size() + bufferRemaining);
896a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            memcpy(copy->data(), buffer->data(), buffer->size());
897a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            copy->setRange(0, buffer->size());
898a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
899a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            buffer = copy;
900a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
901a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
9022aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        size_t maxBytesToRead = bufferRemaining;
9032aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        if (range_length >= 0) {
9042aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber            int64_t bytesLeftInRange = range_length - buffer->size();
905b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross            if (bytesLeftInRange < (int64_t)maxBytesToRead) {
9062aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                maxBytesToRead = bytesLeftInRange;
9072aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber
9082aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                if (bytesLeftInRange == 0) {
9092aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                    break;
9102aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                }
9112aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber            }
9122aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        }
9132aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber
9148dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        // The DataSource is responsible for informing us of error (n < 0) or eof (n == 0)
9158dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        // to help us break out of the loop.
9168dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        ssize_t n = (*source)->readAt(
917a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                buffer->size(), buffer->data() + buffer->size(),
9182aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                maxBytesToRead);
919a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
920a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (n < 0) {
92120ad3a341a96e7746015ccb7369fa567897e11f6Andreas Huber            return n;
922a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
923a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
924a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (n == 0) {
925a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
926a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
927a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
928a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        buffer->setRange(0, buffer->size() + (size_t)n);
92943ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih        bytesRead += n;
930a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
931a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
932a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    *out = buffer;
933784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo    if (actualUrl != NULL) {
93497194cdf8d67f362ef8c6dfdf607298c7e102b3bMarco Nelissen        *actualUrl = (*source)->getUri();
935784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo        if (actualUrl->isEmpty()) {
936784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo            *actualUrl = url;
937784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo        }
938784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo    }
939a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
94043ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih    return bytesRead;
941a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
942a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
94314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubersp<M3UParser> LiveSession::fetchPlaylist(
94414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        const char *url, uint8_t *curPlaylistHash, bool *unchanged) {
945b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber    ALOGV("fetchPlaylist '%s'", url);
946b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
9477e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    *unchanged = false;
9487e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
949a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<ABuffer> buffer;
950784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo    String8 actualUrl;
95143ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih    ssize_t  err = fetchFile(url, &buffer, 0, -1, 0, NULL, &actualUrl);
952a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
95343ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih    if (err <= 0) {
954a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return NULL;
955a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
956a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
9577e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    // MD5 functionality is not available on the simulator, treat all
9587e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    // playlists as changed.
9597e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
9607e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber#if defined(HAVE_ANDROID_OS)
9617e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    uint8_t hash[16];
9627e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
9637e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    MD5_CTX m;
9647e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    MD5_Init(&m);
9657e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    MD5_Update(&m, buffer->data(), buffer->size());
9667e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
9677e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    MD5_Final(hash, &m);
9687e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
96914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (curPlaylistHash != NULL && !memcmp(hash, curPlaylistHash, 16)) {
9707e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        // playlist unchanged
9717e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        *unchanged = true;
9727e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
9737e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        return NULL;
9747e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    }
9757e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
97614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (curPlaylistHash != NULL) {
97714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        memcpy(curPlaylistHash, hash, sizeof(hash));
97814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
9797e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber#endif
9807e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
981a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<M3UParser> playlist =
982784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo        new M3UParser(actualUrl.string(), buffer->data(), buffer->size());
983a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
984a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (playlist->initCheck() != OK) {
98529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("failed to parse .m3u8 playlist");
9869067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber
987a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return NULL;
988a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
989a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
990a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return playlist;
991a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
992a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
993a44153c1a57202fb538659eb50706e60454d6273Andreas Huberstatic double uniformRand() {
994a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return (double)rand() / RAND_MAX;
995a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
996a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
997a44153c1a57202fb538659eb50706e60454d6273Andreas Hubersize_t LiveSession::getBandwidthIndex() {
998a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (mBandwidthItems.size() == 0) {
999a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return 0;
1000a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1001a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1002a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#if 1
1003a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    char value[PROPERTY_VALUE_MAX];
1004673158582c9589cee1d5e4d7c79622609938b8f8Andreas Huber    ssize_t index = -1;
100514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (property_get("media.httplive.bw-index", value, NULL)) {
1006a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        char *end;
100714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        index = strtol(value, &end, 10);
100814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        CHECK(end > value && *end == '\0');
100914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
101014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (index >= 0 && (size_t)index >= mBandwidthItems.size()) {
101114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            index = mBandwidthItems.size() - 1;
1012a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
1013a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1014a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
101514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (index < 0) {
101614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        int32_t bandwidthBps;
101714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (mHTTPDataSource != NULL
101814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                && mHTTPDataSource->estimateBandwidth(&bandwidthBps)) {
101914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            ALOGV("bandwidth estimated at %.2f kbps", bandwidthBps / 1024.0f);
102014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        } else {
102114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            ALOGV("no bandwidth estimate.");
102214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            return 0;  // Pick the lowest bandwidth stream by default.
102314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
1024a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
102514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        char value[PROPERTY_VALUE_MAX];
102614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (property_get("media.httplive.max-bw", value, NULL)) {
102714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            char *end;
102814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            long maxBw = strtoul(value, &end, 10);
102914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            if (end > value && *end == '\0') {
103014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                if (maxBw > 0 && bandwidthBps > maxBw) {
103114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    ALOGV("bandwidth capped to %ld bps", maxBw);
103214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    bandwidthBps = maxBw;
103314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                }
103414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            }
103514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
1036a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
103714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        // Pick the highest bandwidth stream below or equal to estimated bandwidth.
103814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
103914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        index = mBandwidthItems.size() - 1;
104000598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih        while (index > 0) {
104100598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih            // consider only 80% of the available bandwidth, but if we are switching up,
104200598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih            // be even more conservative (70%) to avoid overestimating and immediately
104300598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih            // switching back.
104400598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih            size_t adjustedBandwidthBps = bandwidthBps;
104500598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih            if (index > mCurBandwidthIndex) {
104600598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih                adjustedBandwidthBps = adjustedBandwidthBps * 7 / 10;
104700598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih            } else {
104800598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih                adjustedBandwidthBps = adjustedBandwidthBps * 8 / 10;
104900598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih            }
105000598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih            if (mBandwidthItems.itemAt(index).mBandwidth <= adjustedBandwidthBps) {
105100598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih                break;
105200598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih            }
105314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            --index;
105414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
1055a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1056a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0
1057a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // Change bandwidth at random()
1058a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index = uniformRand() * mBandwidthItems.size();
1059a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0
1060a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // There's a 50% chance to stay on the current bandwidth and
1061a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // a 50% chance to switch to the next higher bandwidth (wrapping around
1062a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // to lowest)
1063a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    const size_t kMinIndex = 0;
1064a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1065309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    static ssize_t mCurBandwidthIndex = -1;
106614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
1067a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index;
1068309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    if (mCurBandwidthIndex < 0) {
1069a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        index = kMinIndex;
1070a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else if (uniformRand() < 0.5) {
1071309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        index = (size_t)mCurBandwidthIndex;
1072a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else {
1073309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        index = mCurBandwidthIndex + 1;
1074a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (index == mBandwidthItems.size()) {
1075a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            index = kMinIndex;
1076a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
1077a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1078309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    mCurBandwidthIndex = index;
1079a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0
1080a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // Pick the highest bandwidth stream below or equal to 1.2 Mbit/sec
1081a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1082a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index = mBandwidthItems.size() - 1;
1083a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    while (index > 0 && mBandwidthItems.itemAt(index).mBandwidth > 1200000) {
1084a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        --index;
1085a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
108614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#elif 1
108714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    char value[PROPERTY_VALUE_MAX];
108814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    size_t index;
108914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (property_get("media.httplive.bw-index", value, NULL)) {
109014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        char *end;
109114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        index = strtoul(value, &end, 10);
109214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        CHECK(end > value && *end == '\0');
109314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
109414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (index >= mBandwidthItems.size()) {
109514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            index = mBandwidthItems.size() - 1;
109614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
109714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    } else {
109814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        index = 0;
109914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
1100a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#else
1101a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index = mBandwidthItems.size() - 1;  // Highest bandwidth stream
1102a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#endif
1103a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
110414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK_GE(index, 0);
110514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
1106a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return index;
1107a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
1108a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1109b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shihint64_t LiveSession::latestMediaSegmentStartTimeUs() {
1110b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    sp<AMessage> audioMeta = mPacketSources.valueFor(STREAMTYPE_AUDIO)->getLatestDequeuedMeta();
1111b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    int64_t minSegmentStartTimeUs = -1, videoSegmentStartTimeUs = -1;
1112b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    if (audioMeta != NULL) {
1113b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih        audioMeta->findInt64("segmentStartTimeUs", &minSegmentStartTimeUs);
1114b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    }
1115b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih
1116b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    sp<AMessage> videoMeta = mPacketSources.valueFor(STREAMTYPE_VIDEO)->getLatestDequeuedMeta();
1117b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    if (videoMeta != NULL
1118b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih            && videoMeta->findInt64("segmentStartTimeUs", &videoSegmentStartTimeUs)) {
1119b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih        if (minSegmentStartTimeUs < 0 || videoSegmentStartTimeUs < minSegmentStartTimeUs) {
1120b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih            minSegmentStartTimeUs = videoSegmentStartTimeUs;
1121b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih        }
1122b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih
1123b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    }
1124b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    return minSegmentStartTimeUs;
1125b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih}
1126b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih
112714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::onSeek(const sp<AMessage> &msg) {
112814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    int64_t timeUs;
112914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(msg->findInt64("timeUs", &timeUs));
11307e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
113114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (!mReconfigurationInProgress) {
1132800599cdd50737de1cde483a34b39923750b0658Robert Shih        changeConfiguration(timeUs, mCurBandwidthIndex);
1133800599cdd50737de1cde483a34b39923750b0658Robert Shih        return OK;
1134800599cdd50737de1cde483a34b39923750b0658Robert Shih    } else {
1135800599cdd50737de1cde483a34b39923750b0658Robert Shih        return -EWOULDBLOCK;
11367e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    }
11377e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber}
11387e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
113914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::getDuration(int64_t *durationUs) const {
1140895651b07fec30b0f9b0d2499599a179d95c9be4Wei Jia    int64_t maxDurationUs = -1ll;
114114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
114214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        int64_t fetcherDurationUs = mFetcherInfos.valueAt(i).mDurationUs;
1143b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
1144895651b07fec30b0f9b0d2499599a179d95c9be4Wei Jia        if (fetcherDurationUs > maxDurationUs) {
114514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            maxDurationUs = fetcherDurationUs;
1146a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
1147a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1148a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
114914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    *durationUs = maxDurationUs;
1150a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
115114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return OK;
115214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
11530f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber
115414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberbool LiveSession::isSeekable() const {
115514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    int64_t durationUs;
115614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return getDuration(&durationUs) == OK && durationUs >= 0;
115714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
11580f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber
115914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberbool LiveSession::hasDynamicDuration() const {
116014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return false;
116114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
11620f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber
1163404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhangsize_t LiveSession::getTrackCount() const {
11649d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih    if (mPlaylist == NULL) {
11659d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih        return 0;
11669d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih    } else {
11679d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih        return mPlaylist->getTrackCount();
11689d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih    }
1169404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang}
1170404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang
1171404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhangsp<AMessage> LiveSession::getTrackInfo(size_t trackIndex) const {
11729d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih    if (mPlaylist == NULL) {
11739d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih        return NULL;
11749d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih    } else {
11759d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih        return mPlaylist->getTrackInfo(trackIndex);
11769d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih    }
1177dcb89b3b505522efde173c105a851c412f947178Chong Zhang}
1178dcb89b3b505522efde173c105a851c412f947178Chong Zhang
1179dcb89b3b505522efde173c105a851c412f947178Chong Zhangstatus_t LiveSession::selectTrack(size_t index, bool select) {
1180b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    if (mPlaylist == NULL) {
1181b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih        return INVALID_OPERATION;
1182b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    }
1183b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih
1184b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    ++mSubtitleGeneration;
1185dcb89b3b505522efde173c105a851c412f947178Chong Zhang    status_t err = mPlaylist->selectTrack(index, select);
1186dcb89b3b505522efde173c105a851c412f947178Chong Zhang    if (err == OK) {
1187309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        sp<AMessage> msg = new AMessage(kWhatChangeConfiguration, id());
1188309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        msg->setInt32("bandwidthIndex", mCurBandwidthIndex);
1189309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        msg->setInt32("pickTrack", select);
1190309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        msg->post();
1191dcb89b3b505522efde173c105a851c412f947178Chong Zhang    }
1192dcb89b3b505522efde173c105a851c412f947178Chong Zhang    return err;
1193dcb89b3b505522efde173c105a851c412f947178Chong Zhang}
1194dcb89b3b505522efde173c105a851c412f947178Chong Zhang
119589bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shihssize_t LiveSession::getSelectedTrack(media_track_type type) const {
119689bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih    if (mPlaylist == NULL) {
119789bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih        return -1;
119889bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih    } else {
119989bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih        return mPlaylist->getSelectedTrack(type);
120089bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih    }
120189bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih}
120289bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih
12031543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shihbool LiveSession::canSwitchUp() {
12041543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // Allow upwards bandwidth switch when a stream has buffered at least 10 seconds.
12051543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    status_t err = OK;
12061543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    for (size_t i = 0; i < mPacketSources.size(); ++i) {
12071543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        sp<AnotherPacketSource> source = mPacketSources.valueAt(i);
12081543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        int64_t dur = source->getBufferedDurationUs(&err);
12091543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        if (err == OK && dur > 10000000) {
12101543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            return true;
12111543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        }
12121543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
12131543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    return false;
12141543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
12151543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
1216dcb89b3b505522efde173c105a851c412f947178Chong Zhangvoid LiveSession::changeConfiguration(
1217dcb89b3b505522efde173c105a851c412f947178Chong Zhang        int64_t timeUs, size_t bandwidthIndex, bool pickTrack) {
12181543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // Protect mPacketSources from a swapPacketSource race condition through reconfiguration.
12191543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // (changeConfiguration, onChangeConfiguration2, onChangeConfiguration3).
12201543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    cancelBandwidthSwitch();
12211543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
122214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(!mReconfigurationInProgress);
122314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mReconfigurationInProgress = true;
1224a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1225309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    mCurBandwidthIndex = bandwidthIndex;
122643c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
1227b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross    ALOGV("changeConfiguration => timeUs:%" PRId64 " us, bwIndex:%zu, pickTrack:%d",
1228dcb89b3b505522efde173c105a851c412f947178Chong Zhang          timeUs, bandwidthIndex, pickTrack);
122943c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
123014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK_LT(bandwidthIndex, mBandwidthItems.size());
123114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    const BandwidthItem &item = mBandwidthItems.itemAt(bandwidthIndex);
1232a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
12331543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    uint32_t streamMask = 0; // streams that should be fetched by the new fetcher
12341543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    uint32_t resumeMask = 0; // streams that should be fetched by the original fetcher
1235a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
12368ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    AString URIs[kMaxStreams];
12378ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
12388ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        if (mPlaylist->getTypeURI(item.mPlaylistIndex, mStreams[i].mType, &URIs[i])) {
12398ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            streamMask |= indexToType(i);
12408ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        }
124114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
1242aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber
124314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Step 1, stop and discard fetchers that are no longer needed.
124414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Pause those that we'll reuse.
124514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
124614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        const AString &uri = mFetcherInfos.keyAt(i);
1247aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber
124814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        bool discardFetcher = true;
1249aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber
125014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        // If we're seeking all current fetchers are discarded.
125114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (timeUs < 0ll) {
1252309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            // delay fetcher removal if not picking tracks
1253309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            discardFetcher = pickTrack;
12541543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
12558ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            for (size_t j = 0; j < kMaxStreams; ++j) {
12561543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                StreamType type = indexToType(j);
12571543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                if ((streamMask & type) && uri == URIs[j]) {
12581543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    resumeMask |= type;
12591543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    streamMask &= ~type;
1260309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    discardFetcher = false;
12618ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                }
12626801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber            }
126314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
1264a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
126514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (discardFetcher) {
126614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            mFetcherInfos.valueAt(i).mFetcher->stopAsync();
12676801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber        } else {
126814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            mFetcherInfos.valueAt(i).mFetcher->pauseAsync();
12696801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber        }
1270a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1271a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
12721543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    sp<AMessage> msg;
12731543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    if (timeUs < 0ll) {
1274309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        // skip onChangeConfiguration2 (decoder destruction) if not seeking.
12751543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        msg = new AMessage(kWhatChangeConfiguration3, id());
12761543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    } else {
12771543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        msg = new AMessage(kWhatChangeConfiguration2, id());
12781543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
127914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    msg->setInt32("streamMask", streamMask);
12801543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    msg->setInt32("resumeMask", resumeMask);
1281309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    msg->setInt32("pickTrack", pickTrack);
128214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    msg->setInt64("timeUs", timeUs);
12838ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
1284309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        if ((streamMask | resumeMask) & indexToType(i)) {
12858ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            msg->setString(mStreams[i].uriKey().c_str(), URIs[i].c_str());
12868ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        }
12876e6b1cae2bac1b78205cefab8e4e9e9538982965Andreas Huber    }
1288a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
128914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Every time a fetcher acknowledges the stopAsync or pauseAsync request
129014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // we'll decrement mContinuationCounter, once it reaches zero, i.e. all
129114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // fetchers have completed their asynchronous operation, we'll post
129214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // mContinuation, which then is handled below in onChangeConfiguration2.
129314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mContinuationCounter = mFetcherInfos.size();
129414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mContinuation = msg;
129588b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber
129614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (mContinuationCounter == 0) {
129714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        msg->post();
12985ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih
12995ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih        if (mSeekReplyID != 0) {
13005ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih            CHECK(mSeekReply != NULL);
1301800599cdd50737de1cde483a34b39923750b0658Robert Shih            mSeekReply->setInt32("err", OK);
13025ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih            mSeekReply->postReply(mSeekReplyID);
1303800599cdd50737de1cde483a34b39923750b0658Robert Shih            mSeekReplyID = 0;
1304800599cdd50737de1cde483a34b39923750b0658Robert Shih            mSeekReply.clear();
13055ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih        }
130688b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber    }
130714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
1308a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1309dcb89b3b505522efde173c105a851c412f947178Chong Zhangvoid LiveSession::onChangeConfiguration(const sp<AMessage> &msg) {
1310dcb89b3b505522efde173c105a851c412f947178Chong Zhang    if (!mReconfigurationInProgress) {
1311309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        int32_t pickTrack = 0, bandwidthIndex = mCurBandwidthIndex;
1312309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        msg->findInt32("pickTrack", &pickTrack);
1313309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        msg->findInt32("bandwidthIndex", &bandwidthIndex);
1314309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        changeConfiguration(-1ll /* timeUs */, bandwidthIndex, pickTrack);
1315dcb89b3b505522efde173c105a851c412f947178Chong Zhang    } else {
1316dcb89b3b505522efde173c105a851c412f947178Chong Zhang        msg->post(1000000ll); // retry in 1 sec
1317dcb89b3b505522efde173c105a851c412f947178Chong Zhang    }
1318dcb89b3b505522efde173c105a851c412f947178Chong Zhang}
1319dcb89b3b505522efde173c105a851c412f947178Chong Zhang
132014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::onChangeConfiguration2(const sp<AMessage> &msg) {
132114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mContinuation.clear();
1322bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
132314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // All fetchers are either suspended or have been removed now.
1324bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
1325309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    uint32_t streamMask, resumeMask;
132614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(msg->findInt32("streamMask", (int32_t *)&streamMask));
1327309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    CHECK(msg->findInt32("resumeMask", (int32_t *)&resumeMask));
1328309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
1329309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    // currently onChangeConfiguration2 is only called for seeking;
1330309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    // remove the following CHECK if using it else where.
1331309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    CHECK_EQ(resumeMask, 0);
1332309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    streamMask |= resumeMask;
1333bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
13348ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    AString URIs[kMaxStreams];
13358ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
13368ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        if (streamMask & indexToType(i)) {
13378ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            const AString &uriKey = mStreams[i].uriKey();
13388ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            CHECK(msg->findString(uriKey.c_str(), &URIs[i]));
13398ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            ALOGV("%s = '%s'", uriKey.c_str(), URIs[i].c_str());
13408ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        }
134122fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber    }
13423831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber
134314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Determine which decoders to shutdown on the player side,
134414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // a decoder has to be shutdown if either
134514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // 1) its streamtype was active before but now longer isn't.
134614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // or
134714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // 2) its streamtype was already active and still is but the URI
134814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    //    has changed.
134914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    uint32_t changedMask = 0;
13508ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams && i != kSubtitleIndex; ++i) {
13518ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        if (((mStreamMask & streamMask & indexToType(i))
13528ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                && !(URIs[i] == mStreams[i].mUri))
13538ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                || (mStreamMask & ~streamMask & indexToType(i))) {
13548ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            changedMask |= indexToType(i);
13558ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        }
1356b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber    }
1357b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
135814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (changedMask == 0) {
135914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        // If nothing changed as far as the audio/video decoders
136014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        // are concerned we can proceed.
136114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        onChangeConfiguration3(msg);
136214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        return;
136314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
136443c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
136514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Something changed, inform the player which will shutdown the
136614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // corresponding decoders and will post the reply once that's done.
136714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Handling the reply will continue executing below in
136814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // onChangeConfiguration3.
136914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> notify = mNotify->dup();
137014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->setInt32("what", kWhatStreamsChanged);
137114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->setInt32("changedMask", changedMask);
137220f725ebcef13ded1b4b85c61c8a4b37cd030656Andreas Huber
137314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    msg->setWhat(kWhatChangeConfiguration3);
137414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    msg->setTarget(id());
1375b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
137614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->setMessage("reply", msg);
137714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->post();
137814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
1379b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
138014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::onChangeConfiguration3(const sp<AMessage> &msg) {
13811543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    mContinuation.clear();
138214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // All remaining fetchers are still suspended, the player has shutdown
138314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // any decoders that needed it.
1384b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
13851543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    uint32_t streamMask, resumeMask;
138614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(msg->findInt32("streamMask", (int32_t *)&streamMask));
13871543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    CHECK(msg->findInt32("resumeMask", (int32_t *)&resumeMask));
1388a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
138914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    int64_t timeUs;
1390309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    int32_t pickTrack;
13911543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    bool switching = false;
139214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(msg->findInt64("timeUs", &timeUs));
1393309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    CHECK(msg->findInt32("pickTrack", &pickTrack));
1394a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
139514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (timeUs < 0ll) {
1396309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        if (!pickTrack) {
1397309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            switching = true;
1398309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        }
1399309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        mRealTimeBaseUs = ALooper::GetNowUs() - mLastDequeuedTimeUs;
1400309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    } else {
1401309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        mRealTimeBaseUs = ALooper::GetNowUs() - timeUs;
140214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
1403a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1404f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
1405f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        if (streamMask & indexToType(i)) {
1406f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            if (switching) {
1407f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih                CHECK(msg->findString(mStreams[i].uriKey().c_str(), &mStreams[i].mNewUri));
1408f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            } else {
1409f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih                CHECK(msg->findString(mStreams[i].uriKey().c_str(), &mStreams[i].mUri));
1410f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            }
1411f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        }
1412f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    }
1413f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih
1414309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    mNewStreamMask = streamMask | resumeMask;
1415f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    if (switching) {
1416f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        mSwapMask = mStreamMask & ~resumeMask;
1417f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    }
1418a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
14191543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // Of all existing fetchers:
14201543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // * Resume fetchers that are still needed and assign them original packet sources.
14211543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // * Mark otherwise unneeded fetchers for removal.
14221543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    ALOGV("resuming fetchers for mask 0x%08x", resumeMask);
142314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
142414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        const AString &uri = mFetcherInfos.keyAt(i);
14250df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas Huber
14268ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        sp<AnotherPacketSource> sources[kMaxStreams];
1427dc793ce8c0ead27ab43e40ce09f27fe338323502Robert Shih        for (size_t j = 0; j < kMaxStreams; ++j) {
14281543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            if ((resumeMask & indexToType(j)) && uri == mStreams[j].mUri) {
14298ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                sources[j] = mPacketSources.valueFor(indexToType(j));
1430309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
1431309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                if (j != kSubtitleIndex) {
1432309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    ALOGV("queueing dummy discontinuity for stream type %d", indexToType(j));
1433309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    sp<AnotherPacketSource> discontinuityQueue;
1434309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    discontinuityQueue = mDiscontinuities.valueFor(indexToType(j));
1435309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    discontinuityQueue->queueDiscontinuity(
1436309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                            ATSParser::DISCONTINUITY_NONE,
1437309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                            NULL,
1438309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                            true);
1439309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                }
14408ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            }
144114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
1442a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
14431543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        FetcherInfo &info = mFetcherInfos.editValueAt(i);
14441543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        if (sources[kAudioIndex] != NULL || sources[kVideoIndex] != NULL
14451543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                || sources[kSubtitleIndex] != NULL) {
14461543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            info.mFetcher->startAsync(
14471543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    sources[kAudioIndex], sources[kVideoIndex], sources[kSubtitleIndex]);
14481543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        } else {
14491543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            info.mToBeRemoved = true;
14501543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        }
1451a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1452a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
145314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // streamMask now only contains the types that need a new fetcher created.
1454a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
145514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (streamMask != 0) {
145614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        ALOGV("creating new fetchers for mask 0x%08x", streamMask);
1457a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1458a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
14591543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // Find out when the original fetchers have buffered up to and start the new fetchers
14601543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // at a later timestamp.
14618ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams; i++) {
14628ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        if (!(indexToType(i) & streamMask)) {
14638ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            continue;
14648ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        }
14651156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
146614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        AString uri;
1467f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        uri = switching ? mStreams[i].mNewUri : mStreams[i].mUri;
14689b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber
146914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        sp<PlaylistFetcher> fetcher = addFetcher(uri.c_str());
147014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        CHECK(fetcher != NULL);
1471a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
14721543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        int32_t latestSeq = -1;
1473309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        int64_t startTimeUs = -1;
1474309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        int64_t segmentStartTimeUs = -1ll;
1475309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        int32_t discontinuitySeq = -1;
14768ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        sp<AnotherPacketSource> sources[kMaxStreams];
14771543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
1478b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih        if (i == kSubtitleIndex) {
1479b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih            segmentStartTimeUs = latestMediaSegmentStartTimeUs();
1480b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih        }
1481b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih
14828ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        // TRICKY: looping from i as earlier streams are already removed from streamMask
14838ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        for (size_t j = i; j < kMaxStreams; ++j) {
1484f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            const AString &streamUri = switching ? mStreams[j].mNewUri : mStreams[j].mUri;
1485f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            if ((streamMask & indexToType(j)) && uri == streamUri) {
14868ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                sources[j] = mPacketSources.valueFor(indexToType(j));
14871543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
1488309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                if (timeUs >= 0) {
14891543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    sources[j]->clear();
1490309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    startTimeUs = timeUs;
1491309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
1492309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    sp<AnotherPacketSource> discontinuityQueue;
1493309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    sp<AMessage> extra = new AMessage;
1494309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    extra->setInt64("timeUs", timeUs);
1495309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    discontinuityQueue = mDiscontinuities.valueFor(indexToType(j));
1496309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    discontinuityQueue->queueDiscontinuity(
1497fef808d42a9c94b0b5ef3c3d5fb0a090edbc42daWei Jia                            ATSParser::DISCONTINUITY_TIME, extra, true);
14981543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                } else {
1499309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    int32_t type;
1500309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    int64_t srcSegmentStartTimeUs;
1501309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    sp<AMessage> meta;
1502309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    if (pickTrack) {
1503309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        // selecting
1504309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        meta = sources[j]->getLatestDequeuedMeta();
1505309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    } else {
1506309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        // adapting
1507309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        meta = sources[j]->getLatestEnqueuedMeta();
1508309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    }
15091543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
15101543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    if (meta != NULL && !meta->findInt32("discontinuity", &type)) {
1511309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        int64_t tmpUs;
1512309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        CHECK(meta->findInt64("timeUs", &tmpUs));
1513309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        if (startTimeUs < 0 || tmpUs < startTimeUs) {
1514309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                            startTimeUs = tmpUs;
1515309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        }
1516309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
1517309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        CHECK(meta->findInt64("segmentStartTimeUs", &tmpUs));
1518309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        if (segmentStartTimeUs < 0 || tmpUs < segmentStartTimeUs) {
1519309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                            segmentStartTimeUs = tmpUs;
15201543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        }
1521309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
1522309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        int32_t seq;
1523309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        CHECK(meta->findInt32("discontinuitySeq", &seq));
1524309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        if (discontinuitySeq < 0 || seq < discontinuitySeq) {
1525309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                            discontinuitySeq = seq;
15261543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        }
15271543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    }
15281543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
1529309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    if (pickTrack) {
1530309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        // selecting track, queue discontinuities before content
1531309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        sources[j]->clear();
1532309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        if (j == kSubtitleIndex) {
1533309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                            break;
1534309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        }
1535309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        sp<AnotherPacketSource> discontinuityQueue;
1536309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        discontinuityQueue = mDiscontinuities.valueFor(indexToType(j));
1537309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        discontinuityQueue->queueDiscontinuity(
1538309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                                ATSParser::DISCONTINUITY_FORMATCHANGE, NULL, true);
1539309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    } else {
1540309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        // adapting, queue discontinuities after resume
1541309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        sources[j] = mPacketSources2.valueFor(indexToType(j));
1542309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        sources[j]->clear();
1543309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        uint32_t extraStreams = mNewStreamMask & (~mStreamMask);
1544309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        if (extraStreams & indexToType(j)) {
1545309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                            sources[j]->queueAccessUnit(createFormatChangeBuffer(/*swap*/ false));
1546309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        }
15471543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    }
15481543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                }
1549a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
15508ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                streamMask &= ~indexToType(j);
15518ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            }
1552a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
155314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
15548ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        fetcher->startAsync(
15558ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                sources[kAudioIndex],
15568ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                sources[kVideoIndex],
15578ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                sources[kSubtitleIndex],
1558309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                startTimeUs < 0 ? mLastSeekTimeUs : startTimeUs,
1559309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                segmentStartTimeUs,
1560309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                discontinuitySeq,
1561309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                switching);
1562a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1563a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
156414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // All fetchers have now been started, the configuration change
156514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // has completed.
1566a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
156700598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih    cancelCheckBandwidthEvent();
156814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    scheduleCheckBandwidthEvent();
1569a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
157014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    ALOGV("XXX configuration change completed.");
157114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mReconfigurationInProgress = false;
15721543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    if (switching) {
15731543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        mSwitchInProgress = true;
15741543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    } else {
15751543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        mStreamMask = mNewStreamMask;
15761543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
1577a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
157814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (mDisconnectReplyID != 0) {
157914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        finishDisconnect();
1580a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
158114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
1582a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
15831543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shihvoid LiveSession::onSwapped(const sp<AMessage> &msg) {
15841543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    int32_t switchGeneration;
15851543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    CHECK(msg->findInt32("switchGeneration", &switchGeneration));
15861543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    if (switchGeneration != mSwitchGeneration) {
15871543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return;
15881543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
15891543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
15901543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    int32_t stream;
15911543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    CHECK(msg->findInt32("stream", &stream));
1592f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih
1593f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    ssize_t idx = typeToIndex(stream);
1594f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    CHECK(idx >= 0);
1595f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    if ((mNewStreamMask & stream) && mStreams[idx].mNewUri.empty()) {
1596f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        ALOGW("swapping stream type %d %s to empty stream", stream, mStreams[idx].mUri.c_str());
1597f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    }
1598f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    mStreams[idx].mUri = mStreams[idx].mNewUri;
1599f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    mStreams[idx].mNewUri.clear();
1600f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih
1601309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    mSwapMask &= ~stream;
1602309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    if (mSwapMask != 0) {
16031543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return;
16041543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
16051543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
16061543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // Check if new variant contains extra streams.
16071543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    uint32_t extraStreams = mNewStreamMask & (~mStreamMask);
16081543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    while (extraStreams) {
16091543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        StreamType extraStream = (StreamType) (extraStreams & ~(extraStreams - 1));
16101543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        swapPacketSource(extraStream);
16111543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        extraStreams &= ~extraStream;
1612f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih
1613f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        idx = typeToIndex(extraStream);
1614f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        CHECK(idx >= 0);
1615f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        if (mStreams[idx].mNewUri.empty()) {
1616f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            ALOGW("swapping extra stream type %d %s to empty stream",
1617f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih                    extraStream, mStreams[idx].mUri.c_str());
1618f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        }
1619f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        mStreams[idx].mUri = mStreams[idx].mNewUri;
1620f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        mStreams[idx].mNewUri.clear();
16211543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
16221543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
16231543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    tryToFinishBandwidthSwitch();
16241543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
16251543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
16260ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shihvoid LiveSession::onCheckSwitchDown() {
16270ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    if (mSwitchDownMonitor == NULL) {
16280ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        return;
16290ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    }
16300ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
1631678bcdc852dd8f801f5c46fdc85db587b721d83dApurupa Pattapu    if (mSwitchInProgress || mReconfigurationInProgress) {
1632678bcdc852dd8f801f5c46fdc85db587b721d83dApurupa Pattapu        ALOGV("Switch/Reconfig in progress, defer switch down");
1633678bcdc852dd8f801f5c46fdc85db587b721d83dApurupa Pattapu        mSwitchDownMonitor->post(1000000ll);
1634678bcdc852dd8f801f5c46fdc85db587b721d83dApurupa Pattapu        return;
1635678bcdc852dd8f801f5c46fdc85db587b721d83dApurupa Pattapu    }
1636678bcdc852dd8f801f5c46fdc85db587b721d83dApurupa Pattapu
16370ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
16380ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        int32_t targetDuration;
16390ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        sp<AnotherPacketSource> packetSource = mPacketSources.valueFor(indexToType(i));
16400ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        sp<AMessage> meta = packetSource->getLatestDequeuedMeta();
16410ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
16420ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        if (meta != NULL && meta->findInt32("targetDuration", &targetDuration) ) {
16430ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih            int64_t bufferedDurationUs = packetSource->getEstimatedDurationUs();
16440ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih            int64_t targetDurationUs = targetDuration * 1000000ll;
16450ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
16460ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih            if (bufferedDurationUs < targetDurationUs / 3) {
16470ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih                (new AMessage(kWhatSwitchDown, id()))->post();
16480ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih                break;
16490ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih            }
16500ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        }
16510ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    }
16520ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
16530ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    mSwitchDownMonitor->post(1000000ll);
16540ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih}
16550ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
16560ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shihvoid LiveSession::onSwitchDown() {
16570ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    if (mReconfigurationInProgress || mSwitchInProgress || mCurBandwidthIndex == 0) {
16580ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        return;
16590ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    }
16600ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
16610ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    ssize_t bandwidthIndex = getBandwidthIndex();
16620ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    if (bandwidthIndex < mCurBandwidthIndex) {
16630ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        changeConfiguration(-1, bandwidthIndex, false);
16640ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        return;
16650ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    }
16660ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
16670ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih}
16680ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
16691543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih// Mark switch done when:
1670309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih//   1. all old buffers are swapped out
16711543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shihvoid LiveSession::tryToFinishBandwidthSwitch() {
1672309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    if (!mSwitchInProgress) {
1673309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        return;
1674309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    }
1675309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
16761543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    bool needToRemoveFetchers = false;
16771543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
16781543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        if (mFetcherInfos.valueAt(i).mToBeRemoved) {
16791543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            needToRemoveFetchers = true;
16801543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            break;
16811543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        }
16821543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
1683309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
1684309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    if (!needToRemoveFetchers && mSwapMask == 0) {
1685309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        ALOGI("mSwitchInProgress = false");
16861543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        mStreamMask = mNewStreamMask;
16871543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        mSwitchInProgress = false;
16881543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
16891543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
16901543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
169114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::scheduleCheckBandwidthEvent() {
169214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> msg = new AMessage(kWhatCheckBandwidth, id());
169314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    msg->setInt32("generation", mCheckBandwidthGeneration);
169414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    msg->post(10000000ll);
1695a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
1696a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
169714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::cancelCheckBandwidthEvent() {
169814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    ++mCheckBandwidthGeneration;
1699a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
1700a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
17011543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shihvoid LiveSession::cancelBandwidthSwitch() {
17021543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    Mutex::Autolock lock(mSwapMutex);
17031543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    mSwitchGeneration++;
17041543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    mSwitchInProgress = false;
17051543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    mSwapMask = 0;
1706f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih
1707f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
1708f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        FetcherInfo& info = mFetcherInfos.editValueAt(i);
1709f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        if (info.mToBeRemoved) {
1710f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            info.mToBeRemoved = false;
1711f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        }
1712f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    }
1713f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih
1714f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
1715f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        if (!mStreams[i].mNewUri.empty()) {
1716f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            ssize_t j = mFetcherInfos.indexOfKey(mStreams[i].mNewUri);
1717f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            if (j < 0) {
1718f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih                mStreams[i].mNewUri.clear();
1719f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih                continue;
1720f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            }
1721f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih
1722f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            const FetcherInfo &info = mFetcherInfos.valueAt(j);
1723f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            info.mFetcher->stopAsync();
1724f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            mFetcherInfos.removeItemsAt(j);
1725f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            mStreams[i].mNewUri.clear();
1726f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        }
1727f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    }
17281543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
17291543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
17301543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shihbool LiveSession::canSwitchBandwidthTo(size_t bandwidthIndex) {
17311543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    if (mReconfigurationInProgress || mSwitchInProgress) {
17321543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return false;
17331543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
17341543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
1735309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    if (mCurBandwidthIndex < 0) {
17361543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return true;
173714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
173814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
1739309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    if (bandwidthIndex == (size_t)mCurBandwidthIndex) {
17401543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return false;
1741309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    } else if (bandwidthIndex > (size_t)mCurBandwidthIndex) {
17421543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return canSwitchUp();
17431543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    } else {
17441543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return true;
17451543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
17461543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
17471543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
174800598ec0b15426197494aaf9e5ec0bc88507c762Robert Shihvoid LiveSession::onCheckBandwidth(const sp<AMessage> &msg) {
174914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    size_t bandwidthIndex = getBandwidthIndex();
17501543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    if (canSwitchBandwidthTo(bandwidthIndex)) {
175114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        changeConfiguration(-1ll /* timeUs */, bandwidthIndex);
17521543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    } else {
175300598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih        // Come back and check again 10 seconds later in case there is nothing to do now.
175400598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih        // If we DO change configuration, once that completes it'll schedule a new
175500598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih        // check bandwidth event with an incremented mCheckBandwidthGeneration.
175600598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih        msg->post(10000000ll);
175714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
1758a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
1759a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
176014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::postPrepared(status_t err) {
176114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(mInPreparationPhase);
1762a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
176314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> notify = mNotify->dup();
176414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (err == OK || err == ERROR_END_OF_STREAM) {
176514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        notify->setInt32("what", kWhatPrepared);
176614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    } else {
176714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        notify->setInt32("what", kWhatPreparationFailed);
176814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        notify->setInt32("err", err);
176914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
1770a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
177114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->post();
1772a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
177314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mInPreparationPhase = false;
17740ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
17750ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    mSwitchDownMonitor = new AMessage(kWhatCheckSwitchDown, id());
17760ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    mSwitchDownMonitor->post();
1777b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber}
1778b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
1779a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}  // namespace android
1780a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1781