LiveSession.cpp revision a1df816c0677185534babba6ffc29970b048e52e
1a44153c1a57202fb538659eb50706e60454d6273Andreas Huber/*
2a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * Copyright (C) 2010 The Android Open Source Project
3a44153c1a57202fb538659eb50706e60454d6273Andreas Huber *
4a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * you may not use this file except in compliance with the License.
6a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * You may obtain a copy of the License at
7a44153c1a57202fb538659eb50706e60454d6273Andreas Huber *
8a44153c1a57202fb538659eb50706e60454d6273Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
9a44153c1a57202fb538659eb50706e60454d6273Andreas Huber *
10a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * Unless required by applicable law or agreed to in writing, software
11a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * See the License for the specific language governing permissions and
14a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * limitations under the License.
15a44153c1a57202fb538659eb50706e60454d6273Andreas Huber */
16a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
17a44153c1a57202fb538659eb50706e60454d6273Andreas Huber//#define LOG_NDEBUG 0
18a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#define LOG_TAG "LiveSession"
19a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <utils/Log.h>
20a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
2114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include "LiveSession.h"
22a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
2314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include "M3UParser.h"
2414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include "PlaylistFetcher.h"
25a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
261156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber#include "include/HTTPBase.h"
2714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include "mpeg2ts/AnotherPacketSource.h"
28a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
29a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <cutils/properties.h>
301b86fe063badb5f28c467ade39be0f4008688947Andreas Huber#include <media/IMediaHTTPConnection.h>
311b86fe063badb5f28c467ade39be0f4008688947Andreas Huber#include <media/IMediaHTTPService.h>
32a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <media/stagefright/foundation/hexdump.h>
33a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <media/stagefright/foundation/ABuffer.h>
34a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <media/stagefright/foundation/ADebug.h>
35a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <media/stagefright/foundation/AMessage.h>
36a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <media/stagefright/DataSource.h>
37a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <media/stagefright/FileSource.h>
38a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <media/stagefright/MediaErrors.h>
391b86fe063badb5f28c467ade39be0f4008688947Andreas Huber#include <media/stagefright/MediaHTTP.h>
4014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include <media/stagefright/MetaData.h>
4114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include <media/stagefright/Utils.h>
42a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
431543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih#include <utils/Mutex.h>
441543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
45a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <ctype.h>
46b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross#include <inttypes.h>
47a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <openssl/aes.h>
487e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber#include <openssl/md5.h>
49a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
50a44153c1a57202fb538659eb50706e60454d6273Andreas Hubernamespace android {
51a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
520df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas HuberLiveSession::LiveSession(
531b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        const sp<AMessage> &notify, uint32_t flags,
5481e68448f3361eaf8618930471fdc3c21bdf5cbcAndreas Huber        const sp<IMediaHTTPService> &httpService)
550df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas Huber    : mNotify(notify),
560df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas Huber      mFlags(flags),
571b86fe063badb5f28c467ade39be0f4008688947Andreas Huber      mHTTPService(httpService),
580df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas Huber      mInPreparationPhase(true),
591b86fe063badb5f28c467ade39be0f4008688947Andreas Huber      mHTTPDataSource(new MediaHTTP(mHTTPService->makeHTTPConnection())),
60a44153c1a57202fb538659eb50706e60454d6273Andreas Huber      mPrevBandwidthIndex(-1),
6114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber      mStreamMask(0),
621543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih      mNewStreamMask(0),
631543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih      mSwapMask(0),
6414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber      mCheckBandwidthGeneration(0),
651543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih      mSwitchGeneration(0),
6614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber      mLastDequeuedTimeUs(0ll),
67dcb89b3b505522efde173c105a851c412f947178Chong Zhang      mRealTimeBaseUs(0ll),
6814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber      mReconfigurationInProgress(false),
691543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih      mSwitchInProgress(false),
705ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih      mDisconnectReplyID(0),
715ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih      mSeekReplyID(0) {
7214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
738ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    mStreams[kAudioIndex] = StreamItem("audio");
748ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    mStreams[kVideoIndex] = StreamItem("video");
75e4f25c280a8f1655c31a745978e0fcbc61f91deeRobert Shih    mStreams[kSubtitleIndex] = StreamItem("subtitles");
7614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
778ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
788ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        mPacketSources.add(indexToType(i), new AnotherPacketSource(NULL /* meta */));
791543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        mPacketSources2.add(indexToType(i), new AnotherPacketSource(NULL /* meta */));
808ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    }
81a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
82a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
83a44153c1a57202fb538659eb50706e60454d6273Andreas HuberLiveSession::~LiveSession() {
84a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
85a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
861543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shihsp<ABuffer> LiveSession::createFormatChangeBuffer(bool swap) {
871543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    ABuffer *discontinuity = new ABuffer(0);
881543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    discontinuity->meta()->setInt32("discontinuity", ATSParser::DISCONTINUITY_FORMATCHANGE);
891543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    discontinuity->meta()->setInt32("swapPacketSource", swap);
901543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    discontinuity->meta()->setInt32("switchGeneration", mSwitchGeneration);
911543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    discontinuity->meta()->setInt64("timeUs", -1);
921543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    return discontinuity;
931543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
941543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
951543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shihvoid LiveSession::swapPacketSource(StreamType stream) {
961543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    sp<AnotherPacketSource> &aps = mPacketSources.editValueFor(stream);
971543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    sp<AnotherPacketSource> &aps2 = mPacketSources2.editValueFor(stream);
981543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    sp<AnotherPacketSource> tmp = aps;
991543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    aps = aps2;
1001543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    aps2 = tmp;
1011543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    aps2->clear();
1021543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
1031543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
10414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::dequeueAccessUnit(
10514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        StreamType stream, sp<ABuffer> *accessUnit) {
10614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (!(mStreamMask & stream)) {
1071543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        // return -EWOULDBLOCK to avoid halting the decoder
1081543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        // when switching between audio/video and audio only.
1091543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return -EWOULDBLOCK;
11014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
11114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
11214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AnotherPacketSource> packetSource = mPacketSources.valueFor(stream);
11314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
11414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    status_t finalResult;
11514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (!packetSource->hasBufferAvailable(&finalResult)) {
11614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        return finalResult == OK ? -EAGAIN : finalResult;
11714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
11814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
11914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    status_t err = packetSource->dequeueAccessUnit(accessUnit);
12014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
12114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    const char *streamStr;
12214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    switch (stream) {
12314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case STREAMTYPE_AUDIO:
12414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            streamStr = "audio";
12514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            break;
12614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case STREAMTYPE_VIDEO:
12714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            streamStr = "video";
12814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            break;
12914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case STREAMTYPE_SUBTITLES:
13014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            streamStr = "subs";
13114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            break;
13214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        default:
13314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            TRESPASS();
13414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
13514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
13614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (err == INFO_DISCONTINUITY) {
13714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        int32_t type;
13814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        CHECK((*accessUnit)->meta()->findInt32("discontinuity", &type));
13914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
14014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        sp<AMessage> extra;
14114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (!(*accessUnit)->meta()->findMessage("extra", &extra)) {
14214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            extra.clear();
14314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
14414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
14514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        ALOGI("[%s] read discontinuity of type %d, extra = %s",
14614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber              streamStr,
14714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber              type,
14814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber              extra == NULL ? "NULL" : extra->debugString().c_str());
1491543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
1501543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        int32_t swap;
1511543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        if (type == ATSParser::DISCONTINUITY_FORMATCHANGE
1521543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                && (*accessUnit)->meta()->findInt32("swapPacketSource", &swap)
1531543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                && swap) {
1541543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
1551543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            int32_t switchGeneration;
1561543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            CHECK((*accessUnit)->meta()->findInt32("switchGeneration", &switchGeneration));
1571543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            {
1581543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                Mutex::Autolock lock(mSwapMutex);
1591543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                if (switchGeneration == mSwitchGeneration) {
1601543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    swapPacketSource(stream);
1611543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    sp<AMessage> msg = new AMessage(kWhatSwapped, id());
1621543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    msg->setInt32("stream", stream);
1631543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    msg->setInt32("switchGeneration", switchGeneration);
1641543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    msg->post();
1651543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                }
1661543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            }
1671543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        }
16814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    } else if (err == OK) {
169dcb89b3b505522efde173c105a851c412f947178Chong Zhang        if (stream == STREAMTYPE_AUDIO || stream == STREAMTYPE_VIDEO) {
170dcb89b3b505522efde173c105a851c412f947178Chong Zhang            int64_t timeUs;
171dcb89b3b505522efde173c105a851c412f947178Chong Zhang            CHECK((*accessUnit)->meta()->findInt64("timeUs",  &timeUs));
172b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross            ALOGV("[%s] read buffer at time %" PRId64 " us", streamStr, timeUs);
173dcb89b3b505522efde173c105a851c412f947178Chong Zhang
174dcb89b3b505522efde173c105a851c412f947178Chong Zhang            mLastDequeuedTimeUs = timeUs;
175dcb89b3b505522efde173c105a851c412f947178Chong Zhang            mRealTimeBaseUs = ALooper::GetNowUs() - timeUs;
176dcb89b3b505522efde173c105a851c412f947178Chong Zhang        } else if (stream == STREAMTYPE_SUBTITLES) {
177dcb89b3b505522efde173c105a851c412f947178Chong Zhang            (*accessUnit)->meta()->setInt32(
178dcb89b3b505522efde173c105a851c412f947178Chong Zhang                    "trackIndex", mPlaylist->getSelectedIndex());
179dcb89b3b505522efde173c105a851c412f947178Chong Zhang            (*accessUnit)->meta()->setInt64("baseUs", mRealTimeBaseUs);
180dcb89b3b505522efde173c105a851c412f947178Chong Zhang        }
18114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    } else {
18214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        ALOGI("[%s] encountered error %d", streamStr, err);
18314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
18414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
18514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return err;
18614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
18714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
18814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::getStreamFormat(StreamType stream, sp<AMessage> *format) {
1891543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // No swapPacketSource race condition; called from the same thread as dequeueAccessUnit.
19014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (!(mStreamMask & stream)) {
19114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        return UNKNOWN_ERROR;
19214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
19314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
19414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AnotherPacketSource> packetSource = mPacketSources.valueFor(stream);
19514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
19614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<MetaData> meta = packetSource->getFormat();
19714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
19814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (meta == NULL) {
19914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        return -EAGAIN;
20014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
20114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
20214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return convertMetaDataToMessage(meta, format);
203a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
204a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
20514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::connectAsync(
206ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        const char *url, const KeyedVector<String8, String8> *headers) {
207a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<AMessage> msg = new AMessage(kWhatConnect, id());
208a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    msg->setString("url", url);
209ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber
210ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    if (headers != NULL) {
211ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        msg->setPointer(
212ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber                "headers",
213ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber                new KeyedVector<String8, String8>(*headers));
214ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    }
215ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber
216a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    msg->post();
217a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
218a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
21914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::disconnect() {
22014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> msg = new AMessage(kWhatDisconnect, id());
221ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
22214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> response;
22314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    status_t err = msg->postAndAwaitResponse(&response);
224ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
22514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return err;
226a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
227a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
22814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::seekTo(int64_t timeUs) {
229a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<AMessage> msg = new AMessage(kWhatSeek, id());
230a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    msg->setInt64("timeUs", timeUs);
231a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
23214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> response;
23314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    status_t err = msg->postAndAwaitResponse(&response);
23414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
2355ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih    uint32_t replyID;
2365ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih    CHECK(response == mSeekReply && 0 != mSeekReplyID);
2375ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih    mSeekReply.clear();
2385ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih    mSeekReplyID = 0;
23914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return err;
240a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
241a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
242a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onMessageReceived(const sp<AMessage> &msg) {
243a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    switch (msg->what()) {
244a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        case kWhatConnect:
24514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
246a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            onConnect(msg);
247a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
24814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
249a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
250a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        case kWhatDisconnect:
25114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
25214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            CHECK(msg->senderAwaitsResponse(&mDisconnectReplyID));
25314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
25414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            if (mReconfigurationInProgress) {
25514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                break;
25614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            }
25714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
25814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            finishDisconnect();
259a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
26014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
261a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
26214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case kWhatSeek:
26314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
2645ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih            CHECK(msg->senderAwaitsResponse(&mSeekReplyID));
26514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
26614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            status_t err = onSeek(msg);
26714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
2685ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih            mSeekReply = new AMessage;
2695ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih            mSeekReply->setInt32("err", err);
27014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            break;
27114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
27214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
27314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case kWhatFetcherNotify:
27414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
27514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            int32_t what;
27614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            CHECK(msg->findInt32("what", &what));
27714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
27814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            switch (what) {
27914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                case PlaylistFetcher::kWhatStarted:
28014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    break;
28114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                case PlaylistFetcher::kWhatPaused:
28214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                case PlaylistFetcher::kWhatStopped:
28314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                {
28414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    if (what == PlaylistFetcher::kWhatStopped) {
28514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        AString uri;
28614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        CHECK(msg->findString("uri", &uri));
2871543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        if (mFetcherInfos.removeItem(uri) < 0) {
2881543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                            // ignore duplicated kWhatStopped messages.
2891543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                            break;
2901543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        }
2911543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
2921543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        tryToFinishBandwidthSwitch();
29314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    }
29414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
29514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    if (mContinuation != NULL) {
29614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        CHECK_GT(mContinuationCounter, 0);
29714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        if (--mContinuationCounter == 0) {
29814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                            mContinuation->post();
2995ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih
3005ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih                            if (mSeekReplyID != 0) {
3015ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih                                CHECK(mSeekReply != NULL);
3025ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih                                mSeekReply->postReply(mSeekReplyID);
3035ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih                            }
30414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        }
30514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    }
30614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    break;
30714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                }
30814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
30914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                case PlaylistFetcher::kWhatDurationUpdate:
31014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                {
31114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    AString uri;
31214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    CHECK(msg->findString("uri", &uri));
31314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
31414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    int64_t durationUs;
31514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    CHECK(msg->findInt64("durationUs", &durationUs));
31614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
31714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    FetcherInfo *info = &mFetcherInfos.editValueFor(uri);
31814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    info->mDurationUs = durationUs;
31914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    break;
32014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                }
32114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
32214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                case PlaylistFetcher::kWhatError:
32314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                {
32414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    status_t err;
32514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    CHECK(msg->findInt32("err", &err));
32614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
32714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    ALOGE("XXX Received error %d from PlaylistFetcher.", err);
32814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
32914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    if (mInPreparationPhase) {
33014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        postPrepared(err);
33114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    }
33214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
3331543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    cancelBandwidthSwitch();
3341543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
33514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    mPacketSources.valueFor(STREAMTYPE_AUDIO)->signalEOS(err);
33614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
33714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    mPacketSources.valueFor(STREAMTYPE_VIDEO)->signalEOS(err);
33814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
33914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    mPacketSources.valueFor(
34014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                            STREAMTYPE_SUBTITLES)->signalEOS(err);
34114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
34214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    sp<AMessage> notify = mNotify->dup();
34314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    notify->setInt32("what", kWhatError);
34414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    notify->setInt32("err", err);
34514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    notify->post();
34614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    break;
34714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                }
34814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
34914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                case PlaylistFetcher::kWhatTemporarilyDoneFetching:
35014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                {
35114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    AString uri;
35214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    CHECK(msg->findString("uri", &uri));
35314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
35414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    FetcherInfo *info = &mFetcherInfos.editValueFor(uri);
35514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    info->mIsPrepared = true;
35614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
35714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    if (mInPreparationPhase) {
35814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        bool allFetchersPrepared = true;
35914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
36014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                            if (!mFetcherInfos.valueAt(i).mIsPrepared) {
36114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                                allFetchersPrepared = false;
36214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                                break;
36314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                            }
36414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        }
36514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
36614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        if (allFetchersPrepared) {
36714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                            postPrepared(OK);
36814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        }
36914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    }
37014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    break;
37114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                }
37214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
3731543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                case PlaylistFetcher::kWhatStartedAt:
3741543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                {
3751543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    int32_t switchGeneration;
3761543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    CHECK(msg->findInt32("switchGeneration", &switchGeneration));
3771543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
3781543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    if (switchGeneration != mSwitchGeneration) {
3791543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        break;
3801543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    }
3811543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
3821543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    // Resume fetcher for the original variant; the resumed fetcher should
3831543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    // continue until the timestamps found in msg, which is stored by the
3841543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    // new fetcher to indicate where the new variant has started buffering.
3851543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    for (size_t i = 0; i < mFetcherInfos.size(); i++) {
3861543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        const FetcherInfo info = mFetcherInfos.valueAt(i);
3871543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        if (info.mToBeRemoved) {
3881543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                            info.mFetcher->resumeUntilAsync(msg);
3891543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        }
3901543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    }
3911543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    break;
3921543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                }
3931543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
39414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                default:
39514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    TRESPASS();
39614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            }
39714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
39814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            break;
39914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
40014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
40114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case kWhatCheckBandwidth:
402a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        {
403a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            int32_t generation;
404a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            CHECK(msg->findInt32("generation", &generation));
405a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
40614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            if (generation != mCheckBandwidthGeneration) {
407a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                break;
408a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            }
409a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
41014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            onCheckBandwidth();
411a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
412a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
413a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
414dcb89b3b505522efde173c105a851c412f947178Chong Zhang        case kWhatChangeConfiguration:
415dcb89b3b505522efde173c105a851c412f947178Chong Zhang        {
416dcb89b3b505522efde173c105a851c412f947178Chong Zhang            onChangeConfiguration(msg);
417dcb89b3b505522efde173c105a851c412f947178Chong Zhang            break;
418dcb89b3b505522efde173c105a851c412f947178Chong Zhang        }
419dcb89b3b505522efde173c105a851c412f947178Chong Zhang
42014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case kWhatChangeConfiguration2:
42114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
42214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            onChangeConfiguration2(msg);
42314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            break;
42414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
42514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
42614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case kWhatChangeConfiguration3:
42714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
42814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            onChangeConfiguration3(msg);
42914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            break;
43014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
43114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
43214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case kWhatFinishDisconnect2:
43314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
43414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            onFinishDisconnect2();
435a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
43614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
437a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
4381543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        case kWhatSwapped:
4391543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        {
4401543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            onSwapped(msg);
4411543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            break;
4421543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        }
443a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        default:
444a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            TRESPASS();
445a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
446a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
447a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
448a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
449a44153c1a57202fb538659eb50706e60454d6273Andreas Huber// static
450a44153c1a57202fb538659eb50706e60454d6273Andreas Huberint LiveSession::SortByBandwidth(const BandwidthItem *a, const BandwidthItem *b) {
451a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (a->mBandwidth < b->mBandwidth) {
452a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return -1;
453a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else if (a->mBandwidth == b->mBandwidth) {
454a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return 0;
455a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
456a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
457a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return 1;
458a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
459a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
4608ca002eedc747dd854b61cbe364b52c06869273fRobert Shih// static
4618ca002eedc747dd854b61cbe364b52c06869273fRobert ShihLiveSession::StreamType LiveSession::indexToType(int idx) {
4628ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    CHECK(idx >= 0 && idx < kMaxStreams);
4638ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    return (StreamType)(1 << idx);
4648ca002eedc747dd854b61cbe364b52c06869273fRobert Shih}
4658ca002eedc747dd854b61cbe364b52c06869273fRobert Shih
466a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onConnect(const sp<AMessage> &msg) {
467a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    AString url;
468a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    CHECK(msg->findString("url", &url));
469a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
470ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    KeyedVector<String8, String8> *headers = NULL;
471ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    if (!msg->findPointer("headers", (void **)&headers)) {
472ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        mExtraHeaders.clear();
473ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    } else {
474ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        mExtraHeaders = *headers;
475ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber
476ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        delete headers;
477ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        headers = NULL;
478ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    }
479ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber
480a1df816c0677185534babba6ffc29970b048e52eLajos Molnar    // TODO currently we don't know if we are coming here from incognito mode
481a1df816c0677185534babba6ffc29970b048e52eLajos Molnar    ALOGI("onConnect %s", uriDebugString(url).c_str());
482a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
483a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    mMasterURL = url;
484a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
4857e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    bool dummy;
48614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mPlaylist = fetchPlaylist(url.c_str(), NULL /* curPlaylistHash */, &dummy);
487ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
48814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (mPlaylist == NULL) {
489a1df816c0677185534babba6ffc29970b048e52eLajos Molnar        ALOGE("unable to fetch master playlist %s.", uriDebugString(url).c_str());
490ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
49114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        postPrepared(ERROR_IO);
492ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber        return;
493ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber    }
494a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
49514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // We trust the content provider to make a reasonable choice of preferred
49614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // initial bandwidth by listing it first in the variant playlist.
49714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // At startup we really don't have a good estimate on the available
49814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // network bandwidth since we haven't tranferred any data yet. Once
49914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // we have we can make a better informed choice.
50014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    size_t initialBandwidth = 0;
50114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    size_t initialBandwidthIndex = 0;
50214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
50314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (mPlaylist->isVariantPlaylist()) {
50414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        for (size_t i = 0; i < mPlaylist->size(); ++i) {
505a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            BandwidthItem item;
506a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
50714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            item.mPlaylistIndex = i;
50814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
509a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            sp<AMessage> meta;
51014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            AString uri;
51114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            mPlaylist->itemAt(i, &uri, &meta);
512a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
513a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            unsigned long bandwidth;
514a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            CHECK(meta->findInt32("bandwidth", (int32_t *)&item.mBandwidth));
515a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
51614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            if (initialBandwidth == 0) {
51714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                initialBandwidth = item.mBandwidth;
51814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            }
51914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
520a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            mBandwidthItems.push(item);
521a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
522a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
523a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        CHECK_GT(mBandwidthItems.size(), 0u);
524a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
525a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        mBandwidthItems.sort(SortByBandwidth);
52614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
52714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        for (size_t i = 0; i < mBandwidthItems.size(); ++i) {
52814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            if (mBandwidthItems.itemAt(i).mBandwidth == initialBandwidth) {
52914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                initialBandwidthIndex = i;
53014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                break;
53114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            }
53214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
53314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    } else {
53414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        // dummy item.
53514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        BandwidthItem item;
53614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        item.mPlaylistIndex = 0;
53714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        item.mBandwidth = 0;
53814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        mBandwidthItems.push(item);
539a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
540a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
541dcb89b3b505522efde173c105a851c412f947178Chong Zhang    changeConfiguration(
542dcb89b3b505522efde173c105a851c412f947178Chong Zhang            0ll /* timeUs */, initialBandwidthIndex, true /* pickTrack */);
543a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
544a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
54514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::finishDisconnect() {
54614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // No reconfiguration is currently pending, make sure none will trigger
54714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // during disconnection either.
54814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    cancelCheckBandwidthEvent();
54914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
5501543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // Protect mPacketSources from a swapPacketSource race condition through disconnect.
5511543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // (finishDisconnect, onFinishDisconnect2)
5521543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    cancelBandwidthSwitch();
5531543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
55414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
55514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        mFetcherInfos.valueAt(i).mFetcher->stopAsync();
55614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
55714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
55814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> msg = new AMessage(kWhatFinishDisconnect2, id());
559a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
56014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mContinuationCounter = mFetcherInfos.size();
56114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mContinuation = msg;
562ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
56314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (mContinuationCounter == 0) {
56414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        msg->post();
56514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
56614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
56714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
56814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::onFinishDisconnect2() {
56914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mContinuation.clear();
57014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
57114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mPacketSources.valueFor(STREAMTYPE_AUDIO)->signalEOS(ERROR_END_OF_STREAM);
57214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mPacketSources.valueFor(STREAMTYPE_VIDEO)->signalEOS(ERROR_END_OF_STREAM);
57314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
57414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mPacketSources.valueFor(
57514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            STREAMTYPE_SUBTITLES)->signalEOS(ERROR_END_OF_STREAM);
57614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
57714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> response = new AMessage;
57814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    response->setInt32("err", OK);
57914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
58014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    response->postReply(mDisconnectReplyID);
58114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mDisconnectReplyID = 0;
58214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
58314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
58414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubersp<PlaylistFetcher> LiveSession::addFetcher(const char *uri) {
58514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    ssize_t index = mFetcherInfos.indexOfKey(uri);
58614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
58714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (index >= 0) {
58814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        return NULL;
58914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
59014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
59114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> notify = new AMessage(kWhatFetcherNotify, id());
59214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->setString("uri", uri);
5931543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    notify->setInt32("switchGeneration", mSwitchGeneration);
59414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
59514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    FetcherInfo info;
59614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    info.mFetcher = new PlaylistFetcher(notify, this, uri);
59714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    info.mDurationUs = -1ll;
59814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    info.mIsPrepared = false;
5991543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    info.mToBeRemoved = false;
60014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    looper()->registerHandler(info.mFetcher);
60114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
60214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mFetcherInfos.add(uri, info);
60314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
60414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return info.mFetcher;
605a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
606a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
6078dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih/*
6088dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * Illustration of parameters:
6098dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih *
6108dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * 0      `range_offset`
6118dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * +------------+-------------------------------------------------------+--+--+
6128dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * |            |                                 | next block to fetch |  |  |
6138dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * |            | `source` handle => `out` buffer |                     |  |  |
6148dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * | `url` file |<--------- buffer size --------->|<--- `block_size` -->|  |  |
6158dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * |            |<----------- `range_length` / buffer capacity ----------->|  |
6168dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * |<------------------------------ file_size ------------------------------->|
6178dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih *
6188dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * Special parameter values:
6198dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * - range_length == -1 means entire file
6208dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * - block_size == 0 means entire range
6218dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih *
6228dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih */
62343ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shihssize_t LiveSession::fetchFile(
6242aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        const char *url, sp<ABuffer> *out,
6258dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        int64_t range_offset, int64_t range_length,
6268dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        uint32_t block_size, /* download block size */
62797194cdf8d67f362ef8c6dfdf607298c7e102b3bMarco Nelissen        sp<DataSource> *source, /* to return and reuse source */
628784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo        String8 *actualUrl) {
6298dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    off64_t size;
6308dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    sp<DataSource> temp_source;
6318dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    if (source == NULL) {
6328dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        source = &temp_source;
6338dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    }
634a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
6358dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    if (*source == NULL) {
6368dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        if (!strncasecmp(url, "file://", 7)) {
6378dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            *source = new FileSource(url + 7);
6388dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        } else if (strncasecmp(url, "http://", 7)
6398dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                && strncasecmp(url, "https://", 8)) {
6408dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            return ERROR_UNSUPPORTED;
6418dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        } else {
6428dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            KeyedVector<String8, String8> headers = mExtraHeaders;
6438dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            if (range_offset > 0 || range_length >= 0) {
6448dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                headers.add(
6458dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                        String8("Range"),
6468dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                        String8(
6478dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                            StringPrintf(
6488dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                                "bytes=%lld-%s",
6498dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                                range_offset,
6508dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                                range_length < 0
6518dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                                    ? "" : StringPrintf("%lld",
6528dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                                            range_offset + range_length - 1).c_str()).c_str()));
6538dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            }
6548dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            status_t err = mHTTPDataSource->connect(url, &headers);
655a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
6568dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            if (err != OK) {
6578dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                return err;
6588dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            }
659a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
6608dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            *source = mHTTPDataSource;
661a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
662a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
663a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
6648dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    status_t getSizeErr = (*source)->getSize(&size);
6658dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    if (getSizeErr != OK) {
666a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        size = 65536;
667a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
668a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
6698dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    sp<ABuffer> buffer = *out != NULL ? *out : new ABuffer(size);
6708dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    if (*out == NULL) {
6718dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        buffer->setRange(0, 0);
6728dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    }
673a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
67443ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih    ssize_t bytesRead = 0;
6758dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    // adjust range_length if only reading partial block
676b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross    if (block_size > 0 && (range_length == -1 || (int64_t)(buffer->size() + block_size) < range_length)) {
6778dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        range_length = buffer->size() + block_size;
6788dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    }
679a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    for (;;) {
6808dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        // Only resize when we don't know the size.
681a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        size_t bufferRemaining = buffer->capacity() - buffer->size();
6828dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        if (bufferRemaining == 0 && getSizeErr != OK) {
683a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            bufferRemaining = 32768;
684a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
685b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross            ALOGV("increasing download buffer to %zu bytes",
686a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                 buffer->size() + bufferRemaining);
687a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
688a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            sp<ABuffer> copy = new ABuffer(buffer->size() + bufferRemaining);
689a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            memcpy(copy->data(), buffer->data(), buffer->size());
690a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            copy->setRange(0, buffer->size());
691a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
692a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            buffer = copy;
693a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
694a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
6952aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        size_t maxBytesToRead = bufferRemaining;
6962aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        if (range_length >= 0) {
6972aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber            int64_t bytesLeftInRange = range_length - buffer->size();
698b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross            if (bytesLeftInRange < (int64_t)maxBytesToRead) {
6992aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                maxBytesToRead = bytesLeftInRange;
7002aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber
7012aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                if (bytesLeftInRange == 0) {
7022aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                    break;
7032aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                }
7042aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber            }
7052aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        }
7062aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber
7078dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        // The DataSource is responsible for informing us of error (n < 0) or eof (n == 0)
7088dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        // to help us break out of the loop.
7098dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        ssize_t n = (*source)->readAt(
710a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                buffer->size(), buffer->data() + buffer->size(),
7112aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                maxBytesToRead);
712a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
713a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (n < 0) {
71420ad3a341a96e7746015ccb7369fa567897e11f6Andreas Huber            return n;
715a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
716a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
717a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (n == 0) {
718a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
719a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
720a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
721a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        buffer->setRange(0, buffer->size() + (size_t)n);
72243ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih        bytesRead += n;
723a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
724a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
725a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    *out = buffer;
726784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo    if (actualUrl != NULL) {
72797194cdf8d67f362ef8c6dfdf607298c7e102b3bMarco Nelissen        *actualUrl = (*source)->getUri();
728784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo        if (actualUrl->isEmpty()) {
729784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo            *actualUrl = url;
730784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo        }
731784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo    }
732a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
73343ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih    return bytesRead;
734a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
735a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
73614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubersp<M3UParser> LiveSession::fetchPlaylist(
73714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        const char *url, uint8_t *curPlaylistHash, bool *unchanged) {
738b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber    ALOGV("fetchPlaylist '%s'", url);
739b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
7407e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    *unchanged = false;
7417e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
742a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<ABuffer> buffer;
743784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo    String8 actualUrl;
74443ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih    ssize_t  err = fetchFile(url, &buffer, 0, -1, 0, NULL, &actualUrl);
745a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
74643ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih    if (err <= 0) {
747a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return NULL;
748a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
749a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
7507e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    // MD5 functionality is not available on the simulator, treat all
7517e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    // playlists as changed.
7527e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
7537e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber#if defined(HAVE_ANDROID_OS)
7547e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    uint8_t hash[16];
7557e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
7567e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    MD5_CTX m;
7577e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    MD5_Init(&m);
7587e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    MD5_Update(&m, buffer->data(), buffer->size());
7597e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
7607e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    MD5_Final(hash, &m);
7617e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
76214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (curPlaylistHash != NULL && !memcmp(hash, curPlaylistHash, 16)) {
7637e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        // playlist unchanged
7647e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        *unchanged = true;
7657e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
7667e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        return NULL;
7677e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    }
7687e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
76914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (curPlaylistHash != NULL) {
77014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        memcpy(curPlaylistHash, hash, sizeof(hash));
77114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
7727e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber#endif
7737e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
774a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<M3UParser> playlist =
775784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo        new M3UParser(actualUrl.string(), buffer->data(), buffer->size());
776a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
777a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (playlist->initCheck() != OK) {
77829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("failed to parse .m3u8 playlist");
7799067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber
780a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return NULL;
781a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
782a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
783a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return playlist;
784a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
785a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
786a44153c1a57202fb538659eb50706e60454d6273Andreas Huberstatic double uniformRand() {
787a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return (double)rand() / RAND_MAX;
788a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
789a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
790a44153c1a57202fb538659eb50706e60454d6273Andreas Hubersize_t LiveSession::getBandwidthIndex() {
791a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (mBandwidthItems.size() == 0) {
792a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return 0;
793a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
794a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
795a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#if 1
796a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    char value[PROPERTY_VALUE_MAX];
797673158582c9589cee1d5e4d7c79622609938b8f8Andreas Huber    ssize_t index = -1;
79814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (property_get("media.httplive.bw-index", value, NULL)) {
799a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        char *end;
80014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        index = strtol(value, &end, 10);
80114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        CHECK(end > value && *end == '\0');
80214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
80314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (index >= 0 && (size_t)index >= mBandwidthItems.size()) {
80414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            index = mBandwidthItems.size() - 1;
805a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
806a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
807a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
80814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (index < 0) {
80914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        int32_t bandwidthBps;
81014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (mHTTPDataSource != NULL
81114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                && mHTTPDataSource->estimateBandwidth(&bandwidthBps)) {
81214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            ALOGV("bandwidth estimated at %.2f kbps", bandwidthBps / 1024.0f);
81314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        } else {
81414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            ALOGV("no bandwidth estimate.");
81514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            return 0;  // Pick the lowest bandwidth stream by default.
81614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
817a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
81814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        char value[PROPERTY_VALUE_MAX];
81914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (property_get("media.httplive.max-bw", value, NULL)) {
82014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            char *end;
82114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            long maxBw = strtoul(value, &end, 10);
82214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            if (end > value && *end == '\0') {
82314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                if (maxBw > 0 && bandwidthBps > maxBw) {
82414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    ALOGV("bandwidth capped to %ld bps", maxBw);
82514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    bandwidthBps = maxBw;
82614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                }
82714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            }
82814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
829a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
83014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        // Consider only 80% of the available bandwidth usable.
83114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        bandwidthBps = (bandwidthBps * 8) / 10;
83214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
83314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        // Pick the highest bandwidth stream below or equal to estimated bandwidth.
83414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
83514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        index = mBandwidthItems.size() - 1;
83614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        while (index > 0 && mBandwidthItems.itemAt(index).mBandwidth
83714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                                > (size_t)bandwidthBps) {
83814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            --index;
83914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
840a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
841a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0
842a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // Change bandwidth at random()
843a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index = uniformRand() * mBandwidthItems.size();
844a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0
845a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // There's a 50% chance to stay on the current bandwidth and
846a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // a 50% chance to switch to the next higher bandwidth (wrapping around
847a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // to lowest)
848a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    const size_t kMinIndex = 0;
849a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
85014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    static ssize_t mPrevBandwidthIndex = -1;
85114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
852a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index;
853a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (mPrevBandwidthIndex < 0) {
854a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        index = kMinIndex;
855a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else if (uniformRand() < 0.5) {
856a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        index = (size_t)mPrevBandwidthIndex;
857a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else {
858a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        index = mPrevBandwidthIndex + 1;
859a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (index == mBandwidthItems.size()) {
860a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            index = kMinIndex;
861a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
862a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
86314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mPrevBandwidthIndex = index;
864a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0
865a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // Pick the highest bandwidth stream below or equal to 1.2 Mbit/sec
866a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
867a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index = mBandwidthItems.size() - 1;
868a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    while (index > 0 && mBandwidthItems.itemAt(index).mBandwidth > 1200000) {
869a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        --index;
870a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
87114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#elif 1
87214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    char value[PROPERTY_VALUE_MAX];
87314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    size_t index;
87414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (property_get("media.httplive.bw-index", value, NULL)) {
87514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        char *end;
87614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        index = strtoul(value, &end, 10);
87714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        CHECK(end > value && *end == '\0');
87814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
87914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (index >= mBandwidthItems.size()) {
88014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            index = mBandwidthItems.size() - 1;
88114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
88214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    } else {
88314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        index = 0;
88414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
885a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#else
886a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index = mBandwidthItems.size() - 1;  // Highest bandwidth stream
887a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#endif
888a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
88914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK_GE(index, 0);
89014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
891a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return index;
892a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
893a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
89414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::onSeek(const sp<AMessage> &msg) {
89514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    int64_t timeUs;
89614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(msg->findInt64("timeUs", &timeUs));
8977e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
89814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (!mReconfigurationInProgress) {
89914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        changeConfiguration(timeUs, getBandwidthIndex());
9007e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    }
9017e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
90214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return OK;
9037e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber}
9047e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
90514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::getDuration(int64_t *durationUs) const {
90614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    int64_t maxDurationUs = 0ll;
90714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
90814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        int64_t fetcherDurationUs = mFetcherInfos.valueAt(i).mDurationUs;
909b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
91014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (fetcherDurationUs >= 0ll && fetcherDurationUs > maxDurationUs) {
91114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            maxDurationUs = fetcherDurationUs;
912a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
913a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
914a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
91514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    *durationUs = maxDurationUs;
916a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
91714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return OK;
91814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
9190f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber
92014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberbool LiveSession::isSeekable() const {
92114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    int64_t durationUs;
92214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return getDuration(&durationUs) == OK && durationUs >= 0;
92314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
9240f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber
92514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberbool LiveSession::hasDynamicDuration() const {
92614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return false;
92714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
9280f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber
929dcb89b3b505522efde173c105a851c412f947178Chong Zhangstatus_t LiveSession::getTrackInfo(Parcel *reply) const {
930dcb89b3b505522efde173c105a851c412f947178Chong Zhang    return mPlaylist->getTrackInfo(reply);
931dcb89b3b505522efde173c105a851c412f947178Chong Zhang}
932dcb89b3b505522efde173c105a851c412f947178Chong Zhang
933dcb89b3b505522efde173c105a851c412f947178Chong Zhangstatus_t LiveSession::selectTrack(size_t index, bool select) {
934dcb89b3b505522efde173c105a851c412f947178Chong Zhang    status_t err = mPlaylist->selectTrack(index, select);
935dcb89b3b505522efde173c105a851c412f947178Chong Zhang    if (err == OK) {
936dcb89b3b505522efde173c105a851c412f947178Chong Zhang        (new AMessage(kWhatChangeConfiguration, id()))->post();
937dcb89b3b505522efde173c105a851c412f947178Chong Zhang    }
938dcb89b3b505522efde173c105a851c412f947178Chong Zhang    return err;
939dcb89b3b505522efde173c105a851c412f947178Chong Zhang}
940dcb89b3b505522efde173c105a851c412f947178Chong Zhang
9411543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shihbool LiveSession::canSwitchUp() {
9421543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // Allow upwards bandwidth switch when a stream has buffered at least 10 seconds.
9431543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    status_t err = OK;
9441543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    for (size_t i = 0; i < mPacketSources.size(); ++i) {
9451543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        sp<AnotherPacketSource> source = mPacketSources.valueAt(i);
9461543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        int64_t dur = source->getBufferedDurationUs(&err);
9471543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        if (err == OK && dur > 10000000) {
9481543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            return true;
9491543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        }
9501543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
9511543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    return false;
9521543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
9531543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
954dcb89b3b505522efde173c105a851c412f947178Chong Zhangvoid LiveSession::changeConfiguration(
955dcb89b3b505522efde173c105a851c412f947178Chong Zhang        int64_t timeUs, size_t bandwidthIndex, bool pickTrack) {
9561543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // Protect mPacketSources from a swapPacketSource race condition through reconfiguration.
9571543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // (changeConfiguration, onChangeConfiguration2, onChangeConfiguration3).
9581543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    cancelBandwidthSwitch();
9591543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
96014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(!mReconfigurationInProgress);
96114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mReconfigurationInProgress = true;
962a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
96314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mPrevBandwidthIndex = bandwidthIndex;
96443c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
965b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross    ALOGV("changeConfiguration => timeUs:%" PRId64 " us, bwIndex:%zu, pickTrack:%d",
966dcb89b3b505522efde173c105a851c412f947178Chong Zhang          timeUs, bandwidthIndex, pickTrack);
96743c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
968dcb89b3b505522efde173c105a851c412f947178Chong Zhang    if (pickTrack) {
969dcb89b3b505522efde173c105a851c412f947178Chong Zhang        mPlaylist->pickRandomMediaItems();
970dcb89b3b505522efde173c105a851c412f947178Chong Zhang    }
97143c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
97214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK_LT(bandwidthIndex, mBandwidthItems.size());
97314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    const BandwidthItem &item = mBandwidthItems.itemAt(bandwidthIndex);
974a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
9751543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    uint32_t streamMask = 0; // streams that should be fetched by the new fetcher
9761543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    uint32_t resumeMask = 0; // streams that should be fetched by the original fetcher
977a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
9788ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    AString URIs[kMaxStreams];
9798ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
9808ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        if (mPlaylist->getTypeURI(item.mPlaylistIndex, mStreams[i].mType, &URIs[i])) {
9818ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            streamMask |= indexToType(i);
9828ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        }
98314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
984aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber
98514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Step 1, stop and discard fetchers that are no longer needed.
98614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Pause those that we'll reuse.
98714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
98814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        const AString &uri = mFetcherInfos.keyAt(i);
989aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber
99014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        bool discardFetcher = true;
991aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber
99214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        // If we're seeking all current fetchers are discarded.
99314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (timeUs < 0ll) {
9941543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            // delay fetcher removal
9951543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            discardFetcher = false;
9961543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
9978ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            for (size_t j = 0; j < kMaxStreams; ++j) {
9981543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                StreamType type = indexToType(j);
9991543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                if ((streamMask & type) && uri == URIs[j]) {
10001543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    resumeMask |= type;
10011543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    streamMask &= ~type;
10028ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                }
10036801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber            }
100414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
1005a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
100614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (discardFetcher) {
100714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            mFetcherInfos.valueAt(i).mFetcher->stopAsync();
10086801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber        } else {
100914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            mFetcherInfos.valueAt(i).mFetcher->pauseAsync();
10106801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber        }
1011a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1012a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
10131543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    sp<AMessage> msg;
10141543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    if (timeUs < 0ll) {
10151543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        // skip onChangeConfiguration2 (decoder destruction) if switching.
10161543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        msg = new AMessage(kWhatChangeConfiguration3, id());
10171543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    } else {
10181543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        msg = new AMessage(kWhatChangeConfiguration2, id());
10191543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
102014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    msg->setInt32("streamMask", streamMask);
10211543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    msg->setInt32("resumeMask", resumeMask);
102214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    msg->setInt64("timeUs", timeUs);
10238ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
10248ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        if (streamMask & indexToType(i)) {
10258ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            msg->setString(mStreams[i].uriKey().c_str(), URIs[i].c_str());
10268ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        }
10276e6b1cae2bac1b78205cefab8e4e9e9538982965Andreas Huber    }
1028a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
102914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Every time a fetcher acknowledges the stopAsync or pauseAsync request
103014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // we'll decrement mContinuationCounter, once it reaches zero, i.e. all
103114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // fetchers have completed their asynchronous operation, we'll post
103214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // mContinuation, which then is handled below in onChangeConfiguration2.
103314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mContinuationCounter = mFetcherInfos.size();
103414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mContinuation = msg;
103588b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber
103614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (mContinuationCounter == 0) {
103714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        msg->post();
10385ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih
10395ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih        if (mSeekReplyID != 0) {
10405ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih            CHECK(mSeekReply != NULL);
10415ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih            mSeekReply->postReply(mSeekReplyID);
10425ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih        }
104388b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber    }
104414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
1045a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1046dcb89b3b505522efde173c105a851c412f947178Chong Zhangvoid LiveSession::onChangeConfiguration(const sp<AMessage> &msg) {
1047dcb89b3b505522efde173c105a851c412f947178Chong Zhang    if (!mReconfigurationInProgress) {
1048dcb89b3b505522efde173c105a851c412f947178Chong Zhang        changeConfiguration(-1ll /* timeUs */, getBandwidthIndex());
1049dcb89b3b505522efde173c105a851c412f947178Chong Zhang    } else {
1050dcb89b3b505522efde173c105a851c412f947178Chong Zhang        msg->post(1000000ll); // retry in 1 sec
1051dcb89b3b505522efde173c105a851c412f947178Chong Zhang    }
1052dcb89b3b505522efde173c105a851c412f947178Chong Zhang}
1053dcb89b3b505522efde173c105a851c412f947178Chong Zhang
105414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::onChangeConfiguration2(const sp<AMessage> &msg) {
105514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mContinuation.clear();
1056bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
105714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // All fetchers are either suspended or have been removed now.
1058bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
105914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    uint32_t streamMask;
106014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(msg->findInt32("streamMask", (int32_t *)&streamMask));
1061bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
10628ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    AString URIs[kMaxStreams];
10638ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
10648ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        if (streamMask & indexToType(i)) {
10658ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            const AString &uriKey = mStreams[i].uriKey();
10668ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            CHECK(msg->findString(uriKey.c_str(), &URIs[i]));
10678ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            ALOGV("%s = '%s'", uriKey.c_str(), URIs[i].c_str());
10688ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        }
106922fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber    }
10703831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber
107114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Determine which decoders to shutdown on the player side,
107214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // a decoder has to be shutdown if either
107314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // 1) its streamtype was active before but now longer isn't.
107414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // or
107514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // 2) its streamtype was already active and still is but the URI
107614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    //    has changed.
107714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    uint32_t changedMask = 0;
10788ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams && i != kSubtitleIndex; ++i) {
10798ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        if (((mStreamMask & streamMask & indexToType(i))
10808ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                && !(URIs[i] == mStreams[i].mUri))
10818ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                || (mStreamMask & ~streamMask & indexToType(i))) {
10828ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            changedMask |= indexToType(i);
10838ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        }
1084b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber    }
1085b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
108614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (changedMask == 0) {
108714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        // If nothing changed as far as the audio/video decoders
108814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        // are concerned we can proceed.
108914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        onChangeConfiguration3(msg);
109014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        return;
109114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
109243c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
109314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Something changed, inform the player which will shutdown the
109414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // corresponding decoders and will post the reply once that's done.
109514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Handling the reply will continue executing below in
109614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // onChangeConfiguration3.
109714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> notify = mNotify->dup();
109814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->setInt32("what", kWhatStreamsChanged);
109914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->setInt32("changedMask", changedMask);
110020f725ebcef13ded1b4b85c61c8a4b37cd030656Andreas Huber
110114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    msg->setWhat(kWhatChangeConfiguration3);
110214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    msg->setTarget(id());
1103b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
110414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->setMessage("reply", msg);
110514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->post();
110614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
1107b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
110814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::onChangeConfiguration3(const sp<AMessage> &msg) {
11091543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    mContinuation.clear();
111014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // All remaining fetchers are still suspended, the player has shutdown
111114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // any decoders that needed it.
1112b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
11131543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    uint32_t streamMask, resumeMask;
111414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(msg->findInt32("streamMask", (int32_t *)&streamMask));
11151543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    CHECK(msg->findInt32("resumeMask", (int32_t *)&resumeMask));
1116a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
11178ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
11188ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        if (streamMask & indexToType(i)) {
11198ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            CHECK(msg->findString(mStreams[i].uriKey().c_str(), &mStreams[i].mUri));
11208ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        }
1121a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1122a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
112314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    int64_t timeUs;
11241543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    bool switching = false;
112514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(msg->findInt64("timeUs", &timeUs));
1126a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
112714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (timeUs < 0ll) {
112814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        timeUs = mLastDequeuedTimeUs;
11291543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        switching = true;
113014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
1131dcb89b3b505522efde173c105a851c412f947178Chong Zhang    mRealTimeBaseUs = ALooper::GetNowUs() - timeUs;
1132a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
11331543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    mNewStreamMask = streamMask;
1134a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
11351543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // Of all existing fetchers:
11361543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // * Resume fetchers that are still needed and assign them original packet sources.
11371543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // * Mark otherwise unneeded fetchers for removal.
11381543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    ALOGV("resuming fetchers for mask 0x%08x", resumeMask);
113914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
114014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        const AString &uri = mFetcherInfos.keyAt(i);
11410df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas Huber
11428ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        sp<AnotherPacketSource> sources[kMaxStreams];
1143dc793ce8c0ead27ab43e40ce09f27fe338323502Robert Shih        for (size_t j = 0; j < kMaxStreams; ++j) {
11441543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            if ((resumeMask & indexToType(j)) && uri == mStreams[j].mUri) {
11458ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                sources[j] = mPacketSources.valueFor(indexToType(j));
11468ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            }
114714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
1148a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
11491543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        FetcherInfo &info = mFetcherInfos.editValueAt(i);
11501543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        if (sources[kAudioIndex] != NULL || sources[kVideoIndex] != NULL
11511543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                || sources[kSubtitleIndex] != NULL) {
11521543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            info.mFetcher->startAsync(
11531543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    sources[kAudioIndex], sources[kVideoIndex], sources[kSubtitleIndex]);
11541543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        } else {
11551543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            info.mToBeRemoved = true;
11561543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        }
1157a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1158a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
115914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // streamMask now only contains the types that need a new fetcher created.
1160a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
116114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (streamMask != 0) {
116214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        ALOGV("creating new fetchers for mask 0x%08x", streamMask);
1163a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1164a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
11651543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // Find out when the original fetchers have buffered up to and start the new fetchers
11661543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // at a later timestamp.
11678ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams; i++) {
11688ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        if (!(indexToType(i) & streamMask)) {
11698ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            continue;
11708ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        }
11711156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
117214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        AString uri;
11738ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        uri = mStreams[i].mUri;
11749b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber
117514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        sp<PlaylistFetcher> fetcher = addFetcher(uri.c_str());
117614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        CHECK(fetcher != NULL);
1177a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
11781543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        int32_t latestSeq = -1;
11791543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        int64_t latestTimeUs = 0ll;
11808ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        sp<AnotherPacketSource> sources[kMaxStreams];
11811543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
11828ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        // TRICKY: looping from i as earlier streams are already removed from streamMask
11838ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        for (size_t j = i; j < kMaxStreams; ++j) {
11848ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            if ((streamMask & indexToType(j)) && uri == mStreams[j].mUri) {
11858ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                sources[j] = mPacketSources.valueFor(indexToType(j));
11861543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
11871543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                if (!switching) {
11881543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    sources[j]->clear();
11891543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                } else {
11901543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    int32_t type, seq;
11911543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    int64_t srcTimeUs;
11921543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    sp<AMessage> meta = sources[j]->getLatestMeta();
11931543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
11941543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    if (meta != NULL && !meta->findInt32("discontinuity", &type)) {
11951543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        CHECK(meta->findInt32("seq", &seq));
11961543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        if (seq > latestSeq) {
11971543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                            latestSeq = seq;
11981543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        }
11991543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        CHECK(meta->findInt64("timeUs", &srcTimeUs));
12001543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        if (srcTimeUs > latestTimeUs) {
12011543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                            latestTimeUs = srcTimeUs;
12021543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        }
12031543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    }
12041543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
12051543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    sources[j] = mPacketSources2.valueFor(indexToType(j));
12061543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    sources[j]->clear();
12071543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    uint32_t extraStreams = mNewStreamMask & (~mStreamMask);
12081543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    if (extraStreams & indexToType(j)) {
12091543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        sources[j]->queueAccessUnit(createFormatChangeBuffer(/* swap = */ false));
12101543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    }
12111543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                }
1212a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
12138ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                streamMask &= ~indexToType(j);
12148ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            }
1215a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
121614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
12178ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        fetcher->startAsync(
12188ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                sources[kAudioIndex],
12198ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                sources[kVideoIndex],
12208ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                sources[kSubtitleIndex],
12211543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                timeUs,
12221543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                latestTimeUs /* min start time(us) */,
12231543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                latestSeq >= 0 ? latestSeq + 1 : -1 /* starting sequence number hint */ );
1224a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1225a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
122614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // All fetchers have now been started, the configuration change
122714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // has completed.
1228a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
122914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    scheduleCheckBandwidthEvent();
1230a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
123114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    ALOGV("XXX configuration change completed.");
123214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mReconfigurationInProgress = false;
12331543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    if (switching) {
12341543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        mSwitchInProgress = true;
12351543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    } else {
12361543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        mStreamMask = mNewStreamMask;
12371543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
1238a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
123914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (mDisconnectReplyID != 0) {
124014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        finishDisconnect();
1241a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
124214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
1243a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
12441543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shihvoid LiveSession::onSwapped(const sp<AMessage> &msg) {
12451543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    int32_t switchGeneration;
12461543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    CHECK(msg->findInt32("switchGeneration", &switchGeneration));
12471543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    if (switchGeneration != mSwitchGeneration) {
12481543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return;
12491543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
12501543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
12511543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    int32_t stream;
12521543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    CHECK(msg->findInt32("stream", &stream));
12531543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    mSwapMask |= stream;
12541543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    if (mSwapMask != mStreamMask) {
12551543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return;
12561543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
12571543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
12581543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // Check if new variant contains extra streams.
12591543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    uint32_t extraStreams = mNewStreamMask & (~mStreamMask);
12601543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    while (extraStreams) {
12611543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        StreamType extraStream = (StreamType) (extraStreams & ~(extraStreams - 1));
12621543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        swapPacketSource(extraStream);
12631543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        extraStreams &= ~extraStream;
12641543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
12651543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
12661543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    tryToFinishBandwidthSwitch();
12671543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
12681543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
12691543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih// Mark switch done when:
12701543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih//   1. all old buffers are swapped out, AND
12711543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih//   2. all old fetchers are removed.
12721543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shihvoid LiveSession::tryToFinishBandwidthSwitch() {
12731543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    bool needToRemoveFetchers = false;
12741543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
12751543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        if (mFetcherInfos.valueAt(i).mToBeRemoved) {
12761543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            needToRemoveFetchers = true;
12771543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            break;
12781543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        }
12791543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
12801543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    if (!needToRemoveFetchers && mSwapMask == mStreamMask) {
12811543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        mStreamMask = mNewStreamMask;
12821543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        mSwitchInProgress = false;
12831543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        mSwapMask = 0;
12841543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
12851543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
12861543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
128714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::scheduleCheckBandwidthEvent() {
128814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> msg = new AMessage(kWhatCheckBandwidth, id());
128914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    msg->setInt32("generation", mCheckBandwidthGeneration);
129014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    msg->post(10000000ll);
1291a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
1292a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
129314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::cancelCheckBandwidthEvent() {
129414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    ++mCheckBandwidthGeneration;
1295a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
1296a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
12971543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shihvoid LiveSession::cancelBandwidthSwitch() {
12981543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    Mutex::Autolock lock(mSwapMutex);
12991543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    mSwitchGeneration++;
13001543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    mSwitchInProgress = false;
13011543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    mSwapMask = 0;
13021543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
13031543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
13041543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shihbool LiveSession::canSwitchBandwidthTo(size_t bandwidthIndex) {
13051543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    if (mReconfigurationInProgress || mSwitchInProgress) {
13061543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return false;
13071543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
13081543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
13091543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    if (mPrevBandwidthIndex < 0) {
13101543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return true;
131114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
131214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
13131543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    if (bandwidthIndex == (size_t)mPrevBandwidthIndex) {
13141543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return false;
13151543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    } else if (bandwidthIndex > (size_t)mPrevBandwidthIndex) {
13161543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return canSwitchUp();
13171543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    } else {
13181543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return true;
13191543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
13201543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
13211543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
13221543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shihvoid LiveSession::onCheckBandwidth() {
132314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    size_t bandwidthIndex = getBandwidthIndex();
13241543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    if (canSwitchBandwidthTo(bandwidthIndex)) {
132514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        changeConfiguration(-1ll /* timeUs */, bandwidthIndex);
13261543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    } else {
13271543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        scheduleCheckBandwidthEvent();
132814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
1329a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
133014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Handling the kWhatCheckBandwidth even here does _not_ automatically
133114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // schedule another one on return, only an explicit call to
133214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // scheduleCheckBandwidthEvent will do that.
133314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // This ensures that only one configuration change is ongoing at any
133414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // one time, once that completes it'll schedule another check bandwidth
133514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // event.
1336a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
1337a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
133814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::postPrepared(status_t err) {
133914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(mInPreparationPhase);
1340a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
134114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> notify = mNotify->dup();
134214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (err == OK || err == ERROR_END_OF_STREAM) {
134314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        notify->setInt32("what", kWhatPrepared);
134414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    } else {
134514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        notify->setInt32("what", kWhatPreparationFailed);
134614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        notify->setInt32("err", err);
134714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
1348a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
134914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->post();
1350a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
135114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mInPreparationPhase = false;
1352b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber}
1353b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
1354a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}  // namespace android
1355a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1356