LiveSession.cpp revision 1543d3c735a5ba4ddfcf8ab644575df13c7e30a9
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>
46a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <openssl/aes.h>
477e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber#include <openssl/md5.h>
48a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
49a44153c1a57202fb538659eb50706e60454d6273Andreas Hubernamespace android {
50a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
510df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas HuberLiveSession::LiveSession(
521b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        const sp<AMessage> &notify, uint32_t flags,
5381e68448f3361eaf8618930471fdc3c21bdf5cbcAndreas Huber        const sp<IMediaHTTPService> &httpService)
540df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas Huber    : mNotify(notify),
550df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas Huber      mFlags(flags),
561b86fe063badb5f28c467ade39be0f4008688947Andreas Huber      mHTTPService(httpService),
570df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas Huber      mInPreparationPhase(true),
581b86fe063badb5f28c467ade39be0f4008688947Andreas Huber      mHTTPDataSource(new MediaHTTP(mHTTPService->makeHTTPConnection())),
59a44153c1a57202fb538659eb50706e60454d6273Andreas Huber      mPrevBandwidthIndex(-1),
6014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber      mStreamMask(0),
611543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih      mNewStreamMask(0),
621543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih      mSwapMask(0),
6314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber      mCheckBandwidthGeneration(0),
641543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih      mSwitchGeneration(0),
6514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber      mLastDequeuedTimeUs(0ll),
66dcb89b3b505522efde173c105a851c412f947178Chong Zhang      mRealTimeBaseUs(0ll),
6714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber      mReconfigurationInProgress(false),
681543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih      mSwitchInProgress(false),
6914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber      mDisconnectReplyID(0) {
7014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
718ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    mStreams[kAudioIndex] = StreamItem("audio");
728ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    mStreams[kVideoIndex] = StreamItem("video");
738ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    mStreams[kSubtitleIndex] = StreamItem("subtitle");
7414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
758ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
768ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        mPacketSources.add(indexToType(i), new AnotherPacketSource(NULL /* meta */));
771543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        mPacketSources2.add(indexToType(i), new AnotherPacketSource(NULL /* meta */));
788ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    }
79a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
80a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
81a44153c1a57202fb538659eb50706e60454d6273Andreas HuberLiveSession::~LiveSession() {
82a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
83a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
841543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shihsp<ABuffer> LiveSession::createFormatChangeBuffer(bool swap) {
851543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    ABuffer *discontinuity = new ABuffer(0);
861543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    discontinuity->meta()->setInt32("discontinuity", ATSParser::DISCONTINUITY_FORMATCHANGE);
871543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    discontinuity->meta()->setInt32("swapPacketSource", swap);
881543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    discontinuity->meta()->setInt32("switchGeneration", mSwitchGeneration);
891543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    discontinuity->meta()->setInt64("timeUs", -1);
901543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    return discontinuity;
911543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
921543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
931543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shihvoid LiveSession::swapPacketSource(StreamType stream) {
941543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    sp<AnotherPacketSource> &aps = mPacketSources.editValueFor(stream);
951543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    sp<AnotherPacketSource> &aps2 = mPacketSources2.editValueFor(stream);
961543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    sp<AnotherPacketSource> tmp = aps;
971543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    aps = aps2;
981543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    aps2 = tmp;
991543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    aps2->clear();
1001543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
1011543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
10214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::dequeueAccessUnit(
10314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        StreamType stream, sp<ABuffer> *accessUnit) {
10414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (!(mStreamMask & stream)) {
1051543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        // return -EWOULDBLOCK to avoid halting the decoder
1061543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        // when switching between audio/video and audio only.
1071543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return -EWOULDBLOCK;
10814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
10914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
11014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AnotherPacketSource> packetSource = mPacketSources.valueFor(stream);
11114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
11214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    status_t finalResult;
11314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (!packetSource->hasBufferAvailable(&finalResult)) {
11414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        return finalResult == OK ? -EAGAIN : finalResult;
11514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
11614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
11714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    status_t err = packetSource->dequeueAccessUnit(accessUnit);
11814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
11914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    const char *streamStr;
12014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    switch (stream) {
12114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case STREAMTYPE_AUDIO:
12214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            streamStr = "audio";
12314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            break;
12414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case STREAMTYPE_VIDEO:
12514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            streamStr = "video";
12614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            break;
12714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case STREAMTYPE_SUBTITLES:
12814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            streamStr = "subs";
12914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            break;
13014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        default:
13114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            TRESPASS();
13214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
13314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
13414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (err == INFO_DISCONTINUITY) {
13514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        int32_t type;
13614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        CHECK((*accessUnit)->meta()->findInt32("discontinuity", &type));
13714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
13814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        sp<AMessage> extra;
13914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (!(*accessUnit)->meta()->findMessage("extra", &extra)) {
14014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            extra.clear();
14114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
14214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
14314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        ALOGI("[%s] read discontinuity of type %d, extra = %s",
14414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber              streamStr,
14514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber              type,
14614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber              extra == NULL ? "NULL" : extra->debugString().c_str());
1471543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
1481543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        int32_t swap;
1491543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        if (type == ATSParser::DISCONTINUITY_FORMATCHANGE
1501543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                && (*accessUnit)->meta()->findInt32("swapPacketSource", &swap)
1511543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                && swap) {
1521543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
1531543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            int32_t switchGeneration;
1541543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            CHECK((*accessUnit)->meta()->findInt32("switchGeneration", &switchGeneration));
1551543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            {
1561543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                Mutex::Autolock lock(mSwapMutex);
1571543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                if (switchGeneration == mSwitchGeneration) {
1581543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    swapPacketSource(stream);
1591543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    sp<AMessage> msg = new AMessage(kWhatSwapped, id());
1601543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    msg->setInt32("stream", stream);
1611543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    msg->setInt32("switchGeneration", switchGeneration);
1621543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    msg->post();
1631543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                }
1641543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            }
1651543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        }
16614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    } else if (err == OK) {
167dcb89b3b505522efde173c105a851c412f947178Chong Zhang        if (stream == STREAMTYPE_AUDIO || stream == STREAMTYPE_VIDEO) {
168dcb89b3b505522efde173c105a851c412f947178Chong Zhang            int64_t timeUs;
169dcb89b3b505522efde173c105a851c412f947178Chong Zhang            CHECK((*accessUnit)->meta()->findInt64("timeUs",  &timeUs));
170dcb89b3b505522efde173c105a851c412f947178Chong Zhang            ALOGV("[%s] read buffer at time %lld us", streamStr, timeUs);
171dcb89b3b505522efde173c105a851c412f947178Chong Zhang
172dcb89b3b505522efde173c105a851c412f947178Chong Zhang            mLastDequeuedTimeUs = timeUs;
173dcb89b3b505522efde173c105a851c412f947178Chong Zhang            mRealTimeBaseUs = ALooper::GetNowUs() - timeUs;
174dcb89b3b505522efde173c105a851c412f947178Chong Zhang        } else if (stream == STREAMTYPE_SUBTITLES) {
175dcb89b3b505522efde173c105a851c412f947178Chong Zhang            (*accessUnit)->meta()->setInt32(
176dcb89b3b505522efde173c105a851c412f947178Chong Zhang                    "trackIndex", mPlaylist->getSelectedIndex());
177dcb89b3b505522efde173c105a851c412f947178Chong Zhang            (*accessUnit)->meta()->setInt64("baseUs", mRealTimeBaseUs);
178dcb89b3b505522efde173c105a851c412f947178Chong Zhang        }
17914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    } else {
18014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        ALOGI("[%s] encountered error %d", streamStr, err);
18114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
18214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
18314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return err;
18414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
18514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
18614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::getStreamFormat(StreamType stream, sp<AMessage> *format) {
1871543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // No swapPacketSource race condition; called from the same thread as dequeueAccessUnit.
18814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (!(mStreamMask & stream)) {
18914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        return UNKNOWN_ERROR;
19014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
19114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
19214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AnotherPacketSource> packetSource = mPacketSources.valueFor(stream);
19314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
19414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<MetaData> meta = packetSource->getFormat();
19514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
19614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (meta == NULL) {
19714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        return -EAGAIN;
19814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
19914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
20014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return convertMetaDataToMessage(meta, format);
201a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
202a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
20314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::connectAsync(
204ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        const char *url, const KeyedVector<String8, String8> *headers) {
205a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<AMessage> msg = new AMessage(kWhatConnect, id());
206a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    msg->setString("url", url);
207ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber
208ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    if (headers != NULL) {
209ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        msg->setPointer(
210ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber                "headers",
211ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber                new KeyedVector<String8, String8>(*headers));
212ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    }
213ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber
214a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    msg->post();
215a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
216a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
21714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::disconnect() {
21814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> msg = new AMessage(kWhatDisconnect, id());
219ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
22014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> response;
22114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    status_t err = msg->postAndAwaitResponse(&response);
222ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
22314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return err;
224a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
225a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
22614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::seekTo(int64_t timeUs) {
227a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<AMessage> msg = new AMessage(kWhatSeek, id());
228a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    msg->setInt64("timeUs", timeUs);
229a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
23014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> response;
23114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    status_t err = msg->postAndAwaitResponse(&response);
23214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
23314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return err;
234a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
235a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
236a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onMessageReceived(const sp<AMessage> &msg) {
237a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    switch (msg->what()) {
238a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        case kWhatConnect:
23914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
240a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            onConnect(msg);
241a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
24214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
243a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
244a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        case kWhatDisconnect:
24514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
24614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            CHECK(msg->senderAwaitsResponse(&mDisconnectReplyID));
24714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
24814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            if (mReconfigurationInProgress) {
24914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                break;
25014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            }
25114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
25214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            finishDisconnect();
253a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
25414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
255a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
25614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case kWhatSeek:
25714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
25814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            uint32_t replyID;
25914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            CHECK(msg->senderAwaitsResponse(&replyID));
26014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
26114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            status_t err = onSeek(msg);
26214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
26314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            sp<AMessage> response = new AMessage;
26414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            response->setInt32("err", err);
26514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
26614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            response->postReply(replyID);
26714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            break;
26814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
26914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
27014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case kWhatFetcherNotify:
27114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
27214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            int32_t what;
27314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            CHECK(msg->findInt32("what", &what));
27414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
27514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            switch (what) {
27614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                case PlaylistFetcher::kWhatStarted:
27714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    break;
27814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                case PlaylistFetcher::kWhatPaused:
27914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                case PlaylistFetcher::kWhatStopped:
28014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                {
28114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    if (what == PlaylistFetcher::kWhatStopped) {
28214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        AString uri;
28314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        CHECK(msg->findString("uri", &uri));
2841543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        if (mFetcherInfos.removeItem(uri) < 0) {
2851543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                            // ignore duplicated kWhatStopped messages.
2861543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                            break;
2871543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        }
2881543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
2891543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        tryToFinishBandwidthSwitch();
29014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    }
29114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
29214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    if (mContinuation != NULL) {
29314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        CHECK_GT(mContinuationCounter, 0);
29414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        if (--mContinuationCounter == 0) {
29514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                            mContinuation->post();
29614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        }
29714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    }
29814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    break;
29914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                }
30014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
30114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                case PlaylistFetcher::kWhatDurationUpdate:
30214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                {
30314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    AString uri;
30414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    CHECK(msg->findString("uri", &uri));
30514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
30614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    int64_t durationUs;
30714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    CHECK(msg->findInt64("durationUs", &durationUs));
30814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
30914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    FetcherInfo *info = &mFetcherInfos.editValueFor(uri);
31014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    info->mDurationUs = durationUs;
31114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    break;
31214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                }
31314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
31414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                case PlaylistFetcher::kWhatError:
31514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                {
31614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    status_t err;
31714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    CHECK(msg->findInt32("err", &err));
31814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
31914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    ALOGE("XXX Received error %d from PlaylistFetcher.", err);
32014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
32114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    if (mInPreparationPhase) {
32214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        postPrepared(err);
32314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    }
32414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
3251543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    cancelBandwidthSwitch();
3261543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
32714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    mPacketSources.valueFor(STREAMTYPE_AUDIO)->signalEOS(err);
32814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
32914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    mPacketSources.valueFor(STREAMTYPE_VIDEO)->signalEOS(err);
33014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
33114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    mPacketSources.valueFor(
33214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                            STREAMTYPE_SUBTITLES)->signalEOS(err);
33314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
33414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    sp<AMessage> notify = mNotify->dup();
33514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    notify->setInt32("what", kWhatError);
33614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    notify->setInt32("err", err);
33714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    notify->post();
33814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    break;
33914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                }
34014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
34114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                case PlaylistFetcher::kWhatTemporarilyDoneFetching:
34214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                {
34314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    AString uri;
34414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    CHECK(msg->findString("uri", &uri));
34514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
34614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    FetcherInfo *info = &mFetcherInfos.editValueFor(uri);
34714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    info->mIsPrepared = true;
34814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
34914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    if (mInPreparationPhase) {
35014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        bool allFetchersPrepared = true;
35114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
35214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                            if (!mFetcherInfos.valueAt(i).mIsPrepared) {
35314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                                allFetchersPrepared = false;
35414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                                break;
35514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                            }
35614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        }
35714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
35814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        if (allFetchersPrepared) {
35914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                            postPrepared(OK);
36014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        }
36114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    }
36214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    break;
36314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                }
36414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
3651543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                case PlaylistFetcher::kWhatStartedAt:
3661543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                {
3671543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    int32_t switchGeneration;
3681543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    CHECK(msg->findInt32("switchGeneration", &switchGeneration));
3691543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
3701543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    if (switchGeneration != mSwitchGeneration) {
3711543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        break;
3721543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    }
3731543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
3741543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    // Resume fetcher for the original variant; the resumed fetcher should
3751543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    // continue until the timestamps found in msg, which is stored by the
3761543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    // new fetcher to indicate where the new variant has started buffering.
3771543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    for (size_t i = 0; i < mFetcherInfos.size(); i++) {
3781543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        const FetcherInfo info = mFetcherInfos.valueAt(i);
3791543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        if (info.mToBeRemoved) {
3801543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                            info.mFetcher->resumeUntilAsync(msg);
3811543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        }
3821543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    }
3831543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    break;
3841543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                }
3851543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
38614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                default:
38714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    TRESPASS();
38814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            }
38914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
39014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            break;
39114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
39214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
39314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case kWhatCheckBandwidth:
394a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        {
395a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            int32_t generation;
396a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            CHECK(msg->findInt32("generation", &generation));
397a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
39814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            if (generation != mCheckBandwidthGeneration) {
399a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                break;
400a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            }
401a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
40214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            onCheckBandwidth();
403a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
404a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
405a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
406dcb89b3b505522efde173c105a851c412f947178Chong Zhang        case kWhatChangeConfiguration:
407dcb89b3b505522efde173c105a851c412f947178Chong Zhang        {
408dcb89b3b505522efde173c105a851c412f947178Chong Zhang            onChangeConfiguration(msg);
409dcb89b3b505522efde173c105a851c412f947178Chong Zhang            break;
410dcb89b3b505522efde173c105a851c412f947178Chong Zhang        }
411dcb89b3b505522efde173c105a851c412f947178Chong Zhang
41214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case kWhatChangeConfiguration2:
41314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
41414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            onChangeConfiguration2(msg);
41514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            break;
41614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
41714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
41814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case kWhatChangeConfiguration3:
41914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
42014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            onChangeConfiguration3(msg);
42114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            break;
42214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
42314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
42414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case kWhatFinishDisconnect2:
42514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
42614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            onFinishDisconnect2();
427a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
42814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
429a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
4301543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        case kWhatSwapped:
4311543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        {
4321543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            onSwapped(msg);
4331543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            break;
4341543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        }
435a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        default:
436a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            TRESPASS();
437a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
438a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
439a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
440a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
441a44153c1a57202fb538659eb50706e60454d6273Andreas Huber// static
442a44153c1a57202fb538659eb50706e60454d6273Andreas Huberint LiveSession::SortByBandwidth(const BandwidthItem *a, const BandwidthItem *b) {
443a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (a->mBandwidth < b->mBandwidth) {
444a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return -1;
445a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else if (a->mBandwidth == b->mBandwidth) {
446a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return 0;
447a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
448a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
449a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return 1;
450a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
451a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
4528ca002eedc747dd854b61cbe364b52c06869273fRobert Shih// static
4538ca002eedc747dd854b61cbe364b52c06869273fRobert ShihLiveSession::StreamType LiveSession::indexToType(int idx) {
4548ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    CHECK(idx >= 0 && idx < kMaxStreams);
4558ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    return (StreamType)(1 << idx);
4568ca002eedc747dd854b61cbe364b52c06869273fRobert Shih}
4578ca002eedc747dd854b61cbe364b52c06869273fRobert Shih
458a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onConnect(const sp<AMessage> &msg) {
459a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    AString url;
460a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    CHECK(msg->findString("url", &url));
461a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
462ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    KeyedVector<String8, String8> *headers = NULL;
463ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    if (!msg->findPointer("headers", (void **)&headers)) {
464ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        mExtraHeaders.clear();
465ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    } else {
466ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        mExtraHeaders = *headers;
467ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber
468ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        delete headers;
469ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        headers = NULL;
470ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    }
471ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber
47214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#if 1
47353ae1640ffbfc690962f7f94694b02680c6f66cbJames Dong    ALOGI("onConnect <URL suppressed>");
47414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#else
47514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    ALOGI("onConnect %s", url.c_str());
47614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#endif
477a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
478a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    mMasterURL = url;
479a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
4807e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    bool dummy;
48114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mPlaylist = fetchPlaylist(url.c_str(), NULL /* curPlaylistHash */, &dummy);
482ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
48314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (mPlaylist == NULL) {
48429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("unable to fetch master playlist '%s'.", url.c_str());
485ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
48614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        postPrepared(ERROR_IO);
487ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber        return;
488ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber    }
489a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
49014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // We trust the content provider to make a reasonable choice of preferred
49114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // initial bandwidth by listing it first in the variant playlist.
49214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // At startup we really don't have a good estimate on the available
49314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // network bandwidth since we haven't tranferred any data yet. Once
49414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // we have we can make a better informed choice.
49514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    size_t initialBandwidth = 0;
49614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    size_t initialBandwidthIndex = 0;
49714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
49814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (mPlaylist->isVariantPlaylist()) {
49914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        for (size_t i = 0; i < mPlaylist->size(); ++i) {
500a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            BandwidthItem item;
501a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
50214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            item.mPlaylistIndex = i;
50314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
504a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            sp<AMessage> meta;
50514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            AString uri;
50614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            mPlaylist->itemAt(i, &uri, &meta);
507a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
508a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            unsigned long bandwidth;
509a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            CHECK(meta->findInt32("bandwidth", (int32_t *)&item.mBandwidth));
510a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
51114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            if (initialBandwidth == 0) {
51214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                initialBandwidth = item.mBandwidth;
51314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            }
51414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
515a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            mBandwidthItems.push(item);
516a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
517a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
518a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        CHECK_GT(mBandwidthItems.size(), 0u);
519a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
520a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        mBandwidthItems.sort(SortByBandwidth);
52114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
52214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        for (size_t i = 0; i < mBandwidthItems.size(); ++i) {
52314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            if (mBandwidthItems.itemAt(i).mBandwidth == initialBandwidth) {
52414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                initialBandwidthIndex = i;
52514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                break;
52614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            }
52714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
52814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    } else {
52914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        // dummy item.
53014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        BandwidthItem item;
53114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        item.mPlaylistIndex = 0;
53214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        item.mBandwidth = 0;
53314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        mBandwidthItems.push(item);
534a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
535a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
536dcb89b3b505522efde173c105a851c412f947178Chong Zhang    changeConfiguration(
537dcb89b3b505522efde173c105a851c412f947178Chong Zhang            0ll /* timeUs */, initialBandwidthIndex, true /* pickTrack */);
538a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
539a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
54014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::finishDisconnect() {
54114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // No reconfiguration is currently pending, make sure none will trigger
54214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // during disconnection either.
54314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    cancelCheckBandwidthEvent();
54414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
5451543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // Protect mPacketSources from a swapPacketSource race condition through disconnect.
5461543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // (finishDisconnect, onFinishDisconnect2)
5471543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    cancelBandwidthSwitch();
5481543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
54914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
55014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        mFetcherInfos.valueAt(i).mFetcher->stopAsync();
55114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
55214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
55314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> msg = new AMessage(kWhatFinishDisconnect2, id());
554a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
55514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mContinuationCounter = mFetcherInfos.size();
55614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mContinuation = msg;
557ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
55814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (mContinuationCounter == 0) {
55914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        msg->post();
56014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
56114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
56214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
56314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::onFinishDisconnect2() {
56414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mContinuation.clear();
56514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
56614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mPacketSources.valueFor(STREAMTYPE_AUDIO)->signalEOS(ERROR_END_OF_STREAM);
56714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mPacketSources.valueFor(STREAMTYPE_VIDEO)->signalEOS(ERROR_END_OF_STREAM);
56814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
56914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mPacketSources.valueFor(
57014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            STREAMTYPE_SUBTITLES)->signalEOS(ERROR_END_OF_STREAM);
57114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
57214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> response = new AMessage;
57314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    response->setInt32("err", OK);
57414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
57514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    response->postReply(mDisconnectReplyID);
57614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mDisconnectReplyID = 0;
57714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
57814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
57914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubersp<PlaylistFetcher> LiveSession::addFetcher(const char *uri) {
58014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    ssize_t index = mFetcherInfos.indexOfKey(uri);
58114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
58214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (index >= 0) {
58314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        return NULL;
58414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
58514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
58614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> notify = new AMessage(kWhatFetcherNotify, id());
58714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->setString("uri", uri);
5881543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    notify->setInt32("switchGeneration", mSwitchGeneration);
58914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
59014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    FetcherInfo info;
59114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    info.mFetcher = new PlaylistFetcher(notify, this, uri);
59214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    info.mDurationUs = -1ll;
59314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    info.mIsPrepared = false;
5941543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    info.mToBeRemoved = false;
59514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    looper()->registerHandler(info.mFetcher);
59614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
59714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mFetcherInfos.add(uri, info);
59814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
59914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return info.mFetcher;
600a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
601a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
6028dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih/*
6038dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * Illustration of parameters:
6048dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih *
6058dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * 0      `range_offset`
6068dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * +------------+-------------------------------------------------------+--+--+
6078dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * |            |                                 | next block to fetch |  |  |
6088dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * |            | `source` handle => `out` buffer |                     |  |  |
6098dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * | `url` file |<--------- buffer size --------->|<--- `block_size` -->|  |  |
6108dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * |            |<----------- `range_length` / buffer capacity ----------->|  |
6118dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * |<------------------------------ file_size ------------------------------->|
6128dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih *
6138dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * Special parameter values:
6148dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * - range_length == -1 means entire file
6158dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * - block_size == 0 means entire range
6168dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih *
6178dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih */
6182aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huberstatus_t LiveSession::fetchFile(
6192aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        const char *url, sp<ABuffer> *out,
6208dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        int64_t range_offset, int64_t range_length,
6218dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        uint32_t block_size, /* download block size */
62297194cdf8d67f362ef8c6dfdf607298c7e102b3bMarco Nelissen        sp<DataSource> *source, /* to return and reuse source */
623784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo        String8 *actualUrl) {
6248dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    off64_t size;
6258dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    sp<DataSource> temp_source;
6268dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    if (source == NULL) {
6278dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        source = &temp_source;
6288dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    }
629a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
6308dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    if (*source == NULL) {
6318dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        if (!strncasecmp(url, "file://", 7)) {
6328dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            *source = new FileSource(url + 7);
6338dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        } else if (strncasecmp(url, "http://", 7)
6348dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                && strncasecmp(url, "https://", 8)) {
6358dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            return ERROR_UNSUPPORTED;
6368dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        } else {
6378dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            KeyedVector<String8, String8> headers = mExtraHeaders;
6388dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            if (range_offset > 0 || range_length >= 0) {
6398dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                headers.add(
6408dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                        String8("Range"),
6418dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                        String8(
6428dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                            StringPrintf(
6438dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                                "bytes=%lld-%s",
6448dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                                range_offset,
6458dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                                range_length < 0
6468dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                                    ? "" : StringPrintf("%lld",
6478dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                                            range_offset + range_length - 1).c_str()).c_str()));
6488dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            }
6498dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            status_t err = mHTTPDataSource->connect(url, &headers);
650a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
6518dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            if (err != OK) {
6528dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                return err;
6538dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            }
654a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
6558dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            *source = mHTTPDataSource;
656a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
657a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
658a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
6598dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    status_t getSizeErr = (*source)->getSize(&size);
6608dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    if (getSizeErr != OK) {
661a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        size = 65536;
662a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
663a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
6648dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    sp<ABuffer> buffer = *out != NULL ? *out : new ABuffer(size);
6658dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    if (*out == NULL) {
6668dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        buffer->setRange(0, 0);
6678dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    }
668a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
6698dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    // adjust range_length if only reading partial block
6708dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    if (block_size > 0 && (range_length == -1 || buffer->size() + block_size < range_length)) {
6718dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        range_length = buffer->size() + block_size;
6728dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    }
673a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    for (;;) {
6748dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        // Only resize when we don't know the size.
675a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        size_t bufferRemaining = buffer->capacity() - buffer->size();
6768dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        if (bufferRemaining == 0 && getSizeErr != OK) {
677a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            bufferRemaining = 32768;
678a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
6793856b090cd04ba5dd4a59a12430ed724d5995909Steve Block            ALOGV("increasing download buffer to %d bytes",
680a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                 buffer->size() + bufferRemaining);
681a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
682a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            sp<ABuffer> copy = new ABuffer(buffer->size() + bufferRemaining);
683a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            memcpy(copy->data(), buffer->data(), buffer->size());
684a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            copy->setRange(0, buffer->size());
685a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
686a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            buffer = copy;
687a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
688a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
6892aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        size_t maxBytesToRead = bufferRemaining;
6902aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        if (range_length >= 0) {
6912aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber            int64_t bytesLeftInRange = range_length - buffer->size();
6922aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber            if (bytesLeftInRange < maxBytesToRead) {
6932aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                maxBytesToRead = bytesLeftInRange;
6942aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber
6952aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                if (bytesLeftInRange == 0) {
6962aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                    break;
6972aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                }
6982aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber            }
6992aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        }
7002aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber
7018dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        // The DataSource is responsible for informing us of error (n < 0) or eof (n == 0)
7028dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        // to help us break out of the loop.
7038dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        ssize_t n = (*source)->readAt(
704a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                buffer->size(), buffer->data() + buffer->size(),
7052aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                maxBytesToRead);
706a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
707a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (n < 0) {
70820ad3a341a96e7746015ccb7369fa567897e11f6Andreas Huber            return n;
709a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
710a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
711a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (n == 0) {
712a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
713a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
714a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
715a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        buffer->setRange(0, buffer->size() + (size_t)n);
716a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
717a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
718a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    *out = buffer;
719784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo    if (actualUrl != NULL) {
72097194cdf8d67f362ef8c6dfdf607298c7e102b3bMarco Nelissen        *actualUrl = (*source)->getUri();
721784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo        if (actualUrl->isEmpty()) {
722784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo            *actualUrl = url;
723784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo        }
724784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo    }
725a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
726a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return OK;
727a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
728a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
72914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubersp<M3UParser> LiveSession::fetchPlaylist(
73014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        const char *url, uint8_t *curPlaylistHash, bool *unchanged) {
731b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber    ALOGV("fetchPlaylist '%s'", url);
732b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
7337e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    *unchanged = false;
7347e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
735a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<ABuffer> buffer;
736784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo    String8 actualUrl;
73797194cdf8d67f362ef8c6dfdf607298c7e102b3bMarco Nelissen    status_t err = fetchFile(url, &buffer, 0, -1, 0, NULL, &actualUrl);
738a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
739a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (err != OK) {
740a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return NULL;
741a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
742a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
7437e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    // MD5 functionality is not available on the simulator, treat all
7447e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    // playlists as changed.
7457e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
7467e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber#if defined(HAVE_ANDROID_OS)
7477e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    uint8_t hash[16];
7487e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
7497e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    MD5_CTX m;
7507e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    MD5_Init(&m);
7517e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    MD5_Update(&m, buffer->data(), buffer->size());
7527e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
7537e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    MD5_Final(hash, &m);
7547e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
75514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (curPlaylistHash != NULL && !memcmp(hash, curPlaylistHash, 16)) {
7567e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        // playlist unchanged
7577e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        *unchanged = true;
7587e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
7597e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        return NULL;
7607e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    }
7617e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
76214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (curPlaylistHash != NULL) {
76314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        memcpy(curPlaylistHash, hash, sizeof(hash));
76414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
7657e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber#endif
7667e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
767a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<M3UParser> playlist =
768784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo        new M3UParser(actualUrl.string(), buffer->data(), buffer->size());
769a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
770a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (playlist->initCheck() != OK) {
77129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("failed to parse .m3u8 playlist");
7729067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber
773a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return NULL;
774a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
775a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
776a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return playlist;
777a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
778a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
779a44153c1a57202fb538659eb50706e60454d6273Andreas Huberstatic double uniformRand() {
780a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return (double)rand() / RAND_MAX;
781a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
782a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
783a44153c1a57202fb538659eb50706e60454d6273Andreas Hubersize_t LiveSession::getBandwidthIndex() {
784a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (mBandwidthItems.size() == 0) {
785a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return 0;
786a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
787a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
788a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#if 1
789a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    char value[PROPERTY_VALUE_MAX];
790673158582c9589cee1d5e4d7c79622609938b8f8Andreas Huber    ssize_t index = -1;
79114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (property_get("media.httplive.bw-index", value, NULL)) {
792a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        char *end;
79314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        index = strtol(value, &end, 10);
79414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        CHECK(end > value && *end == '\0');
79514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
79614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (index >= 0 && (size_t)index >= mBandwidthItems.size()) {
79714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            index = mBandwidthItems.size() - 1;
798a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
799a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
800a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
80114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (index < 0) {
80214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        int32_t bandwidthBps;
80314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (mHTTPDataSource != NULL
80414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                && mHTTPDataSource->estimateBandwidth(&bandwidthBps)) {
80514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            ALOGV("bandwidth estimated at %.2f kbps", bandwidthBps / 1024.0f);
80614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        } else {
80714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            ALOGV("no bandwidth estimate.");
80814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            return 0;  // Pick the lowest bandwidth stream by default.
80914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
810a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
81114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        char value[PROPERTY_VALUE_MAX];
81214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (property_get("media.httplive.max-bw", value, NULL)) {
81314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            char *end;
81414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            long maxBw = strtoul(value, &end, 10);
81514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            if (end > value && *end == '\0') {
81614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                if (maxBw > 0 && bandwidthBps > maxBw) {
81714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    ALOGV("bandwidth capped to %ld bps", maxBw);
81814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    bandwidthBps = maxBw;
81914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                }
82014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            }
82114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
822a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
82314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        // Consider only 80% of the available bandwidth usable.
82414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        bandwidthBps = (bandwidthBps * 8) / 10;
82514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
82614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        // Pick the highest bandwidth stream below or equal to estimated bandwidth.
82714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
82814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        index = mBandwidthItems.size() - 1;
82914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        while (index > 0 && mBandwidthItems.itemAt(index).mBandwidth
83014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                                > (size_t)bandwidthBps) {
83114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            --index;
83214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
833a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
834a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0
835a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // Change bandwidth at random()
836a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index = uniformRand() * mBandwidthItems.size();
837a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0
838a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // There's a 50% chance to stay on the current bandwidth and
839a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // a 50% chance to switch to the next higher bandwidth (wrapping around
840a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // to lowest)
841a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    const size_t kMinIndex = 0;
842a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
84314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    static ssize_t mPrevBandwidthIndex = -1;
84414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
845a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index;
846a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (mPrevBandwidthIndex < 0) {
847a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        index = kMinIndex;
848a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else if (uniformRand() < 0.5) {
849a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        index = (size_t)mPrevBandwidthIndex;
850a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else {
851a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        index = mPrevBandwidthIndex + 1;
852a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (index == mBandwidthItems.size()) {
853a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            index = kMinIndex;
854a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
855a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
85614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mPrevBandwidthIndex = index;
857a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0
858a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // Pick the highest bandwidth stream below or equal to 1.2 Mbit/sec
859a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
860a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index = mBandwidthItems.size() - 1;
861a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    while (index > 0 && mBandwidthItems.itemAt(index).mBandwidth > 1200000) {
862a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        --index;
863a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
86414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#elif 1
86514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    char value[PROPERTY_VALUE_MAX];
86614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    size_t index;
86714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (property_get("media.httplive.bw-index", value, NULL)) {
86814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        char *end;
86914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        index = strtoul(value, &end, 10);
87014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        CHECK(end > value && *end == '\0');
87114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
87214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (index >= mBandwidthItems.size()) {
87314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            index = mBandwidthItems.size() - 1;
87414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
87514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    } else {
87614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        index = 0;
87714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
878a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#else
879a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index = mBandwidthItems.size() - 1;  // Highest bandwidth stream
880a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#endif
881a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
88214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK_GE(index, 0);
88314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
884a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return index;
885a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
886a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
88714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::onSeek(const sp<AMessage> &msg) {
88814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    int64_t timeUs;
88914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(msg->findInt64("timeUs", &timeUs));
8907e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
89114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (!mReconfigurationInProgress) {
89214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        changeConfiguration(timeUs, getBandwidthIndex());
8937e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    }
8947e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
89514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return OK;
8967e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber}
8977e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
89814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::getDuration(int64_t *durationUs) const {
89914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    int64_t maxDurationUs = 0ll;
90014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
90114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        int64_t fetcherDurationUs = mFetcherInfos.valueAt(i).mDurationUs;
902b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
90314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (fetcherDurationUs >= 0ll && fetcherDurationUs > maxDurationUs) {
90414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            maxDurationUs = fetcherDurationUs;
905a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
906a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
907a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
90814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    *durationUs = maxDurationUs;
909a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
91014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return OK;
91114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
9120f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber
91314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberbool LiveSession::isSeekable() const {
91414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    int64_t durationUs;
91514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return getDuration(&durationUs) == OK && durationUs >= 0;
91614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
9170f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber
91814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberbool LiveSession::hasDynamicDuration() const {
91914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return false;
92014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
9210f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber
922dcb89b3b505522efde173c105a851c412f947178Chong Zhangstatus_t LiveSession::getTrackInfo(Parcel *reply) const {
923dcb89b3b505522efde173c105a851c412f947178Chong Zhang    return mPlaylist->getTrackInfo(reply);
924dcb89b3b505522efde173c105a851c412f947178Chong Zhang}
925dcb89b3b505522efde173c105a851c412f947178Chong Zhang
926dcb89b3b505522efde173c105a851c412f947178Chong Zhangstatus_t LiveSession::selectTrack(size_t index, bool select) {
927dcb89b3b505522efde173c105a851c412f947178Chong Zhang    status_t err = mPlaylist->selectTrack(index, select);
928dcb89b3b505522efde173c105a851c412f947178Chong Zhang    if (err == OK) {
929dcb89b3b505522efde173c105a851c412f947178Chong Zhang        (new AMessage(kWhatChangeConfiguration, id()))->post();
930dcb89b3b505522efde173c105a851c412f947178Chong Zhang    }
931dcb89b3b505522efde173c105a851c412f947178Chong Zhang    return err;
932dcb89b3b505522efde173c105a851c412f947178Chong Zhang}
933dcb89b3b505522efde173c105a851c412f947178Chong Zhang
9341543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shihbool LiveSession::canSwitchUp() {
9351543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // Allow upwards bandwidth switch when a stream has buffered at least 10 seconds.
9361543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    status_t err = OK;
9371543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    for (size_t i = 0; i < mPacketSources.size(); ++i) {
9381543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        sp<AnotherPacketSource> source = mPacketSources.valueAt(i);
9391543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        int64_t dur = source->getBufferedDurationUs(&err);
9401543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        if (err == OK && dur > 10000000) {
9411543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            return true;
9421543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        }
9431543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
9441543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    return false;
9451543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
9461543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
947dcb89b3b505522efde173c105a851c412f947178Chong Zhangvoid LiveSession::changeConfiguration(
948dcb89b3b505522efde173c105a851c412f947178Chong Zhang        int64_t timeUs, size_t bandwidthIndex, bool pickTrack) {
9491543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // Protect mPacketSources from a swapPacketSource race condition through reconfiguration.
9501543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // (changeConfiguration, onChangeConfiguration2, onChangeConfiguration3).
9511543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    cancelBandwidthSwitch();
9521543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
95314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(!mReconfigurationInProgress);
95414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mReconfigurationInProgress = true;
955a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
95614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mPrevBandwidthIndex = bandwidthIndex;
95743c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
958dcb89b3b505522efde173c105a851c412f947178Chong Zhang    ALOGV("changeConfiguration => timeUs:%lld us, bwIndex:%d, pickTrack:%d",
959dcb89b3b505522efde173c105a851c412f947178Chong Zhang          timeUs, bandwidthIndex, pickTrack);
96043c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
961dcb89b3b505522efde173c105a851c412f947178Chong Zhang    if (pickTrack) {
962dcb89b3b505522efde173c105a851c412f947178Chong Zhang        mPlaylist->pickRandomMediaItems();
963dcb89b3b505522efde173c105a851c412f947178Chong Zhang    }
96443c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
96514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK_LT(bandwidthIndex, mBandwidthItems.size());
96614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    const BandwidthItem &item = mBandwidthItems.itemAt(bandwidthIndex);
967a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
9681543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    uint32_t streamMask = 0; // streams that should be fetched by the new fetcher
9691543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    uint32_t resumeMask = 0; // streams that should be fetched by the original fetcher
970a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
9718ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    AString URIs[kMaxStreams];
9728ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
9738ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        if (mPlaylist->getTypeURI(item.mPlaylistIndex, mStreams[i].mType, &URIs[i])) {
9748ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            streamMask |= indexToType(i);
9758ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        }
97614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
977aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber
97814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Step 1, stop and discard fetchers that are no longer needed.
97914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Pause those that we'll reuse.
98014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
98114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        const AString &uri = mFetcherInfos.keyAt(i);
982aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber
98314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        bool discardFetcher = true;
984aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber
98514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        // If we're seeking all current fetchers are discarded.
98614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (timeUs < 0ll) {
9871543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            // delay fetcher removal
9881543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            discardFetcher = false;
9891543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
9908ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            for (size_t j = 0; j < kMaxStreams; ++j) {
9911543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                StreamType type = indexToType(j);
9921543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                if ((streamMask & type) && uri == URIs[j]) {
9931543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    resumeMask |= type;
9941543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    streamMask &= ~type;
9958ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                }
9966801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber            }
99714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
998a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
99914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (discardFetcher) {
100014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            mFetcherInfos.valueAt(i).mFetcher->stopAsync();
10016801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber        } else {
100214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            mFetcherInfos.valueAt(i).mFetcher->pauseAsync();
10036801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber        }
1004a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1005a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
10061543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    sp<AMessage> msg;
10071543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    if (timeUs < 0ll) {
10081543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        // skip onChangeConfiguration2 (decoder destruction) if switching.
10091543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        msg = new AMessage(kWhatChangeConfiguration3, id());
10101543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    } else {
10111543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        msg = new AMessage(kWhatChangeConfiguration2, id());
10121543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
101314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    msg->setInt32("streamMask", streamMask);
10141543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    msg->setInt32("resumeMask", resumeMask);
101514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    msg->setInt64("timeUs", timeUs);
10168ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
10178ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        if (streamMask & indexToType(i)) {
10188ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            msg->setString(mStreams[i].uriKey().c_str(), URIs[i].c_str());
10198ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        }
10206e6b1cae2bac1b78205cefab8e4e9e9538982965Andreas Huber    }
1021a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
102214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Every time a fetcher acknowledges the stopAsync or pauseAsync request
102314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // we'll decrement mContinuationCounter, once it reaches zero, i.e. all
102414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // fetchers have completed their asynchronous operation, we'll post
102514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // mContinuation, which then is handled below in onChangeConfiguration2.
102614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mContinuationCounter = mFetcherInfos.size();
102714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mContinuation = msg;
102888b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber
102914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (mContinuationCounter == 0) {
103014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        msg->post();
103188b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber    }
103214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
1033a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1034dcb89b3b505522efde173c105a851c412f947178Chong Zhangvoid LiveSession::onChangeConfiguration(const sp<AMessage> &msg) {
1035dcb89b3b505522efde173c105a851c412f947178Chong Zhang    if (!mReconfigurationInProgress) {
1036dcb89b3b505522efde173c105a851c412f947178Chong Zhang        changeConfiguration(-1ll /* timeUs */, getBandwidthIndex());
1037dcb89b3b505522efde173c105a851c412f947178Chong Zhang    } else {
1038dcb89b3b505522efde173c105a851c412f947178Chong Zhang        msg->post(1000000ll); // retry in 1 sec
1039dcb89b3b505522efde173c105a851c412f947178Chong Zhang    }
1040dcb89b3b505522efde173c105a851c412f947178Chong Zhang}
1041dcb89b3b505522efde173c105a851c412f947178Chong Zhang
104214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::onChangeConfiguration2(const sp<AMessage> &msg) {
104314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mContinuation.clear();
1044bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
104514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // All fetchers are either suspended or have been removed now.
1046bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
104714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    uint32_t streamMask;
104814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(msg->findInt32("streamMask", (int32_t *)&streamMask));
1049bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
10508ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    AString URIs[kMaxStreams];
10518ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
10528ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        if (streamMask & indexToType(i)) {
10538ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            const AString &uriKey = mStreams[i].uriKey();
10548ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            CHECK(msg->findString(uriKey.c_str(), &URIs[i]));
10558ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            ALOGV("%s = '%s'", uriKey.c_str(), URIs[i].c_str());
10568ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        }
105722fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber    }
10583831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber
105914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Determine which decoders to shutdown on the player side,
106014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // a decoder has to be shutdown if either
106114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // 1) its streamtype was active before but now longer isn't.
106214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // or
106314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // 2) its streamtype was already active and still is but the URI
106414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    //    has changed.
106514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    uint32_t changedMask = 0;
10668ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams && i != kSubtitleIndex; ++i) {
10678ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        if (((mStreamMask & streamMask & indexToType(i))
10688ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                && !(URIs[i] == mStreams[i].mUri))
10698ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                || (mStreamMask & ~streamMask & indexToType(i))) {
10708ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            changedMask |= indexToType(i);
10718ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        }
1072b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber    }
1073b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
107414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (changedMask == 0) {
107514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        // If nothing changed as far as the audio/video decoders
107614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        // are concerned we can proceed.
107714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        onChangeConfiguration3(msg);
107814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        return;
107914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
108043c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
108114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Something changed, inform the player which will shutdown the
108214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // corresponding decoders and will post the reply once that's done.
108314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Handling the reply will continue executing below in
108414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // onChangeConfiguration3.
108514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> notify = mNotify->dup();
108614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->setInt32("what", kWhatStreamsChanged);
108714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->setInt32("changedMask", changedMask);
108820f725ebcef13ded1b4b85c61c8a4b37cd030656Andreas Huber
108914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    msg->setWhat(kWhatChangeConfiguration3);
109014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    msg->setTarget(id());
1091b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
109214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->setMessage("reply", msg);
109314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->post();
109414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
1095b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
109614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::onChangeConfiguration3(const sp<AMessage> &msg) {
10971543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    mContinuation.clear();
109814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // All remaining fetchers are still suspended, the player has shutdown
109914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // any decoders that needed it.
1100b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
11011543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    uint32_t streamMask, resumeMask;
110214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(msg->findInt32("streamMask", (int32_t *)&streamMask));
11031543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    CHECK(msg->findInt32("resumeMask", (int32_t *)&resumeMask));
1104a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
11058ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
11068ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        if (streamMask & indexToType(i)) {
11078ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            CHECK(msg->findString(mStreams[i].uriKey().c_str(), &mStreams[i].mUri));
11088ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        }
1109a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1110a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
111114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    int64_t timeUs;
11121543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    bool switching = false;
111314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(msg->findInt64("timeUs", &timeUs));
1114a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
111514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (timeUs < 0ll) {
111614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        timeUs = mLastDequeuedTimeUs;
11171543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        switching = true;
111814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
1119dcb89b3b505522efde173c105a851c412f947178Chong Zhang    mRealTimeBaseUs = ALooper::GetNowUs() - timeUs;
1120a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
11211543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    mNewStreamMask = streamMask;
1122a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
11231543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // Of all existing fetchers:
11241543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // * Resume fetchers that are still needed and assign them original packet sources.
11251543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // * Mark otherwise unneeded fetchers for removal.
11261543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    ALOGV("resuming fetchers for mask 0x%08x", resumeMask);
112714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
112814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        const AString &uri = mFetcherInfos.keyAt(i);
11290df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas Huber
11308ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        sp<AnotherPacketSource> sources[kMaxStreams];
1131dc793ce8c0ead27ab43e40ce09f27fe338323502Robert Shih        for (size_t j = 0; j < kMaxStreams; ++j) {
11321543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            if ((resumeMask & indexToType(j)) && uri == mStreams[j].mUri) {
11338ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                sources[j] = mPacketSources.valueFor(indexToType(j));
11348ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            }
113514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
1136a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
11371543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        FetcherInfo &info = mFetcherInfos.editValueAt(i);
11381543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        if (sources[kAudioIndex] != NULL || sources[kVideoIndex] != NULL
11391543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                || sources[kSubtitleIndex] != NULL) {
11401543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            info.mFetcher->startAsync(
11411543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    sources[kAudioIndex], sources[kVideoIndex], sources[kSubtitleIndex]);
11421543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        } else {
11431543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            info.mToBeRemoved = true;
11441543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        }
1145a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1146a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
114714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // streamMask now only contains the types that need a new fetcher created.
1148a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
114914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (streamMask != 0) {
115014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        ALOGV("creating new fetchers for mask 0x%08x", streamMask);
1151a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1152a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
11531543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // Find out when the original fetchers have buffered up to and start the new fetchers
11541543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // at a later timestamp.
11558ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams; i++) {
11568ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        if (!(indexToType(i) & streamMask)) {
11578ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            continue;
11588ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        }
11591156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
116014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        AString uri;
11618ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        uri = mStreams[i].mUri;
11629b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber
116314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        sp<PlaylistFetcher> fetcher = addFetcher(uri.c_str());
116414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        CHECK(fetcher != NULL);
1165a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
11661543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        int32_t latestSeq = -1;
11671543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        int64_t latestTimeUs = 0ll;
11688ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        sp<AnotherPacketSource> sources[kMaxStreams];
11691543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
11708ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        // TRICKY: looping from i as earlier streams are already removed from streamMask
11718ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        for (size_t j = i; j < kMaxStreams; ++j) {
11728ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            if ((streamMask & indexToType(j)) && uri == mStreams[j].mUri) {
11738ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                sources[j] = mPacketSources.valueFor(indexToType(j));
11741543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
11751543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                if (!switching) {
11761543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    sources[j]->clear();
11771543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                } else {
11781543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    int32_t type, seq;
11791543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    int64_t srcTimeUs;
11801543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    sp<AMessage> meta = sources[j]->getLatestMeta();
11811543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
11821543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    if (meta != NULL && !meta->findInt32("discontinuity", &type)) {
11831543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        CHECK(meta->findInt32("seq", &seq));
11841543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        if (seq > latestSeq) {
11851543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                            latestSeq = seq;
11861543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        }
11871543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        CHECK(meta->findInt64("timeUs", &srcTimeUs));
11881543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        if (srcTimeUs > latestTimeUs) {
11891543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                            latestTimeUs = srcTimeUs;
11901543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        }
11911543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    }
11921543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
11931543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    sources[j] = mPacketSources2.valueFor(indexToType(j));
11941543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    sources[j]->clear();
11951543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    uint32_t extraStreams = mNewStreamMask & (~mStreamMask);
11961543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    if (extraStreams & indexToType(j)) {
11971543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        sources[j]->queueAccessUnit(createFormatChangeBuffer(/* swap = */ false));
11981543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    }
11991543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                }
1200a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
12018ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                streamMask &= ~indexToType(j);
12028ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            }
1203a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
120414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
12058ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        fetcher->startAsync(
12068ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                sources[kAudioIndex],
12078ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                sources[kVideoIndex],
12088ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                sources[kSubtitleIndex],
12091543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                timeUs,
12101543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                latestTimeUs /* min start time(us) */,
12111543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                latestSeq >= 0 ? latestSeq + 1 : -1 /* starting sequence number hint */ );
1212a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1213a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
121414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // All fetchers have now been started, the configuration change
121514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // has completed.
1216a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
121714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    scheduleCheckBandwidthEvent();
1218a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
121914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    ALOGV("XXX configuration change completed.");
122014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mReconfigurationInProgress = false;
12211543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    if (switching) {
12221543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        mSwitchInProgress = true;
12231543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    } else {
12241543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        mStreamMask = mNewStreamMask;
12251543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
1226a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
122714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (mDisconnectReplyID != 0) {
122814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        finishDisconnect();
1229a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
123014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
1231a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
12321543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shihvoid LiveSession::onSwapped(const sp<AMessage> &msg) {
12331543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    int32_t switchGeneration;
12341543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    CHECK(msg->findInt32("switchGeneration", &switchGeneration));
12351543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    if (switchGeneration != mSwitchGeneration) {
12361543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return;
12371543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
12381543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
12391543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    int32_t stream;
12401543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    CHECK(msg->findInt32("stream", &stream));
12411543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    mSwapMask |= stream;
12421543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    if (mSwapMask != mStreamMask) {
12431543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return;
12441543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
12451543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
12461543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // Check if new variant contains extra streams.
12471543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    uint32_t extraStreams = mNewStreamMask & (~mStreamMask);
12481543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    while (extraStreams) {
12491543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        StreamType extraStream = (StreamType) (extraStreams & ~(extraStreams - 1));
12501543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        swapPacketSource(extraStream);
12511543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        extraStreams &= ~extraStream;
12521543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
12531543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
12541543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    tryToFinishBandwidthSwitch();
12551543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
12561543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
12571543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih// Mark switch done when:
12581543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih//   1. all old buffers are swapped out, AND
12591543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih//   2. all old fetchers are removed.
12601543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shihvoid LiveSession::tryToFinishBandwidthSwitch() {
12611543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    bool needToRemoveFetchers = false;
12621543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
12631543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        if (mFetcherInfos.valueAt(i).mToBeRemoved) {
12641543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            needToRemoveFetchers = true;
12651543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            break;
12661543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        }
12671543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
12681543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    if (!needToRemoveFetchers && mSwapMask == mStreamMask) {
12691543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        mStreamMask = mNewStreamMask;
12701543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        mSwitchInProgress = false;
12711543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        mSwapMask = 0;
12721543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
12731543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
12741543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
127514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::scheduleCheckBandwidthEvent() {
127614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> msg = new AMessage(kWhatCheckBandwidth, id());
127714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    msg->setInt32("generation", mCheckBandwidthGeneration);
127814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    msg->post(10000000ll);
1279a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
1280a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
128114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::cancelCheckBandwidthEvent() {
128214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    ++mCheckBandwidthGeneration;
1283a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
1284a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
12851543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shihvoid LiveSession::cancelBandwidthSwitch() {
12861543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    Mutex::Autolock lock(mSwapMutex);
12871543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    mSwitchGeneration++;
12881543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    mSwitchInProgress = false;
12891543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    mSwapMask = 0;
12901543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
12911543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
12921543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shihbool LiveSession::canSwitchBandwidthTo(size_t bandwidthIndex) {
12931543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    if (mReconfigurationInProgress || mSwitchInProgress) {
12941543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return false;
12951543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
12961543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
12971543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    if (mPrevBandwidthIndex < 0) {
12981543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return true;
129914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
130014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
13011543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    if (bandwidthIndex == (size_t)mPrevBandwidthIndex) {
13021543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return false;
13031543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    } else if (bandwidthIndex > (size_t)mPrevBandwidthIndex) {
13041543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return canSwitchUp();
13051543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    } else {
13061543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return true;
13071543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
13081543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
13091543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
13101543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shihvoid LiveSession::onCheckBandwidth() {
131114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    size_t bandwidthIndex = getBandwidthIndex();
13121543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    if (canSwitchBandwidthTo(bandwidthIndex)) {
131314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        changeConfiguration(-1ll /* timeUs */, bandwidthIndex);
13141543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    } else {
13151543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        scheduleCheckBandwidthEvent();
131614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
1317a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
131814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Handling the kWhatCheckBandwidth even here does _not_ automatically
131914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // schedule another one on return, only an explicit call to
132014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // scheduleCheckBandwidthEvent will do that.
132114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // This ensures that only one configuration change is ongoing at any
132214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // one time, once that completes it'll schedule another check bandwidth
132314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // event.
1324a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
1325a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
132614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::postPrepared(status_t err) {
132714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(mInPreparationPhase);
1328a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
132914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> notify = mNotify->dup();
133014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (err == OK || err == ERROR_END_OF_STREAM) {
133114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        notify->setInt32("what", kWhatPrepared);
133214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    } else {
133314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        notify->setInt32("what", kWhatPreparationFailed);
133414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        notify->setInt32("err", err);
133514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
1336a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
133714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->post();
1338a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
133914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mInPreparationPhase = false;
1340b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber}
1341b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
1342a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}  // namespace android
1343a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1344