LiveSession.cpp revision c4547ba77f78632172db3647a09659d9863d3b5c
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
52964adb17885185808398507d2de88665fe193ee2Chong Zhang// static
53a93fd2be99d21629bed504b9b7df035fc2f54562Leena Winterrowd// Number of recently-read bytes to use for bandwidth estimation
54a93fd2be99d21629bed504b9b7df035fc2f54562Leena Winterrowdconst size_t LiveSession::kBandwidthHistoryBytes = 200 * 1024;
55964adb17885185808398507d2de88665fe193ee2Chong Zhang// High water mark to start up switch or report prepared)
56964adb17885185808398507d2de88665fe193ee2Chong Zhangconst int64_t LiveSession::kHighWaterMark = 8000000ll;
57964adb17885185808398507d2de88665fe193ee2Chong Zhangconst int64_t LiveSession::kMidWaterMark = 5000000ll;
58964adb17885185808398507d2de88665fe193ee2Chong Zhangconst int64_t LiveSession::kLowWaterMark = 3000000ll;
59a93fd2be99d21629bed504b9b7df035fc2f54562Leena Winterrowd
600df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas HuberLiveSession::LiveSession(
611b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        const sp<AMessage> &notify, uint32_t flags,
6281e68448f3361eaf8618930471fdc3c21bdf5cbcAndreas Huber        const sp<IMediaHTTPService> &httpService)
630df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas Huber    : mNotify(notify),
640df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas Huber      mFlags(flags),
651b86fe063badb5f28c467ade39be0f4008688947Andreas Huber      mHTTPService(httpService),
660df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas Huber      mInPreparationPhase(true),
671b86fe063badb5f28c467ade39be0f4008688947Andreas Huber      mHTTPDataSource(new MediaHTTP(mHTTPService->makeHTTPConnection())),
68309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih      mCurBandwidthIndex(-1),
6914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber      mStreamMask(0),
701543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih      mNewStreamMask(0),
711543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih      mSwapMask(0),
7214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber      mCheckBandwidthGeneration(0),
731543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih      mSwitchGeneration(0),
74b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih      mSubtitleGeneration(0),
7514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber      mLastDequeuedTimeUs(0ll),
76dcb89b3b505522efde173c105a851c412f947178Chong Zhang      mRealTimeBaseUs(0ll),
7714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber      mReconfigurationInProgress(false),
781543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih      mSwitchInProgress(false),
79309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih      mFirstTimeUsValid(false),
80309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih      mFirstTimeUs(0),
81964adb17885185808398507d2de88665fe193ee2Chong Zhang      mLastSeekTimeUs(0),
82964adb17885185808398507d2de88665fe193ee2Chong Zhang      mPollBufferingGeneration(0) {
8314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
848ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    mStreams[kAudioIndex] = StreamItem("audio");
858ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    mStreams[kVideoIndex] = StreamItem("video");
86e4f25c280a8f1655c31a745978e0fcbc61f91deeRobert Shih    mStreams[kSubtitleIndex] = StreamItem("subtitles");
8714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
888ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
898ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        mPacketSources.add(indexToType(i), new AnotherPacketSource(NULL /* meta */));
901543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        mPacketSources2.add(indexToType(i), new AnotherPacketSource(NULL /* meta */));
918ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    }
92a93fd2be99d21629bed504b9b7df035fc2f54562Leena Winterrowd
93a93fd2be99d21629bed504b9b7df035fc2f54562Leena Winterrowd    size_t numHistoryItems = kBandwidthHistoryBytes /
94a93fd2be99d21629bed504b9b7df035fc2f54562Leena Winterrowd            PlaylistFetcher::kDownloadBlockSize + 1;
95a93fd2be99d21629bed504b9b7df035fc2f54562Leena Winterrowd    if (numHistoryItems < 5) {
96a93fd2be99d21629bed504b9b7df035fc2f54562Leena Winterrowd        numHistoryItems = 5;
97a93fd2be99d21629bed504b9b7df035fc2f54562Leena Winterrowd    }
98a93fd2be99d21629bed504b9b7df035fc2f54562Leena Winterrowd    mHTTPDataSource->setBandwidthHistorySize(numHistoryItems);
99a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
100a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
101a44153c1a57202fb538659eb50706e60454d6273Andreas HuberLiveSession::~LiveSession() {
102964adb17885185808398507d2de88665fe193ee2Chong Zhang    if (mFetcherLooper != NULL) {
103964adb17885185808398507d2de88665fe193ee2Chong Zhang        mFetcherLooper->stop();
104964adb17885185808398507d2de88665fe193ee2Chong Zhang    }
105a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
106a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1071543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shihsp<ABuffer> LiveSession::createFormatChangeBuffer(bool swap) {
1081543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    ABuffer *discontinuity = new ABuffer(0);
1091543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    discontinuity->meta()->setInt32("discontinuity", ATSParser::DISCONTINUITY_FORMATCHANGE);
1101543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    discontinuity->meta()->setInt32("swapPacketSource", swap);
1111543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    discontinuity->meta()->setInt32("switchGeneration", mSwitchGeneration);
1121543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    discontinuity->meta()->setInt64("timeUs", -1);
1131543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    return discontinuity;
1141543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
1151543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
1161543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shihvoid LiveSession::swapPacketSource(StreamType stream) {
1171543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    sp<AnotherPacketSource> &aps = mPacketSources.editValueFor(stream);
1181543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    sp<AnotherPacketSource> &aps2 = mPacketSources2.editValueFor(stream);
1191543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    sp<AnotherPacketSource> tmp = aps;
1201543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    aps = aps2;
1211543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    aps2 = tmp;
1221543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    aps2->clear();
1231543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
1241543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
12514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::dequeueAccessUnit(
12614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        StreamType stream, sp<ABuffer> *accessUnit) {
12714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (!(mStreamMask & stream)) {
1281543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        // return -EWOULDBLOCK to avoid halting the decoder
1291543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        // when switching between audio/video and audio only.
1301543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return -EWOULDBLOCK;
13114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
13214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
133964adb17885185808398507d2de88665fe193ee2Chong Zhang    status_t finalResult = OK;
13414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AnotherPacketSource> packetSource = mPacketSources.valueFor(stream);
13514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
136f69c996864844e8f669308af8412cede043062a2Robert Shih    ssize_t idx = typeToIndex(stream);
13714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (!packetSource->hasBufferAvailable(&finalResult)) {
138f69c996864844e8f669308af8412cede043062a2Robert Shih        if (finalResult == OK) {
139f69c996864844e8f669308af8412cede043062a2Robert Shih            return -EAGAIN;
140f69c996864844e8f669308af8412cede043062a2Robert Shih        } else {
141f69c996864844e8f669308af8412cede043062a2Robert Shih            return finalResult;
142f69c996864844e8f669308af8412cede043062a2Robert Shih        }
143f69c996864844e8f669308af8412cede043062a2Robert Shih    }
144f69c996864844e8f669308af8412cede043062a2Robert Shih
145c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang    // Do not let client pull data if we don't have format yet.
146c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang    // We might only have a format discontinuity queued without actual data.
147c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang    // When NuPlayerDecoder dequeues the format discontinuity, it will
148c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang    // immediately try to getFormat. If we return NULL, NuPlayerDecoder
149c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang    // thinks it can do seamless change, so will not shutdown decoder.
150c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang    // When the actual format arrives, it can't handle it and get stuck.
151c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang    // TODO: We need a method to check if the packet source has any
152c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang    //       data packets available, dequeuing should only start then.
153c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang    sp<MetaData> format = packetSource->getFormat();
154c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang    if (format == NULL) {
155c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        return -EAGAIN;
156c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang    }
157174609765fb9c8cbd6aeb61f489746c3570bfee2Leena Winterrowd    int32_t targetDuration = 0;
158174609765fb9c8cbd6aeb61f489746c3570bfee2Leena Winterrowd    sp<AMessage> meta = packetSource->getLatestEnqueuedMeta();
159174609765fb9c8cbd6aeb61f489746c3570bfee2Leena Winterrowd    if (meta != NULL) {
160174609765fb9c8cbd6aeb61f489746c3570bfee2Leena Winterrowd        meta->findInt32("targetDuration", &targetDuration);
161174609765fb9c8cbd6aeb61f489746c3570bfee2Leena Winterrowd    }
162174609765fb9c8cbd6aeb61f489746c3570bfee2Leena Winterrowd
163174609765fb9c8cbd6aeb61f489746c3570bfee2Leena Winterrowd    int64_t targetDurationUs = targetDuration * 1000000ll;
164174609765fb9c8cbd6aeb61f489746c3570bfee2Leena Winterrowd    if (targetDurationUs == 0 ||
165174609765fb9c8cbd6aeb61f489746c3570bfee2Leena Winterrowd            targetDurationUs > PlaylistFetcher::kMinBufferedDurationUs) {
166174609765fb9c8cbd6aeb61f489746c3570bfee2Leena Winterrowd        // Fetchers limit buffering to
167174609765fb9c8cbd6aeb61f489746c3570bfee2Leena Winterrowd        // min(3 * targetDuration, kMinBufferedDurationUs)
168174609765fb9c8cbd6aeb61f489746c3570bfee2Leena Winterrowd        targetDurationUs = PlaylistFetcher::kMinBufferedDurationUs;
169174609765fb9c8cbd6aeb61f489746c3570bfee2Leena Winterrowd    }
170174609765fb9c8cbd6aeb61f489746c3570bfee2Leena Winterrowd
171309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    // wait for counterpart
172309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    sp<AnotherPacketSource> otherSource;
17373d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih    uint32_t mask = mNewStreamMask & mStreamMask;
17473d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih    uint32_t fetchersMask  = 0;
17573d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
17673d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih        uint32_t fetcherMask = mFetcherInfos.valueAt(i).mFetcher->getStreamTypeMask();
17773d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih        fetchersMask |= fetcherMask;
17873d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih    }
17973d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih    mask &= fetchersMask;
18073d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih    if (stream == STREAMTYPE_AUDIO && (mask & STREAMTYPE_VIDEO)) {
181309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        otherSource = mPacketSources.valueFor(STREAMTYPE_VIDEO);
18273d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih    } else if (stream == STREAMTYPE_VIDEO && (mask & STREAMTYPE_AUDIO)) {
183309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        otherSource = mPacketSources.valueFor(STREAMTYPE_AUDIO);
184309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    }
185309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    if (otherSource != NULL && !otherSource->hasBufferAvailable(&finalResult)) {
186309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        return finalResult == OK ? -EAGAIN : finalResult;
187309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    }
188309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
18914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    status_t err = packetSource->dequeueAccessUnit(accessUnit);
19014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
191309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    size_t streamIdx;
19214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    const char *streamStr;
19314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    switch (stream) {
19414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case STREAMTYPE_AUDIO:
195309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            streamIdx = kAudioIndex;
19614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            streamStr = "audio";
19714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            break;
19814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case STREAMTYPE_VIDEO:
199309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            streamIdx = kVideoIndex;
20014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            streamStr = "video";
20114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            break;
20214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case STREAMTYPE_SUBTITLES:
203309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            streamIdx = kSubtitleIndex;
20414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            streamStr = "subs";
20514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            break;
20614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        default:
20714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            TRESPASS();
20814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
20914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
210309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    StreamItem& strm = mStreams[streamIdx];
21114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (err == INFO_DISCONTINUITY) {
212309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        // adaptive streaming, discontinuities in the playlist
21314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        int32_t type;
21414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        CHECK((*accessUnit)->meta()->findInt32("discontinuity", &type));
21514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
21614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        sp<AMessage> extra;
21714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (!(*accessUnit)->meta()->findMessage("extra", &extra)) {
21814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            extra.clear();
21914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
22014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
22114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        ALOGI("[%s] read discontinuity of type %d, extra = %s",
22214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber              streamStr,
22314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber              type,
22414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber              extra == NULL ? "NULL" : extra->debugString().c_str());
2251543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
2261543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        int32_t swap;
227309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        if ((*accessUnit)->meta()->findInt32("swapPacketSource", &swap) && swap) {
2281543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            int32_t switchGeneration;
2291543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            CHECK((*accessUnit)->meta()->findInt32("switchGeneration", &switchGeneration));
2301543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            {
2311543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                Mutex::Autolock lock(mSwapMutex);
2321543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                if (switchGeneration == mSwitchGeneration) {
2331543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    swapPacketSource(stream);
2341d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar                    sp<AMessage> msg = new AMessage(kWhatSwapped, this);
2351543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    msg->setInt32("stream", stream);
2361543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    msg->setInt32("switchGeneration", switchGeneration);
2371543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    msg->post();
2381543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                }
2391543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            }
240309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        } else {
241309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            size_t seq = strm.mCurDiscontinuitySeq;
242309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            int64_t offsetTimeUs;
243309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            if (mDiscontinuityOffsetTimesUs.indexOfKey(seq) >= 0) {
244309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                offsetTimeUs = mDiscontinuityOffsetTimesUs.valueFor(seq);
245309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            } else {
246309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                offsetTimeUs = 0;
247309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            }
248309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
249309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            seq += 1;
250309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            if (mDiscontinuityAbsStartTimesUs.indexOfKey(strm.mCurDiscontinuitySeq) >= 0) {
251309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                int64_t firstTimeUs;
252309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                firstTimeUs = mDiscontinuityAbsStartTimesUs.valueFor(strm.mCurDiscontinuitySeq);
253309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                offsetTimeUs += strm.mLastDequeuedTimeUs - firstTimeUs;
254309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                offsetTimeUs += strm.mLastSampleDurationUs;
255309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            } else {
256309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                offsetTimeUs += strm.mLastSampleDurationUs;
257309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            }
258309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
259309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            mDiscontinuityOffsetTimesUs.add(seq, offsetTimeUs);
2601543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        }
26114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    } else if (err == OK) {
262309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
263dcb89b3b505522efde173c105a851c412f947178Chong Zhang        if (stream == STREAMTYPE_AUDIO || stream == STREAMTYPE_VIDEO) {
264dcb89b3b505522efde173c105a851c412f947178Chong Zhang            int64_t timeUs;
265309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            int32_t discontinuitySeq = 0;
266dcb89b3b505522efde173c105a851c412f947178Chong Zhang            CHECK((*accessUnit)->meta()->findInt64("timeUs",  &timeUs));
267309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            (*accessUnit)->meta()->findInt32("discontinuitySeq", &discontinuitySeq);
268309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            strm.mCurDiscontinuitySeq = discontinuitySeq;
269309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
270309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            int32_t discard = 0;
271309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            int64_t firstTimeUs;
272309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            if (mDiscontinuityAbsStartTimesUs.indexOfKey(strm.mCurDiscontinuitySeq) >= 0) {
273309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                int64_t durUs; // approximate sample duration
274309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                if (timeUs > strm.mLastDequeuedTimeUs) {
275309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    durUs = timeUs - strm.mLastDequeuedTimeUs;
276309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                } else {
277309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    durUs = strm.mLastDequeuedTimeUs - timeUs;
278309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                }
279309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                strm.mLastSampleDurationUs = durUs;
280309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                firstTimeUs = mDiscontinuityAbsStartTimesUs.valueFor(strm.mCurDiscontinuitySeq);
281309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            } else if ((*accessUnit)->meta()->findInt32("discard", &discard) && discard) {
282309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                firstTimeUs = timeUs;
283309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            } else {
284309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                mDiscontinuityAbsStartTimesUs.add(strm.mCurDiscontinuitySeq, timeUs);
285309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                firstTimeUs = timeUs;
286309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            }
287309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
288309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            strm.mLastDequeuedTimeUs = timeUs;
289309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            if (timeUs >= firstTimeUs) {
290309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                timeUs -= firstTimeUs;
291309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            } else {
292309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                timeUs = 0;
293309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            }
294309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            timeUs += mLastSeekTimeUs;
295309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            if (mDiscontinuityOffsetTimesUs.indexOfKey(discontinuitySeq) >= 0) {
296309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                timeUs += mDiscontinuityOffsetTimesUs.valueFor(discontinuitySeq);
297309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            }
298dcb89b3b505522efde173c105a851c412f947178Chong Zhang
299309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            ALOGV("[%s] read buffer at time %" PRId64 " us", streamStr, timeUs);
300309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            (*accessUnit)->meta()->setInt64("timeUs",  timeUs);
301dcb89b3b505522efde173c105a851c412f947178Chong Zhang            mLastDequeuedTimeUs = timeUs;
302dcb89b3b505522efde173c105a851c412f947178Chong Zhang            mRealTimeBaseUs = ALooper::GetNowUs() - timeUs;
303dcb89b3b505522efde173c105a851c412f947178Chong Zhang        } else if (stream == STREAMTYPE_SUBTITLES) {
304b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih            int32_t subtitleGeneration;
305b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih            if ((*accessUnit)->meta()->findInt32("subtitleGeneration", &subtitleGeneration)
306b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih                    && subtitleGeneration != mSubtitleGeneration) {
307b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih               return -EAGAIN;
308b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih            };
309dcb89b3b505522efde173c105a851c412f947178Chong Zhang            (*accessUnit)->meta()->setInt32(
310dcb89b3b505522efde173c105a851c412f947178Chong Zhang                    "trackIndex", mPlaylist->getSelectedIndex());
311dcb89b3b505522efde173c105a851c412f947178Chong Zhang            (*accessUnit)->meta()->setInt64("baseUs", mRealTimeBaseUs);
312dcb89b3b505522efde173c105a851c412f947178Chong Zhang        }
31314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    } else {
31414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        ALOGI("[%s] encountered error %d", streamStr, err);
31514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
31614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
31714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return err;
31814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
31914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
32014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::getStreamFormat(StreamType stream, sp<AMessage> *format) {
3211543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // No swapPacketSource race condition; called from the same thread as dequeueAccessUnit.
32214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (!(mStreamMask & stream)) {
32314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        return UNKNOWN_ERROR;
32414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
32514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
32614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AnotherPacketSource> packetSource = mPacketSources.valueFor(stream);
32714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
32814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<MetaData> meta = packetSource->getFormat();
32914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
33014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (meta == NULL) {
33114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        return -EAGAIN;
33214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
33314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
33414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return convertMetaDataToMessage(meta, format);
335a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
336a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
33714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::connectAsync(
338ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        const char *url, const KeyedVector<String8, String8> *headers) {
3391d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatConnect, this);
340a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    msg->setString("url", url);
341ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber
342ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    if (headers != NULL) {
343ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        msg->setPointer(
344ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber                "headers",
345ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber                new KeyedVector<String8, String8>(*headers));
346ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    }
347ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber
348a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    msg->post();
349a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
350a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
35114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::disconnect() {
3521d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatDisconnect, this);
353ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
35414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> response;
35514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    status_t err = msg->postAndAwaitResponse(&response);
356ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
35714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return err;
358a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
359a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
36014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::seekTo(int64_t timeUs) {
3611d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatSeek, this);
362a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    msg->setInt64("timeUs", timeUs);
363a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
36414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> response;
36514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    status_t err = msg->postAndAwaitResponse(&response);
36614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
36714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return err;
368a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
369a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
370a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onMessageReceived(const sp<AMessage> &msg) {
371a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    switch (msg->what()) {
372a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        case kWhatConnect:
37314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
374a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            onConnect(msg);
375a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
37614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
377a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
378a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        case kWhatDisconnect:
37914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
38014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            CHECK(msg->senderAwaitsResponse(&mDisconnectReplyID));
38114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
38214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            if (mReconfigurationInProgress) {
38314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                break;
38414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            }
38514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
38614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            finishDisconnect();
387a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
38814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
389a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
39014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case kWhatSeek:
39114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
3923f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar            sp<AReplyToken> seekReplyID;
393800599cdd50737de1cde483a34b39923750b0658Robert Shih            CHECK(msg->senderAwaitsResponse(&seekReplyID));
394800599cdd50737de1cde483a34b39923750b0658Robert Shih            mSeekReplyID = seekReplyID;
395800599cdd50737de1cde483a34b39923750b0658Robert Shih            mSeekReply = new AMessage;
39614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
39714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            status_t err = onSeek(msg);
39814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
399800599cdd50737de1cde483a34b39923750b0658Robert Shih            if (err != OK) {
400800599cdd50737de1cde483a34b39923750b0658Robert Shih                msg->post(50000);
401800599cdd50737de1cde483a34b39923750b0658Robert Shih            }
40214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            break;
40314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
40414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
40514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case kWhatFetcherNotify:
40614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
40714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            int32_t what;
40814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            CHECK(msg->findInt32("what", &what));
40914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
41014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            switch (what) {
41114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                case PlaylistFetcher::kWhatStarted:
41214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    break;
41314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                case PlaylistFetcher::kWhatPaused:
41414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                case PlaylistFetcher::kWhatStopped:
41514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                {
41614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    if (what == PlaylistFetcher::kWhatStopped) {
41714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        AString uri;
41814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        CHECK(msg->findString("uri", &uri));
419964adb17885185808398507d2de88665fe193ee2Chong Zhang                        ssize_t index = mFetcherInfos.indexOfKey(uri);
420964adb17885185808398507d2de88665fe193ee2Chong Zhang                        if (index < 0) {
4211543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                            // ignore duplicated kWhatStopped messages.
4221543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                            break;
4231543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        }
4241543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
425964adb17885185808398507d2de88665fe193ee2Chong Zhang                        mFetcherLooper->unregisterHandler(
426964adb17885185808398507d2de88665fe193ee2Chong Zhang                                mFetcherInfos[index].mFetcher->id());
427964adb17885185808398507d2de88665fe193ee2Chong Zhang                        mFetcherInfos.removeItemsAt(index);
428964adb17885185808398507d2de88665fe193ee2Chong Zhang
429309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        if (mSwitchInProgress) {
430309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                            tryToFinishBandwidthSwitch();
431309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        }
43214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    }
43314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
43414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    if (mContinuation != NULL) {
43514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        CHECK_GT(mContinuationCounter, 0);
43614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        if (--mContinuationCounter == 0) {
43714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                            mContinuation->post();
43814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        }
43914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    }
44014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    break;
44114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                }
44214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
44314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                case PlaylistFetcher::kWhatDurationUpdate:
44414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                {
44514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    AString uri;
44614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    CHECK(msg->findString("uri", &uri));
44714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
44814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    int64_t durationUs;
44914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    CHECK(msg->findInt64("durationUs", &durationUs));
45014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
451964adb17885185808398507d2de88665fe193ee2Chong Zhang                    ssize_t index = mFetcherInfos.indexOfKey(uri);
452964adb17885185808398507d2de88665fe193ee2Chong Zhang                    if (index >= 0) {
453964adb17885185808398507d2de88665fe193ee2Chong Zhang                        FetcherInfo *info = &mFetcherInfos.editValueFor(uri);
454964adb17885185808398507d2de88665fe193ee2Chong Zhang                        info->mDurationUs = durationUs;
455964adb17885185808398507d2de88665fe193ee2Chong Zhang                    }
45614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    break;
45714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                }
45814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
45914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                case PlaylistFetcher::kWhatError:
46014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                {
46114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    status_t err;
46214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    CHECK(msg->findInt32("err", &err));
46314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
46414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    ALOGE("XXX Received error %d from PlaylistFetcher.", err);
46514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
46615f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                    // handle EOS on subtitle tracks independently
46715f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                    AString uri;
46815f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                    if (err == ERROR_END_OF_STREAM && msg->findString("uri", &uri)) {
46915f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                        ssize_t i = mFetcherInfos.indexOfKey(uri);
47015f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                        if (i >= 0) {
47115f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                            const sp<PlaylistFetcher> &fetcher = mFetcherInfos.valueAt(i).mFetcher;
47215f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                            if (fetcher != NULL) {
47315f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                                uint32_t type = fetcher->getStreamTypeMask();
47415f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                                if (type == STREAMTYPE_SUBTITLES) {
47515f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                                    mPacketSources.valueFor(
47615f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                                            STREAMTYPE_SUBTITLES)->signalEOS(err);;
47715f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                                    break;
47815f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                                }
47915f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                            }
48015f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                        }
48115f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih                    }
48215f8ecfa23b650b3efa8fe841d2be6bd0c9523fbRobert Shih
48314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    if (mInPreparationPhase) {
48414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                        postPrepared(err);
48514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    }
48614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
4871543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    cancelBandwidthSwitch();
4881543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
48914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    mPacketSources.valueFor(STREAMTYPE_AUDIO)->signalEOS(err);
49014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
49114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    mPacketSources.valueFor(STREAMTYPE_VIDEO)->signalEOS(err);
49214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
49314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    mPacketSources.valueFor(
49414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                            STREAMTYPE_SUBTITLES)->signalEOS(err);
49514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
49614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    sp<AMessage> notify = mNotify->dup();
49714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    notify->setInt32("what", kWhatError);
49814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    notify->setInt32("err", err);
49914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    notify->post();
50014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    break;
50114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                }
50214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
5031543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                case PlaylistFetcher::kWhatStartedAt:
5041543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                {
5051543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    int32_t switchGeneration;
5061543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    CHECK(msg->findInt32("switchGeneration", &switchGeneration));
5071543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
5081543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    if (switchGeneration != mSwitchGeneration) {
5091543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        break;
5101543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    }
5111543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
5121543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    // Resume fetcher for the original variant; the resumed fetcher should
5131543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    // continue until the timestamps found in msg, which is stored by the
5141543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    // new fetcher to indicate where the new variant has started buffering.
5151543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    for (size_t i = 0; i < mFetcherInfos.size(); i++) {
5161543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        const FetcherInfo info = mFetcherInfos.valueAt(i);
5171543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        if (info.mToBeRemoved) {
5181543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                            info.mFetcher->resumeUntilAsync(msg);
5191543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        }
5201543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    }
5211543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    break;
5221543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                }
5231543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
52414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                default:
52514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    TRESPASS();
52614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            }
52714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
52814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            break;
52914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
53014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
531dcb89b3b505522efde173c105a851c412f947178Chong Zhang        case kWhatChangeConfiguration:
532dcb89b3b505522efde173c105a851c412f947178Chong Zhang        {
533dcb89b3b505522efde173c105a851c412f947178Chong Zhang            onChangeConfiguration(msg);
534dcb89b3b505522efde173c105a851c412f947178Chong Zhang            break;
535dcb89b3b505522efde173c105a851c412f947178Chong Zhang        }
536dcb89b3b505522efde173c105a851c412f947178Chong Zhang
53714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case kWhatChangeConfiguration2:
53814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
53914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            onChangeConfiguration2(msg);
54014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            break;
54114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
54214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
54314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case kWhatChangeConfiguration3:
54414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
54514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            onChangeConfiguration3(msg);
54614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            break;
54714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
54814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
54914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        case kWhatFinishDisconnect2:
55014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        {
55114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            onFinishDisconnect2();
552a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
55314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
554a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
5551543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        case kWhatSwapped:
5561543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        {
5571543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            onSwapped(msg);
5581543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            break;
5591543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        }
5600ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
561964adb17885185808398507d2de88665fe193ee2Chong Zhang        case kWhatPollBuffering:
5620ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        {
563964adb17885185808398507d2de88665fe193ee2Chong Zhang            int32_t generation;
564964adb17885185808398507d2de88665fe193ee2Chong Zhang            CHECK(msg->findInt32("generation", &generation));
565964adb17885185808398507d2de88665fe193ee2Chong Zhang            if (generation == mPollBufferingGeneration) {
566964adb17885185808398507d2de88665fe193ee2Chong Zhang                onPollBuffering();
567964adb17885185808398507d2de88665fe193ee2Chong Zhang            }
5680ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih            break;
5690ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        }
5700ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
571a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        default:
572a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            TRESPASS();
573a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
574a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
575a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
576a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
577a44153c1a57202fb538659eb50706e60454d6273Andreas Huber// static
578a44153c1a57202fb538659eb50706e60454d6273Andreas Huberint LiveSession::SortByBandwidth(const BandwidthItem *a, const BandwidthItem *b) {
579a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (a->mBandwidth < b->mBandwidth) {
580a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return -1;
581a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else if (a->mBandwidth == b->mBandwidth) {
582a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return 0;
583a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
584a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
585a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return 1;
586a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
587a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
5888ca002eedc747dd854b61cbe364b52c06869273fRobert Shih// static
5898ca002eedc747dd854b61cbe364b52c06869273fRobert ShihLiveSession::StreamType LiveSession::indexToType(int idx) {
5908ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    CHECK(idx >= 0 && idx < kMaxStreams);
5918ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    return (StreamType)(1 << idx);
5928ca002eedc747dd854b61cbe364b52c06869273fRobert Shih}
5938ca002eedc747dd854b61cbe364b52c06869273fRobert Shih
594f69c996864844e8f669308af8412cede043062a2Robert Shih// static
595f69c996864844e8f669308af8412cede043062a2Robert Shihssize_t LiveSession::typeToIndex(int32_t type) {
596f69c996864844e8f669308af8412cede043062a2Robert Shih    switch (type) {
597f69c996864844e8f669308af8412cede043062a2Robert Shih        case STREAMTYPE_AUDIO:
598f69c996864844e8f669308af8412cede043062a2Robert Shih            return 0;
599f69c996864844e8f669308af8412cede043062a2Robert Shih        case STREAMTYPE_VIDEO:
600f69c996864844e8f669308af8412cede043062a2Robert Shih            return 1;
601f69c996864844e8f669308af8412cede043062a2Robert Shih        case STREAMTYPE_SUBTITLES:
602f69c996864844e8f669308af8412cede043062a2Robert Shih            return 2;
603f69c996864844e8f669308af8412cede043062a2Robert Shih        default:
604f69c996864844e8f669308af8412cede043062a2Robert Shih            return -1;
605f69c996864844e8f669308af8412cede043062a2Robert Shih    };
606f69c996864844e8f669308af8412cede043062a2Robert Shih    return -1;
607f69c996864844e8f669308af8412cede043062a2Robert Shih}
608f69c996864844e8f669308af8412cede043062a2Robert Shih
609a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onConnect(const sp<AMessage> &msg) {
610a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    AString url;
611a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    CHECK(msg->findString("url", &url));
612a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
613ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    KeyedVector<String8, String8> *headers = NULL;
614ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    if (!msg->findPointer("headers", (void **)&headers)) {
615ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        mExtraHeaders.clear();
616ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    } else {
617ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        mExtraHeaders = *headers;
618ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber
619ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        delete headers;
620ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        headers = NULL;
621ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    }
622ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber
623a1df816c0677185534babba6ffc29970b048e52eLajos Molnar    // TODO currently we don't know if we are coming here from incognito mode
624a1df816c0677185534babba6ffc29970b048e52eLajos Molnar    ALOGI("onConnect %s", uriDebugString(url).c_str());
625a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
626a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    mMasterURL = url;
627a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
6287e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    bool dummy;
62914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mPlaylist = fetchPlaylist(url.c_str(), NULL /* curPlaylistHash */, &dummy);
630ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
63114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (mPlaylist == NULL) {
632a1df816c0677185534babba6ffc29970b048e52eLajos Molnar        ALOGE("unable to fetch master playlist %s.", uriDebugString(url).c_str());
633ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
63414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        postPrepared(ERROR_IO);
635ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber        return;
636ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber    }
637a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
638964adb17885185808398507d2de88665fe193ee2Chong Zhang    // create looper for fetchers
639964adb17885185808398507d2de88665fe193ee2Chong Zhang    if (mFetcherLooper == NULL) {
640964adb17885185808398507d2de88665fe193ee2Chong Zhang        mFetcherLooper = new ALooper();
641964adb17885185808398507d2de88665fe193ee2Chong Zhang
642964adb17885185808398507d2de88665fe193ee2Chong Zhang        mFetcherLooper->setName("Fetcher");
643964adb17885185808398507d2de88665fe193ee2Chong Zhang        mFetcherLooper->start(false, false);
644964adb17885185808398507d2de88665fe193ee2Chong Zhang    }
645964adb17885185808398507d2de88665fe193ee2Chong Zhang
64614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // We trust the content provider to make a reasonable choice of preferred
64714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // initial bandwidth by listing it first in the variant playlist.
64814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // At startup we really don't have a good estimate on the available
64914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // network bandwidth since we haven't tranferred any data yet. Once
65014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // we have we can make a better informed choice.
65114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    size_t initialBandwidth = 0;
65214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    size_t initialBandwidthIndex = 0;
65314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
65414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (mPlaylist->isVariantPlaylist()) {
65514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        for (size_t i = 0; i < mPlaylist->size(); ++i) {
656a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            BandwidthItem item;
657a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
65814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            item.mPlaylistIndex = i;
65914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
660a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            sp<AMessage> meta;
66114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            AString uri;
66214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            mPlaylist->itemAt(i, &uri, &meta);
663a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
664a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            CHECK(meta->findInt32("bandwidth", (int32_t *)&item.mBandwidth));
665a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
66614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            if (initialBandwidth == 0) {
66714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                initialBandwidth = item.mBandwidth;
66814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            }
66914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
670a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            mBandwidthItems.push(item);
671a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
672a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
673a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        CHECK_GT(mBandwidthItems.size(), 0u);
674a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
675a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        mBandwidthItems.sort(SortByBandwidth);
67614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
67714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        for (size_t i = 0; i < mBandwidthItems.size(); ++i) {
67814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            if (mBandwidthItems.itemAt(i).mBandwidth == initialBandwidth) {
67914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                initialBandwidthIndex = i;
68014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                break;
68114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            }
68214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
68314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    } else {
68414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        // dummy item.
68514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        BandwidthItem item;
68614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        item.mPlaylistIndex = 0;
68714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        item.mBandwidth = 0;
68814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        mBandwidthItems.push(item);
689a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
690a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
691309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    mPlaylist->pickRandomMediaItems();
692dcb89b3b505522efde173c105a851c412f947178Chong Zhang    changeConfiguration(
693309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            0ll /* timeUs */, initialBandwidthIndex, false /* pickTrack */);
694964adb17885185808398507d2de88665fe193ee2Chong Zhang
695964adb17885185808398507d2de88665fe193ee2Chong Zhang    schedulePollBuffering();
696a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
697a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
69814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::finishDisconnect() {
69914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // No reconfiguration is currently pending, make sure none will trigger
70014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // during disconnection either.
70114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
7021543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // Protect mPacketSources from a swapPacketSource race condition through disconnect.
7031543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // (finishDisconnect, onFinishDisconnect2)
7041543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    cancelBandwidthSwitch();
7051543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
706964adb17885185808398507d2de88665fe193ee2Chong Zhang    // cancel buffer polling
707964adb17885185808398507d2de88665fe193ee2Chong Zhang    cancelPollBuffering();
7080ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
70914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
71014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        mFetcherInfos.valueAt(i).mFetcher->stopAsync();
71114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
71214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
7131d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatFinishDisconnect2, this);
714a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
71514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mContinuationCounter = mFetcherInfos.size();
71614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mContinuation = msg;
717ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
71814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (mContinuationCounter == 0) {
71914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        msg->post();
72014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
72114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
72214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
72314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::onFinishDisconnect2() {
72414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mContinuation.clear();
72514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
72614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mPacketSources.valueFor(STREAMTYPE_AUDIO)->signalEOS(ERROR_END_OF_STREAM);
72714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mPacketSources.valueFor(STREAMTYPE_VIDEO)->signalEOS(ERROR_END_OF_STREAM);
72814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
72914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mPacketSources.valueFor(
73014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            STREAMTYPE_SUBTITLES)->signalEOS(ERROR_END_OF_STREAM);
73114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
73214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> response = new AMessage;
73314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    response->setInt32("err", OK);
73414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
73514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    response->postReply(mDisconnectReplyID);
736c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang    mDisconnectReplyID.clear();
73714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
73814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
73914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubersp<PlaylistFetcher> LiveSession::addFetcher(const char *uri) {
74014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    ssize_t index = mFetcherInfos.indexOfKey(uri);
74114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
74214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (index >= 0) {
74314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        return NULL;
74414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
74514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
7461d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> notify = new AMessage(kWhatFetcherNotify, this);
74714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->setString("uri", uri);
7481543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    notify->setInt32("switchGeneration", mSwitchGeneration);
74914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
75014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    FetcherInfo info;
751b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    info.mFetcher = new PlaylistFetcher(notify, this, uri, mSubtitleGeneration);
75214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    info.mDurationUs = -1ll;
75314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    info.mIsPrepared = false;
7541543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    info.mToBeRemoved = false;
755964adb17885185808398507d2de88665fe193ee2Chong Zhang    mFetcherLooper->registerHandler(info.mFetcher);
75614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
75714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mFetcherInfos.add(uri, info);
75814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
75914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return info.mFetcher;
760a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
761a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
7628dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih/*
7638dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * Illustration of parameters:
7648dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih *
7658dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * 0      `range_offset`
7668dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * +------------+-------------------------------------------------------+--+--+
7678dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * |            |                                 | next block to fetch |  |  |
7688dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * |            | `source` handle => `out` buffer |                     |  |  |
7698dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * | `url` file |<--------- buffer size --------->|<--- `block_size` -->|  |  |
7708dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * |            |<----------- `range_length` / buffer capacity ----------->|  |
7718dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * |<------------------------------ file_size ------------------------------->|
7728dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih *
7738dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * Special parameter values:
7748dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * - range_length == -1 means entire file
7758dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih * - block_size == 0 means entire range
7768dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih *
7778dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih */
77843ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shihssize_t LiveSession::fetchFile(
7792aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        const char *url, sp<ABuffer> *out,
7808dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        int64_t range_offset, int64_t range_length,
7818dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        uint32_t block_size, /* download block size */
78297194cdf8d67f362ef8c6dfdf607298c7e102b3bMarco Nelissen        sp<DataSource> *source, /* to return and reuse source */
783784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo        String8 *actualUrl) {
7848dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    off64_t size;
7858dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    sp<DataSource> temp_source;
7868dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    if (source == NULL) {
7878dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        source = &temp_source;
7888dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    }
789a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
7908dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    if (*source == NULL) {
7918dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        if (!strncasecmp(url, "file://", 7)) {
7928dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            *source = new FileSource(url + 7);
7938dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        } else if (strncasecmp(url, "http://", 7)
7948dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                && strncasecmp(url, "https://", 8)) {
7958dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            return ERROR_UNSUPPORTED;
7968dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        } else {
7978dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            KeyedVector<String8, String8> headers = mExtraHeaders;
7988dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            if (range_offset > 0 || range_length >= 0) {
7998dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                headers.add(
8008dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                        String8("Range"),
8018dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                        String8(
802a1e8944a21e5833b7aadc451776f11797f5f9273Elliott Hughes                            AStringPrintf(
8038dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                                "bytes=%lld-%s",
8048dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                                range_offset,
8058dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                                range_length < 0
806a1e8944a21e5833b7aadc451776f11797f5f9273Elliott Hughes                                    ? "" : AStringPrintf("%lld",
8078dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                                            range_offset + range_length - 1).c_str()).c_str()));
8088dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            }
8098dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            status_t err = mHTTPDataSource->connect(url, &headers);
810a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
8118dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            if (err != OK) {
8128dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih                return err;
8138dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            }
814a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
8158dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih            *source = mHTTPDataSource;
816a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
817a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
818a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
8198dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    status_t getSizeErr = (*source)->getSize(&size);
8208dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    if (getSizeErr != OK) {
821a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        size = 65536;
822a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
823a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
8248dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    sp<ABuffer> buffer = *out != NULL ? *out : new ABuffer(size);
8258dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    if (*out == NULL) {
8268dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        buffer->setRange(0, 0);
8278dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    }
828a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
82943ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih    ssize_t bytesRead = 0;
8308dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    // adjust range_length if only reading partial block
831b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross    if (block_size > 0 && (range_length == -1 || (int64_t)(buffer->size() + block_size) < range_length)) {
8328dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        range_length = buffer->size() + block_size;
8338dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih    }
834a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    for (;;) {
8358dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        // Only resize when we don't know the size.
836a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        size_t bufferRemaining = buffer->capacity() - buffer->size();
8378dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        if (bufferRemaining == 0 && getSizeErr != OK) {
8389aff25fb41f516ac26f9d1983a25402909f1e77aLeena Winterrowd            size_t bufferIncrement = buffer->size() / 2;
8399aff25fb41f516ac26f9d1983a25402909f1e77aLeena Winterrowd            if (bufferIncrement < 32768) {
8409aff25fb41f516ac26f9d1983a25402909f1e77aLeena Winterrowd                bufferIncrement = 32768;
8419aff25fb41f516ac26f9d1983a25402909f1e77aLeena Winterrowd            }
8429aff25fb41f516ac26f9d1983a25402909f1e77aLeena Winterrowd            bufferRemaining = bufferIncrement;
843a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
844b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross            ALOGV("increasing download buffer to %zu bytes",
845a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                 buffer->size() + bufferRemaining);
846a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
847a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            sp<ABuffer> copy = new ABuffer(buffer->size() + bufferRemaining);
848a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            memcpy(copy->data(), buffer->data(), buffer->size());
849a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            copy->setRange(0, buffer->size());
850a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
851a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            buffer = copy;
852a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
853a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
8542aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        size_t maxBytesToRead = bufferRemaining;
8552aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        if (range_length >= 0) {
8562aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber            int64_t bytesLeftInRange = range_length - buffer->size();
857b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross            if (bytesLeftInRange < (int64_t)maxBytesToRead) {
8582aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                maxBytesToRead = bytesLeftInRange;
8592aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber
8602aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                if (bytesLeftInRange == 0) {
8612aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                    break;
8622aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                }
8632aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber            }
8642aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        }
8652aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber
8668dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        // The DataSource is responsible for informing us of error (n < 0) or eof (n == 0)
8678dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        // to help us break out of the loop.
8688dd1c202aea703ed8beacaaa0dad5ae9c76a0863Robert Shih        ssize_t n = (*source)->readAt(
869a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                buffer->size(), buffer->data() + buffer->size(),
8702aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                maxBytesToRead);
871a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
872a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (n < 0) {
87320ad3a341a96e7746015ccb7369fa567897e11f6Andreas Huber            return n;
874a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
875a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
876a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (n == 0) {
877a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
878a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
879a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
880a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        buffer->setRange(0, buffer->size() + (size_t)n);
88143ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih        bytesRead += n;
882a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
883a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
884a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    *out = buffer;
885784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo    if (actualUrl != NULL) {
88697194cdf8d67f362ef8c6dfdf607298c7e102b3bMarco Nelissen        *actualUrl = (*source)->getUri();
887784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo        if (actualUrl->isEmpty()) {
888784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo            *actualUrl = url;
889784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo        }
890784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo    }
891a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
89243ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih    return bytesRead;
893a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
894a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
89514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubersp<M3UParser> LiveSession::fetchPlaylist(
89614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        const char *url, uint8_t *curPlaylistHash, bool *unchanged) {
897b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber    ALOGV("fetchPlaylist '%s'", url);
898b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
8997e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    *unchanged = false;
9007e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
901a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<ABuffer> buffer;
902784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo    String8 actualUrl;
90343ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih    ssize_t  err = fetchFile(url, &buffer, 0, -1, 0, NULL, &actualUrl);
904a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
90543ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih    if (err <= 0) {
906a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return NULL;
907a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
908a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
9097e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    // MD5 functionality is not available on the simulator, treat all
9107e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    // playlists as changed.
9117e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
9127e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber#if defined(HAVE_ANDROID_OS)
9137e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    uint8_t hash[16];
9147e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
9157e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    MD5_CTX m;
9167e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    MD5_Init(&m);
9177e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    MD5_Update(&m, buffer->data(), buffer->size());
9187e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
9197e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    MD5_Final(hash, &m);
9207e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
92114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (curPlaylistHash != NULL && !memcmp(hash, curPlaylistHash, 16)) {
9227e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        // playlist unchanged
9237e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        *unchanged = true;
9247e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
9257e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        return NULL;
9267e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    }
9277e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
92814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (curPlaylistHash != NULL) {
92914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        memcpy(curPlaylistHash, hash, sizeof(hash));
93014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
9317e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber#endif
9327e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
933a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<M3UParser> playlist =
934784faaf1d76902be6b36d3af01fb5325f0d45a04Martin Storsjo        new M3UParser(actualUrl.string(), buffer->data(), buffer->size());
935a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
936a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (playlist->initCheck() != OK) {
93729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("failed to parse .m3u8 playlist");
9389067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber
939a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return NULL;
940a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
941a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
942a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return playlist;
943a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
944a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
945b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe#if 0
946a44153c1a57202fb538659eb50706e60454d6273Andreas Huberstatic double uniformRand() {
947a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return (double)rand() / RAND_MAX;
948a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
949b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe#endif
950a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
951a44153c1a57202fb538659eb50706e60454d6273Andreas Hubersize_t LiveSession::getBandwidthIndex() {
952a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (mBandwidthItems.size() == 0) {
953a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return 0;
954a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
955a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
956a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#if 1
957a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    char value[PROPERTY_VALUE_MAX];
958673158582c9589cee1d5e4d7c79622609938b8f8Andreas Huber    ssize_t index = -1;
95914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (property_get("media.httplive.bw-index", value, NULL)) {
960a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        char *end;
96114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        index = strtol(value, &end, 10);
96214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        CHECK(end > value && *end == '\0');
96314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
96414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (index >= 0 && (size_t)index >= mBandwidthItems.size()) {
96514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            index = mBandwidthItems.size() - 1;
966a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
967a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
968a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
96914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (index < 0) {
97014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        int32_t bandwidthBps;
97114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (mHTTPDataSource != NULL
97214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                && mHTTPDataSource->estimateBandwidth(&bandwidthBps)) {
97314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            ALOGV("bandwidth estimated at %.2f kbps", bandwidthBps / 1024.0f);
97414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        } else {
97514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            ALOGV("no bandwidth estimate.");
97614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            return 0;  // Pick the lowest bandwidth stream by default.
97714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
978a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
97914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        char value[PROPERTY_VALUE_MAX];
98014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (property_get("media.httplive.max-bw", value, NULL)) {
98114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            char *end;
98214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            long maxBw = strtoul(value, &end, 10);
98314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            if (end > value && *end == '\0') {
98414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                if (maxBw > 0 && bandwidthBps > maxBw) {
98514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    ALOGV("bandwidth capped to %ld bps", maxBw);
98614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                    bandwidthBps = maxBw;
98714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber                }
98814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            }
98914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
990a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
99114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        // Pick the highest bandwidth stream below or equal to estimated bandwidth.
99214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
99314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        index = mBandwidthItems.size() - 1;
99400598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih        while (index > 0) {
99500598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih            // consider only 80% of the available bandwidth, but if we are switching up,
99600598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih            // be even more conservative (70%) to avoid overestimating and immediately
99700598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih            // switching back.
99800598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih            size_t adjustedBandwidthBps = bandwidthBps;
99900598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih            if (index > mCurBandwidthIndex) {
100000598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih                adjustedBandwidthBps = adjustedBandwidthBps * 7 / 10;
100100598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih            } else {
100200598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih                adjustedBandwidthBps = adjustedBandwidthBps * 8 / 10;
100300598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih            }
100400598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih            if (mBandwidthItems.itemAt(index).mBandwidth <= adjustedBandwidthBps) {
100500598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih                break;
100600598ec0b15426197494aaf9e5ec0bc88507c762Robert Shih            }
100714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            --index;
100814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
1009a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1010a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0
1011a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // Change bandwidth at random()
1012a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index = uniformRand() * mBandwidthItems.size();
1013a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0
1014a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // There's a 50% chance to stay on the current bandwidth and
1015a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // a 50% chance to switch to the next higher bandwidth (wrapping around
1016a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // to lowest)
1017a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    const size_t kMinIndex = 0;
1018a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1019309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    static ssize_t mCurBandwidthIndex = -1;
102014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
1021a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index;
1022309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    if (mCurBandwidthIndex < 0) {
1023a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        index = kMinIndex;
1024a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else if (uniformRand() < 0.5) {
1025309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        index = (size_t)mCurBandwidthIndex;
1026a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else {
1027309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        index = mCurBandwidthIndex + 1;
1028a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (index == mBandwidthItems.size()) {
1029a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            index = kMinIndex;
1030a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
1031a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1032309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    mCurBandwidthIndex = index;
1033a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0
1034a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // Pick the highest bandwidth stream below or equal to 1.2 Mbit/sec
1035a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1036a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index = mBandwidthItems.size() - 1;
1037a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    while (index > 0 && mBandwidthItems.itemAt(index).mBandwidth > 1200000) {
1038a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        --index;
1039a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
104014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#elif 1
104114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    char value[PROPERTY_VALUE_MAX];
104214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    size_t index;
104314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (property_get("media.httplive.bw-index", value, NULL)) {
104414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        char *end;
104514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        index = strtoul(value, &end, 10);
104614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        CHECK(end > value && *end == '\0');
104714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
104814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (index >= mBandwidthItems.size()) {
104914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            index = mBandwidthItems.size() - 1;
105014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
105114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    } else {
105214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        index = 0;
105314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
1054a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#else
1055a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index = mBandwidthItems.size() - 1;  // Highest bandwidth stream
1056a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#endif
1057a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
105814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK_GE(index, 0);
105914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
1060a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return index;
1061a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
1062a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1063b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shihint64_t LiveSession::latestMediaSegmentStartTimeUs() {
1064b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    sp<AMessage> audioMeta = mPacketSources.valueFor(STREAMTYPE_AUDIO)->getLatestDequeuedMeta();
1065b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    int64_t minSegmentStartTimeUs = -1, videoSegmentStartTimeUs = -1;
1066b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    if (audioMeta != NULL) {
1067b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih        audioMeta->findInt64("segmentStartTimeUs", &minSegmentStartTimeUs);
1068b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    }
1069b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih
1070b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    sp<AMessage> videoMeta = mPacketSources.valueFor(STREAMTYPE_VIDEO)->getLatestDequeuedMeta();
1071b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    if (videoMeta != NULL
1072b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih            && videoMeta->findInt64("segmentStartTimeUs", &videoSegmentStartTimeUs)) {
1073b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih        if (minSegmentStartTimeUs < 0 || videoSegmentStartTimeUs < minSegmentStartTimeUs) {
1074b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih            minSegmentStartTimeUs = videoSegmentStartTimeUs;
1075b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih        }
1076b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih
1077b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    }
1078b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    return minSegmentStartTimeUs;
1079b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih}
1080b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih
108114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::onSeek(const sp<AMessage> &msg) {
108214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    int64_t timeUs;
108314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(msg->findInt64("timeUs", &timeUs));
10847e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
108514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (!mReconfigurationInProgress) {
1086800599cdd50737de1cde483a34b39923750b0658Robert Shih        changeConfiguration(timeUs, mCurBandwidthIndex);
1087800599cdd50737de1cde483a34b39923750b0658Robert Shih        return OK;
1088800599cdd50737de1cde483a34b39923750b0658Robert Shih    } else {
1089800599cdd50737de1cde483a34b39923750b0658Robert Shih        return -EWOULDBLOCK;
10907e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    }
10917e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber}
10927e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
109314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t LiveSession::getDuration(int64_t *durationUs) const {
1094895651b07fec30b0f9b0d2499599a179d95c9be4Wei Jia    int64_t maxDurationUs = -1ll;
109514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
109614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        int64_t fetcherDurationUs = mFetcherInfos.valueAt(i).mDurationUs;
1097b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
1098895651b07fec30b0f9b0d2499599a179d95c9be4Wei Jia        if (fetcherDurationUs > maxDurationUs) {
109914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            maxDurationUs = fetcherDurationUs;
1100a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
1101a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1102a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
110314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    *durationUs = maxDurationUs;
1104a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
110514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return OK;
110614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
11070f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber
110814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberbool LiveSession::isSeekable() const {
110914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    int64_t durationUs;
111014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return getDuration(&durationUs) == OK && durationUs >= 0;
111114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
11120f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber
111314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberbool LiveSession::hasDynamicDuration() const {
111414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return false;
111514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
11160f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber
1117404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhangsize_t LiveSession::getTrackCount() const {
11189d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih    if (mPlaylist == NULL) {
11199d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih        return 0;
11209d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih    } else {
11219d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih        return mPlaylist->getTrackCount();
11229d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih    }
1123404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang}
1124404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang
1125404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhangsp<AMessage> LiveSession::getTrackInfo(size_t trackIndex) const {
11269d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih    if (mPlaylist == NULL) {
11279d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih        return NULL;
11289d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih    } else {
11299d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih        return mPlaylist->getTrackInfo(trackIndex);
11309d7fc5c5fab0c7c967a625d22fffda046f9d5c29Robert Shih    }
1131dcb89b3b505522efde173c105a851c412f947178Chong Zhang}
1132dcb89b3b505522efde173c105a851c412f947178Chong Zhang
1133dcb89b3b505522efde173c105a851c412f947178Chong Zhangstatus_t LiveSession::selectTrack(size_t index, bool select) {
1134b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    if (mPlaylist == NULL) {
1135b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih        return INVALID_OPERATION;
1136b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    }
1137b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih
1138b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih    ++mSubtitleGeneration;
1139dcb89b3b505522efde173c105a851c412f947178Chong Zhang    status_t err = mPlaylist->selectTrack(index, select);
1140dcb89b3b505522efde173c105a851c412f947178Chong Zhang    if (err == OK) {
11411d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar        sp<AMessage> msg = new AMessage(kWhatChangeConfiguration, this);
1142309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        msg->setInt32("bandwidthIndex", mCurBandwidthIndex);
1143309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        msg->setInt32("pickTrack", select);
1144309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        msg->post();
1145dcb89b3b505522efde173c105a851c412f947178Chong Zhang    }
1146dcb89b3b505522efde173c105a851c412f947178Chong Zhang    return err;
1147dcb89b3b505522efde173c105a851c412f947178Chong Zhang}
1148dcb89b3b505522efde173c105a851c412f947178Chong Zhang
114989bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shihssize_t LiveSession::getSelectedTrack(media_track_type type) const {
115089bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih    if (mPlaylist == NULL) {
115189bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih        return -1;
115289bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih    } else {
115389bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih        return mPlaylist->getSelectedTrack(type);
115489bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih    }
115589bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih}
115689bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih
1157dcb89b3b505522efde173c105a851c412f947178Chong Zhangvoid LiveSession::changeConfiguration(
1158dcb89b3b505522efde173c105a851c412f947178Chong Zhang        int64_t timeUs, size_t bandwidthIndex, bool pickTrack) {
11591543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // Protect mPacketSources from a swapPacketSource race condition through reconfiguration.
11601543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // (changeConfiguration, onChangeConfiguration2, onChangeConfiguration3).
11611543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    cancelBandwidthSwitch();
11621543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
116314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(!mReconfigurationInProgress);
116414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mReconfigurationInProgress = true;
1165a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1166309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    mCurBandwidthIndex = bandwidthIndex;
116743c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
1168b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross    ALOGV("changeConfiguration => timeUs:%" PRId64 " us, bwIndex:%zu, pickTrack:%d",
1169dcb89b3b505522efde173c105a851c412f947178Chong Zhang          timeUs, bandwidthIndex, pickTrack);
117043c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
117114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK_LT(bandwidthIndex, mBandwidthItems.size());
117214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    const BandwidthItem &item = mBandwidthItems.itemAt(bandwidthIndex);
1173a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
11741543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    uint32_t streamMask = 0; // streams that should be fetched by the new fetcher
11751543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    uint32_t resumeMask = 0; // streams that should be fetched by the original fetcher
1176a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
11778ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    AString URIs[kMaxStreams];
11788ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
11798ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        if (mPlaylist->getTypeURI(item.mPlaylistIndex, mStreams[i].mType, &URIs[i])) {
11808ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            streamMask |= indexToType(i);
11818ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        }
118214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
1183aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber
118414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Step 1, stop and discard fetchers that are no longer needed.
118514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Pause those that we'll reuse.
118614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
118714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        const AString &uri = mFetcherInfos.keyAt(i);
1188aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber
118914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        bool discardFetcher = true;
1190aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber
119114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (timeUs < 0ll) {
1192309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            // delay fetcher removal if not picking tracks
1193309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            discardFetcher = pickTrack;
11941543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
1195c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        }
1196c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang
1197c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        for (size_t j = 0; j < kMaxStreams; ++j) {
1198c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang            StreamType type = indexToType(j);
1199c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang            if ((streamMask & type) && uri == URIs[j]) {
1200c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang                resumeMask |= type;
1201c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang                streamMask &= ~type;
1202c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang                discardFetcher = false;
12036801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber            }
120414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
1205a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
120614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (discardFetcher) {
120714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber            mFetcherInfos.valueAt(i).mFetcher->stopAsync();
12086801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber        } else {
1209c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang            // if we're seeking, pause immediately (no need to finish the segment)
1210c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang            bool immediate = (timeUs >= 0ll);
1211c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang            mFetcherInfos.valueAt(i).mFetcher->pauseAsync(immediate);
12126801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber        }
1213a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1214a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
12151543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    sp<AMessage> msg;
12161543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    if (timeUs < 0ll) {
1217309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        // skip onChangeConfiguration2 (decoder destruction) if not seeking.
12181d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar        msg = new AMessage(kWhatChangeConfiguration3, this);
12191543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    } else {
12201d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar        msg = new AMessage(kWhatChangeConfiguration2, this);
12211543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
122214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    msg->setInt32("streamMask", streamMask);
12231543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    msg->setInt32("resumeMask", resumeMask);
1224309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    msg->setInt32("pickTrack", pickTrack);
122514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    msg->setInt64("timeUs", timeUs);
12268ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
1227309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        if ((streamMask | resumeMask) & indexToType(i)) {
12288ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            msg->setString(mStreams[i].uriKey().c_str(), URIs[i].c_str());
12298ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        }
12306e6b1cae2bac1b78205cefab8e4e9e9538982965Andreas Huber    }
1231a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
123214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Every time a fetcher acknowledges the stopAsync or pauseAsync request
123314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // we'll decrement mContinuationCounter, once it reaches zero, i.e. all
123414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // fetchers have completed their asynchronous operation, we'll post
123514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // mContinuation, which then is handled below in onChangeConfiguration2.
123614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mContinuationCounter = mFetcherInfos.size();
123714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mContinuation = msg;
123888b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber
123914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (mContinuationCounter == 0) {
124014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        msg->post();
124188b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber    }
124214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
1243a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1244dcb89b3b505522efde173c105a851c412f947178Chong Zhangvoid LiveSession::onChangeConfiguration(const sp<AMessage> &msg) {
1245dcb89b3b505522efde173c105a851c412f947178Chong Zhang    if (!mReconfigurationInProgress) {
1246309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        int32_t pickTrack = 0, bandwidthIndex = mCurBandwidthIndex;
1247309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        msg->findInt32("pickTrack", &pickTrack);
1248309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        msg->findInt32("bandwidthIndex", &bandwidthIndex);
1249309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        changeConfiguration(-1ll /* timeUs */, bandwidthIndex, pickTrack);
1250dcb89b3b505522efde173c105a851c412f947178Chong Zhang    } else {
1251dcb89b3b505522efde173c105a851c412f947178Chong Zhang        msg->post(1000000ll); // retry in 1 sec
1252dcb89b3b505522efde173c105a851c412f947178Chong Zhang    }
1253dcb89b3b505522efde173c105a851c412f947178Chong Zhang}
1254dcb89b3b505522efde173c105a851c412f947178Chong Zhang
125514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::onChangeConfiguration2(const sp<AMessage> &msg) {
125614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mContinuation.clear();
1257bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
125814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // All fetchers are either suspended or have been removed now.
1259bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
1260964adb17885185808398507d2de88665fe193ee2Chong Zhang    // If we're seeking, clear all packet sources before we report
1261964adb17885185808398507d2de88665fe193ee2Chong Zhang    // seek complete, to prevent decoder from pulling stale data.
1262964adb17885185808398507d2de88665fe193ee2Chong Zhang    int64_t timeUs;
1263964adb17885185808398507d2de88665fe193ee2Chong Zhang    CHECK(msg->findInt64("timeUs", &timeUs));
1264964adb17885185808398507d2de88665fe193ee2Chong Zhang
1265964adb17885185808398507d2de88665fe193ee2Chong Zhang    if (timeUs >= 0) {
1266964adb17885185808398507d2de88665fe193ee2Chong Zhang        mLastSeekTimeUs = timeUs;
1267964adb17885185808398507d2de88665fe193ee2Chong Zhang
1268964adb17885185808398507d2de88665fe193ee2Chong Zhang        for (size_t i = 0; i < mPacketSources.size(); i++) {
1269964adb17885185808398507d2de88665fe193ee2Chong Zhang            mPacketSources.editValueAt(i)->clear();
1270964adb17885185808398507d2de88665fe193ee2Chong Zhang        }
1271964adb17885185808398507d2de88665fe193ee2Chong Zhang
1272964adb17885185808398507d2de88665fe193ee2Chong Zhang        mDiscontinuityOffsetTimesUs.clear();
1273964adb17885185808398507d2de88665fe193ee2Chong Zhang        mDiscontinuityAbsStartTimesUs.clear();
1274964adb17885185808398507d2de88665fe193ee2Chong Zhang
1275c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        if (mSeekReplyID != NULL) {
1276964adb17885185808398507d2de88665fe193ee2Chong Zhang            CHECK(mSeekReply != NULL);
1277964adb17885185808398507d2de88665fe193ee2Chong Zhang            mSeekReply->setInt32("err", OK);
1278964adb17885185808398507d2de88665fe193ee2Chong Zhang            mSeekReply->postReply(mSeekReplyID);
1279c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang            mSeekReplyID.clear();
1280964adb17885185808398507d2de88665fe193ee2Chong Zhang            mSeekReply.clear();
1281964adb17885185808398507d2de88665fe193ee2Chong Zhang        }
1282964adb17885185808398507d2de88665fe193ee2Chong Zhang    }
1283964adb17885185808398507d2de88665fe193ee2Chong Zhang
1284309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    uint32_t streamMask, resumeMask;
128514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(msg->findInt32("streamMask", (int32_t *)&streamMask));
1286309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    CHECK(msg->findInt32("resumeMask", (int32_t *)&resumeMask));
1287309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
1288309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    streamMask |= resumeMask;
1289bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
12908ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    AString URIs[kMaxStreams];
12918ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
12928ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        if (streamMask & indexToType(i)) {
12938ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            const AString &uriKey = mStreams[i].uriKey();
12948ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            CHECK(msg->findString(uriKey.c_str(), &URIs[i]));
12958ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            ALOGV("%s = '%s'", uriKey.c_str(), URIs[i].c_str());
12968ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        }
129722fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber    }
12983831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber
129914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    uint32_t changedMask = 0;
13008ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams && i != kSubtitleIndex; ++i) {
1301c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        // stream URI could change even if onChangeConfiguration2 is only
1302c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        // used for seek. Seek could happen during a bw switch, in this
1303c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        // case bw switch will be cancelled, but the seekTo position will
1304c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        // fetch from the new URI.
1305c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        if ((mStreamMask & streamMask & indexToType(i))
1306c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang                && !mStreams[i].mUri.empty()
1307c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang                && !(URIs[i] == mStreams[i].mUri)) {
1308c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang            ALOGV("stream %d changed: oldURI %s, newURI %s", i,
1309c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang                    mStreams[i].mUri.c_str(), URIs[i].c_str());
1310c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang            sp<AnotherPacketSource> source = mPacketSources.valueFor(indexToType(i));
1311c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang            source->queueDiscontinuity(
1312c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang                    ATSParser::DISCONTINUITY_FORMATCHANGE, NULL, true);
1313c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        }
1314c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        // Determine which decoders to shutdown on the player side,
1315c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        // a decoder has to be shutdown if its streamtype was active
1316c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        // before but now longer isn't.
1317c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang        if ((mStreamMask & ~streamMask & indexToType(i))) {
13188ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            changedMask |= indexToType(i);
13198ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        }
1320b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber    }
1321b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
132214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (changedMask == 0) {
132314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        // If nothing changed as far as the audio/video decoders
132414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        // are concerned we can proceed.
132514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        onChangeConfiguration3(msg);
132614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        return;
132714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
132843c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
132914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Something changed, inform the player which will shutdown the
133014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // corresponding decoders and will post the reply once that's done.
133114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // Handling the reply will continue executing below in
133214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // onChangeConfiguration3.
133314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> notify = mNotify->dup();
133414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->setInt32("what", kWhatStreamsChanged);
133514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->setInt32("changedMask", changedMask);
133620f725ebcef13ded1b4b85c61c8a4b37cd030656Andreas Huber
133714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    msg->setWhat(kWhatChangeConfiguration3);
13381d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    msg->setTarget(this);
1339b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
134014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->setMessage("reply", msg);
134114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->post();
134214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
1343b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
134414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::onChangeConfiguration3(const sp<AMessage> &msg) {
13451543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    mContinuation.clear();
134614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // All remaining fetchers are still suspended, the player has shutdown
134714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // any decoders that needed it.
1348b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
13491543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    uint32_t streamMask, resumeMask;
135014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(msg->findInt32("streamMask", (int32_t *)&streamMask));
13511543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    CHECK(msg->findInt32("resumeMask", (int32_t *)&resumeMask));
1352a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
135314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    int64_t timeUs;
1354309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    int32_t pickTrack;
13551543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    bool switching = false;
135614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(msg->findInt64("timeUs", &timeUs));
1357309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    CHECK(msg->findInt32("pickTrack", &pickTrack));
1358a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
135914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (timeUs < 0ll) {
1360309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        if (!pickTrack) {
1361309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih            switching = true;
1362309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        }
1363309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        mRealTimeBaseUs = ALooper::GetNowUs() - mLastDequeuedTimeUs;
1364309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    } else {
1365309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        mRealTimeBaseUs = ALooper::GetNowUs() - timeUs;
136614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
1367a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1368f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
1369f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        if (streamMask & indexToType(i)) {
1370f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            if (switching) {
1371f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih                CHECK(msg->findString(mStreams[i].uriKey().c_str(), &mStreams[i].mNewUri));
1372f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            } else {
1373f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih                CHECK(msg->findString(mStreams[i].uriKey().c_str(), &mStreams[i].mUri));
1374f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            }
1375f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        }
1376f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    }
1377f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih
1378309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    mNewStreamMask = streamMask | resumeMask;
1379f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    if (switching) {
1380f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        mSwapMask = mStreamMask & ~resumeMask;
1381f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    }
1382a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
13831543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // Of all existing fetchers:
13841543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // * Resume fetchers that are still needed and assign them original packet sources.
13851543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // * Mark otherwise unneeded fetchers for removal.
13861543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    ALOGV("resuming fetchers for mask 0x%08x", resumeMask);
138714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
138814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        const AString &uri = mFetcherInfos.keyAt(i);
13890df36ec3303c2c6bf9b42c07945ac8bd234153f3Andreas Huber
13908ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        sp<AnotherPacketSource> sources[kMaxStreams];
1391dc793ce8c0ead27ab43e40ce09f27fe338323502Robert Shih        for (size_t j = 0; j < kMaxStreams; ++j) {
13921543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            if ((resumeMask & indexToType(j)) && uri == mStreams[j].mUri) {
13938ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                sources[j] = mPacketSources.valueFor(indexToType(j));
13948ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            }
139514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        }
13961543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        FetcherInfo &info = mFetcherInfos.editValueAt(i);
13971543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        if (sources[kAudioIndex] != NULL || sources[kVideoIndex] != NULL
13981543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                || sources[kSubtitleIndex] != NULL) {
13991543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            info.mFetcher->startAsync(
1400c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang                    sources[kAudioIndex], sources[kVideoIndex], sources[kSubtitleIndex], timeUs);
14011543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        } else {
14021543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            info.mToBeRemoved = true;
14031543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        }
1404a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1405a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
140614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // streamMask now only contains the types that need a new fetcher created.
1407a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
140814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (streamMask != 0) {
140914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        ALOGV("creating new fetchers for mask 0x%08x", streamMask);
1410a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1411a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
14121543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // Find out when the original fetchers have buffered up to and start the new fetchers
14131543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // at a later timestamp.
14148ca002eedc747dd854b61cbe364b52c06869273fRobert Shih    for (size_t i = 0; i < kMaxStreams; i++) {
14158ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        if (!(indexToType(i) & streamMask)) {
14168ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            continue;
14178ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        }
14181156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
141914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        AString uri;
1420f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        uri = switching ? mStreams[i].mNewUri : mStreams[i].mUri;
14219b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber
142214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        sp<PlaylistFetcher> fetcher = addFetcher(uri.c_str());
142314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        CHECK(fetcher != NULL);
1424a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1425309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        int64_t startTimeUs = -1;
1426309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        int64_t segmentStartTimeUs = -1ll;
1427309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        int32_t discontinuitySeq = -1;
14288ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        sp<AnotherPacketSource> sources[kMaxStreams];
14291543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
1430b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih        if (i == kSubtitleIndex) {
1431b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih            segmentStartTimeUs = latestMediaSegmentStartTimeUs();
1432b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih        }
1433b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih
14348ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        // TRICKY: looping from i as earlier streams are already removed from streamMask
14358ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        for (size_t j = i; j < kMaxStreams; ++j) {
1436f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            const AString &streamUri = switching ? mStreams[j].mNewUri : mStreams[j].mUri;
1437f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            if ((streamMask & indexToType(j)) && uri == streamUri) {
14388ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                sources[j] = mPacketSources.valueFor(indexToType(j));
14391543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
1440309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                if (timeUs >= 0) {
1441309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    startTimeUs = timeUs;
14421543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                } else {
1443309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    int32_t type;
1444309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    sp<AMessage> meta;
1445309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    if (pickTrack) {
1446309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        // selecting
1447309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        meta = sources[j]->getLatestDequeuedMeta();
1448309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    } else {
1449309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        // adapting
1450309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        meta = sources[j]->getLatestEnqueuedMeta();
1451309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    }
14521543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
14531543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    if (meta != NULL && !meta->findInt32("discontinuity", &type)) {
1454309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        int64_t tmpUs;
1455afcc4fcbb3a094ec2221d6e523772e76894d1f00Robert Shih                        int64_t tmpSegmentUs;
1456afcc4fcbb3a094ec2221d6e523772e76894d1f00Robert Shih
1457309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        CHECK(meta->findInt64("timeUs", &tmpUs));
1458afcc4fcbb3a094ec2221d6e523772e76894d1f00Robert Shih                        CHECK(meta->findInt64("segmentStartTimeUs", &tmpSegmentUs));
1459afcc4fcbb3a094ec2221d6e523772e76894d1f00Robert Shih                        if (startTimeUs < 0 || tmpSegmentUs < segmentStartTimeUs) {
1460afcc4fcbb3a094ec2221d6e523772e76894d1f00Robert Shih                            startTimeUs = tmpUs;
1461afcc4fcbb3a094ec2221d6e523772e76894d1f00Robert Shih                            segmentStartTimeUs = tmpSegmentUs;
1462afcc4fcbb3a094ec2221d6e523772e76894d1f00Robert Shih                        } else if (tmpSegmentUs == segmentStartTimeUs && tmpUs < startTimeUs) {
1463309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                            startTimeUs = tmpUs;
14641543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        }
1465309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
1466309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        int32_t seq;
1467309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        CHECK(meta->findInt32("discontinuitySeq", &seq));
1468309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        if (discontinuitySeq < 0 || seq < discontinuitySeq) {
1469309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                            discontinuitySeq = seq;
14701543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                        }
14711543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    }
14721543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
1473309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    if (pickTrack) {
1474309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        // selecting track, queue discontinuities before content
1475309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        sources[j]->clear();
1476309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        if (j == kSubtitleIndex) {
1477309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                            break;
1478309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        }
1479964adb17885185808398507d2de88665fe193ee2Chong Zhang
1480964adb17885185808398507d2de88665fe193ee2Chong Zhang                        ALOGV("stream[%d]: queue format change", j);
1481964adb17885185808398507d2de88665fe193ee2Chong Zhang
1482964adb17885185808398507d2de88665fe193ee2Chong Zhang                        sources[j]->queueDiscontinuity(
1483309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                                ATSParser::DISCONTINUITY_FORMATCHANGE, NULL, true);
1484309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                    } else {
1485309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        // adapting, queue discontinuities after resume
1486309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        sources[j] = mPacketSources2.valueFor(indexToType(j));
1487309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        sources[j]->clear();
1488309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        uint32_t extraStreams = mNewStreamMask & (~mStreamMask);
1489309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        if (extraStreams & indexToType(j)) {
1490309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                            sources[j]->queueAccessUnit(createFormatChangeBuffer(/*swap*/ false));
1491309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                        }
14921543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                    }
14931543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih                }
1494a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
14958ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                streamMask &= ~indexToType(j);
14968ca002eedc747dd854b61cbe364b52c06869273fRobert Shih            }
1497a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
149814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
14998ca002eedc747dd854b61cbe364b52c06869273fRobert Shih        fetcher->startAsync(
15008ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                sources[kAudioIndex],
15018ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                sources[kVideoIndex],
15028ca002eedc747dd854b61cbe364b52c06869273fRobert Shih                sources[kSubtitleIndex],
1503309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                startTimeUs < 0 ? mLastSeekTimeUs : startTimeUs,
1504309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                segmentStartTimeUs,
1505309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                discontinuitySeq,
1506309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih                switching);
1507a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
1508a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
150914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // All fetchers have now been started, the configuration change
151014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // has completed.
1511a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
151214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    ALOGV("XXX configuration change completed.");
151314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mReconfigurationInProgress = false;
15141543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    if (switching) {
15151543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        mSwitchInProgress = true;
15161543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    } else {
15171543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        mStreamMask = mNewStreamMask;
15181543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
1519a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1520c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang    if (mDisconnectReplyID != NULL) {
152114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        finishDisconnect();
1522a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
152314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
1524a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
15251543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shihvoid LiveSession::onSwapped(const sp<AMessage> &msg) {
15261543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    int32_t switchGeneration;
15271543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    CHECK(msg->findInt32("switchGeneration", &switchGeneration));
15281543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    if (switchGeneration != mSwitchGeneration) {
15291543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return;
15301543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
15311543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
15321543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    int32_t stream;
15331543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    CHECK(msg->findInt32("stream", &stream));
1534f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih
1535f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    ssize_t idx = typeToIndex(stream);
1536f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    CHECK(idx >= 0);
1537f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    if ((mNewStreamMask & stream) && mStreams[idx].mNewUri.empty()) {
1538f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        ALOGW("swapping stream type %d %s to empty stream", stream, mStreams[idx].mUri.c_str());
1539f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    }
1540f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    mStreams[idx].mUri = mStreams[idx].mNewUri;
1541f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    mStreams[idx].mNewUri.clear();
1542f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih
1543309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    mSwapMask &= ~stream;
1544309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    if (mSwapMask != 0) {
15451543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return;
15461543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
15471543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
15481543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    // Check if new variant contains extra streams.
15491543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    uint32_t extraStreams = mNewStreamMask & (~mStreamMask);
15501543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    while (extraStreams) {
15511543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        StreamType extraStream = (StreamType) (extraStreams & ~(extraStreams - 1));
15521543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        swapPacketSource(extraStream);
15531543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        extraStreams &= ~extraStream;
1554f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih
1555f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        idx = typeToIndex(extraStream);
1556f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        CHECK(idx >= 0);
1557f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        if (mStreams[idx].mNewUri.empty()) {
1558f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            ALOGW("swapping extra stream type %d %s to empty stream",
1559f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih                    extraStream, mStreams[idx].mUri.c_str());
1560f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        }
1561f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        mStreams[idx].mUri = mStreams[idx].mNewUri;
1562f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        mStreams[idx].mNewUri.clear();
15631543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
15641543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
15651543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    tryToFinishBandwidthSwitch();
15661543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
15671543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
1568964adb17885185808398507d2de88665fe193ee2Chong Zhangvoid LiveSession::schedulePollBuffering() {
1569964adb17885185808398507d2de88665fe193ee2Chong Zhang    sp<AMessage> msg = new AMessage(kWhatPollBuffering, this);
1570964adb17885185808398507d2de88665fe193ee2Chong Zhang    msg->setInt32("generation", mPollBufferingGeneration);
1571964adb17885185808398507d2de88665fe193ee2Chong Zhang    msg->post(1000000ll);
1572964adb17885185808398507d2de88665fe193ee2Chong Zhang}
1573678bcdc852dd8f801f5c46fdc85db587b721d83dApurupa Pattapu
1574964adb17885185808398507d2de88665fe193ee2Chong Zhangvoid LiveSession::cancelPollBuffering() {
1575964adb17885185808398507d2de88665fe193ee2Chong Zhang    ++mPollBufferingGeneration;
1576964adb17885185808398507d2de88665fe193ee2Chong Zhang}
15770ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
1578964adb17885185808398507d2de88665fe193ee2Chong Zhangvoid LiveSession::onPollBuffering() {
1579964adb17885185808398507d2de88665fe193ee2Chong Zhang    ALOGV("onPollBuffering: mSwitchInProgress %d, mReconfigurationInProgress %d, "
1580964adb17885185808398507d2de88665fe193ee2Chong Zhang            "mInPreparationPhase %d, mStreamMask 0x%x",
1581964adb17885185808398507d2de88665fe193ee2Chong Zhang        mSwitchInProgress, mReconfigurationInProgress,
1582964adb17885185808398507d2de88665fe193ee2Chong Zhang        mInPreparationPhase, mStreamMask);
15830ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
1584964adb17885185808398507d2de88665fe193ee2Chong Zhang    bool low, mid, high;
1585964adb17885185808398507d2de88665fe193ee2Chong Zhang    if (checkBuffering(low, mid, high)) {
1586964adb17885185808398507d2de88665fe193ee2Chong Zhang        if (mInPreparationPhase && mid) {
1587964adb17885185808398507d2de88665fe193ee2Chong Zhang            postPrepared(OK);
15880ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih        }
15890ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
1590964adb17885185808398507d2de88665fe193ee2Chong Zhang        // don't switch before we report prepared
1591964adb17885185808398507d2de88665fe193ee2Chong Zhang        if (!mInPreparationPhase && (low || high)) {
1592964adb17885185808398507d2de88665fe193ee2Chong Zhang            switchBandwidthIfNeeded(high);
1593964adb17885185808398507d2de88665fe193ee2Chong Zhang        }
15940ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih    }
15950ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
1596964adb17885185808398507d2de88665fe193ee2Chong Zhang    schedulePollBuffering();
15970ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih}
15980ad776d2e4c6b4968d9dcd9bf34b962366b312a9Robert Shih
15991543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih// Mark switch done when:
1600309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih//   1. all old buffers are swapped out
16011543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shihvoid LiveSession::tryToFinishBandwidthSwitch() {
1602309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    if (!mSwitchInProgress) {
1603309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        return;
1604309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    }
1605309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
16061543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    bool needToRemoveFetchers = false;
16071543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
16081543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        if (mFetcherInfos.valueAt(i).mToBeRemoved) {
16091543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            needToRemoveFetchers = true;
16101543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih            break;
16111543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        }
16121543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
1613309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih
1614309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih    if (!needToRemoveFetchers && mSwapMask == 0) {
1615309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih        ALOGI("mSwitchInProgress = false");
16161543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        mStreamMask = mNewStreamMask;
16171543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        mSwitchInProgress = false;
16181543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
16191543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
16201543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
16211543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shihvoid LiveSession::cancelBandwidthSwitch() {
16221543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    Mutex::Autolock lock(mSwapMutex);
16231543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    mSwitchGeneration++;
16241543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    mSwitchInProgress = false;
16251543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    mSwapMask = 0;
1626f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih
1627f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
1628f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        FetcherInfo& info = mFetcherInfos.editValueAt(i);
1629f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        if (info.mToBeRemoved) {
1630f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            info.mToBeRemoved = false;
1631f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        }
1632f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    }
1633f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih
1634f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    for (size_t i = 0; i < kMaxStreams; ++i) {
1635f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        if (!mStreams[i].mNewUri.empty()) {
1636f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            ssize_t j = mFetcherInfos.indexOfKey(mStreams[i].mNewUri);
1637f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            if (j < 0) {
1638f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih                mStreams[i].mNewUri.clear();
1639f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih                continue;
1640f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            }
1641f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih
1642f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            const FetcherInfo &info = mFetcherInfos.valueAt(j);
1643f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            info.mFetcher->stopAsync();
1644f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            mFetcherInfos.removeItemsAt(j);
1645f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih            mStreams[i].mNewUri.clear();
1646f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih        }
1647f4a48dfa8570d6a4708a868b8b15d1236f7ca54bRobert Shih    }
16481543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
16491543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
1650964adb17885185808398507d2de88665fe193ee2Chong Zhangbool LiveSession::checkBuffering(bool &low, bool &mid, bool &high) {
1651964adb17885185808398507d2de88665fe193ee2Chong Zhang    low = mid = high = false;
1652964adb17885185808398507d2de88665fe193ee2Chong Zhang
1653964adb17885185808398507d2de88665fe193ee2Chong Zhang    if (mSwitchInProgress || mReconfigurationInProgress) {
1654964adb17885185808398507d2de88665fe193ee2Chong Zhang        ALOGV("Switch/Reconfig in progress, defer buffer polling");
16551543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return false;
16561543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
16571543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
1658964adb17885185808398507d2de88665fe193ee2Chong Zhang    // TODO: Fine tune low/high mark.
1659964adb17885185808398507d2de88665fe193ee2Chong Zhang    //       We also need to pause playback if buffering is too low.
1660964adb17885185808398507d2de88665fe193ee2Chong Zhang    //       Currently during underflow, we depend on decoder to starve
1661964adb17885185808398507d2de88665fe193ee2Chong Zhang    //       to pause, but A/V could have different buffering left,
1662964adb17885185808398507d2de88665fe193ee2Chong Zhang    //       they're not paused together.
1663964adb17885185808398507d2de88665fe193ee2Chong Zhang    // TODO: Report buffering level to NuPlayer for BUFFERING_UPDATE
1664964adb17885185808398507d2de88665fe193ee2Chong Zhang
1665964adb17885185808398507d2de88665fe193ee2Chong Zhang    // Switch down if any of the fetchers are below low mark;
1666964adb17885185808398507d2de88665fe193ee2Chong Zhang    // Switch up   if all of the fetchers are over high mark.
1667964adb17885185808398507d2de88665fe193ee2Chong Zhang    size_t activeCount, lowCount, midCount, highCount;
1668964adb17885185808398507d2de88665fe193ee2Chong Zhang    activeCount = lowCount = midCount = highCount = 0;
1669964adb17885185808398507d2de88665fe193ee2Chong Zhang    for (size_t i = 0; i < mPacketSources.size(); ++i) {
1670964adb17885185808398507d2de88665fe193ee2Chong Zhang        // we don't check subtitles for buffering level
1671964adb17885185808398507d2de88665fe193ee2Chong Zhang        if (!(mStreamMask & mPacketSources.keyAt(i)
1672964adb17885185808398507d2de88665fe193ee2Chong Zhang                & (STREAMTYPE_AUDIO | STREAMTYPE_VIDEO))) {
1673964adb17885185808398507d2de88665fe193ee2Chong Zhang            continue;
1674964adb17885185808398507d2de88665fe193ee2Chong Zhang        }
1675964adb17885185808398507d2de88665fe193ee2Chong Zhang        // ignore streams that never had any packet queued.
1676964adb17885185808398507d2de88665fe193ee2Chong Zhang        // (it's possible that the variant only has audio or video)
1677964adb17885185808398507d2de88665fe193ee2Chong Zhang        sp<AMessage> meta = mPacketSources[i]->getLatestEnqueuedMeta();
1678964adb17885185808398507d2de88665fe193ee2Chong Zhang        if (meta == NULL) {
1679964adb17885185808398507d2de88665fe193ee2Chong Zhang            continue;
1680964adb17885185808398507d2de88665fe193ee2Chong Zhang        }
1681964adb17885185808398507d2de88665fe193ee2Chong Zhang
1682964adb17885185808398507d2de88665fe193ee2Chong Zhang        ++activeCount;
1683964adb17885185808398507d2de88665fe193ee2Chong Zhang        int64_t bufferedDurationUs =
1684964adb17885185808398507d2de88665fe193ee2Chong Zhang                mPacketSources[i]->getEstimatedDurationUs();
1685964adb17885185808398507d2de88665fe193ee2Chong Zhang        ALOGV("source[%d]: buffered %lld us", i, bufferedDurationUs);
1686964adb17885185808398507d2de88665fe193ee2Chong Zhang        if (bufferedDurationUs < kLowWaterMark) {
1687964adb17885185808398507d2de88665fe193ee2Chong Zhang            ++lowCount;
1688964adb17885185808398507d2de88665fe193ee2Chong Zhang            break;
1689964adb17885185808398507d2de88665fe193ee2Chong Zhang        } else if (bufferedDurationUs > kHighWaterMark) {
1690964adb17885185808398507d2de88665fe193ee2Chong Zhang            ++midCount;
1691964adb17885185808398507d2de88665fe193ee2Chong Zhang            ++highCount;
1692964adb17885185808398507d2de88665fe193ee2Chong Zhang        } else if (bufferedDurationUs > kMidWaterMark) {
1693964adb17885185808398507d2de88665fe193ee2Chong Zhang            ++midCount;
1694964adb17885185808398507d2de88665fe193ee2Chong Zhang        }
169514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
169614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
1697964adb17885185808398507d2de88665fe193ee2Chong Zhang    if (activeCount > 0) {
1698964adb17885185808398507d2de88665fe193ee2Chong Zhang        high = (highCount == activeCount);
1699964adb17885185808398507d2de88665fe193ee2Chong Zhang        mid = (midCount == activeCount);
1700964adb17885185808398507d2de88665fe193ee2Chong Zhang        low = (lowCount > 0);
17011543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih        return true;
17021543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih    }
1703964adb17885185808398507d2de88665fe193ee2Chong Zhang
1704964adb17885185808398507d2de88665fe193ee2Chong Zhang    return false;
17051543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih}
17061543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih
1707964adb17885185808398507d2de88665fe193ee2Chong Zhangvoid LiveSession::switchBandwidthIfNeeded(bool canSwitchUp) {
1708964adb17885185808398507d2de88665fe193ee2Chong Zhang    ssize_t bandwidthIndex = getBandwidthIndex();
1709964adb17885185808398507d2de88665fe193ee2Chong Zhang
1710964adb17885185808398507d2de88665fe193ee2Chong Zhang    if ((canSwitchUp && bandwidthIndex > mCurBandwidthIndex)
1711964adb17885185808398507d2de88665fe193ee2Chong Zhang            || (!canSwitchUp && bandwidthIndex < mCurBandwidthIndex)) {
1712964adb17885185808398507d2de88665fe193ee2Chong Zhang        changeConfiguration(-1, bandwidthIndex, false);
171314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
1714a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
1715a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
171614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid LiveSession::postPrepared(status_t err) {
171714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    CHECK(mInPreparationPhase);
1718a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
171914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    sp<AMessage> notify = mNotify->dup();
172014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (err == OK || err == ERROR_END_OF_STREAM) {
172114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        notify->setInt32("what", kWhatPrepared);
172214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    } else {
172314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        notify->setInt32("what", kWhatPreparationFailed);
172414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        notify->setInt32("err", err);
172514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
1726a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
172714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    notify->post();
1728a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
172914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mInPreparationPhase = false;
1730b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber}
1731b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber
1732964adb17885185808398507d2de88665fe193ee2Chong Zhang
1733a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}  // namespace android
1734a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1735