LiveSession.cpp revision 29357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47
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
21a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include "include/LiveSession.h"
22a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
23a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include "LiveDataSource.h"
24a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
25a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include "include/M3UParser.h"
261156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber#include "include/HTTPBase.h"
27a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
28a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <cutils/properties.h>
29a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <media/stagefright/foundation/hexdump.h>
30a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <media/stagefright/foundation/ABuffer.h>
31a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <media/stagefright/foundation/ADebug.h>
32a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <media/stagefright/foundation/AMessage.h>
33a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <media/stagefright/DataSource.h>
34a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <media/stagefright/FileSource.h>
35a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <media/stagefright/MediaErrors.h>
36a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
37a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <ctype.h>
38a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <openssl/aes.h>
397e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber#include <openssl/md5.h>
40a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
41a44153c1a57202fb538659eb50706e60454d6273Andreas Hubernamespace android {
42a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
439b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas HuberLiveSession::LiveSession(uint32_t flags, bool uidValid, uid_t uid)
447314fa17093d514199fedcb55ac41136a1b31cb3Andreas Huber    : mFlags(flags),
459b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber      mUIDValid(uidValid),
469b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber      mUID(uid),
477314fa17093d514199fedcb55ac41136a1b31cb3Andreas Huber      mDataSource(new LiveDataSource),
487314fa17093d514199fedcb55ac41136a1b31cb3Andreas Huber      mHTTPDataSource(
491156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber              HTTPBase::Create(
507314fa17093d514199fedcb55ac41136a1b31cb3Andreas Huber                  (mFlags & kFlagIncognito)
511156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                    ? HTTPBase::kFlagIncognito
527314fa17093d514199fedcb55ac41136a1b31cb3Andreas Huber                    : 0)),
53a44153c1a57202fb538659eb50706e60454d6273Andreas Huber      mPrevBandwidthIndex(-1),
54a44153c1a57202fb538659eb50706e60454d6273Andreas Huber      mLastPlaylistFetchTimeUs(-1),
55a44153c1a57202fb538659eb50706e60454d6273Andreas Huber      mSeqNumber(-1),
56a44153c1a57202fb538659eb50706e60454d6273Andreas Huber      mSeekTimeUs(-1),
57a44153c1a57202fb538659eb50706e60454d6273Andreas Huber      mNumRetries(0),
58a44153c1a57202fb538659eb50706e60454d6273Andreas Huber      mDurationUs(-1),
59a44153c1a57202fb538659eb50706e60454d6273Andreas Huber      mSeekDone(false),
60ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber      mDisconnectPending(false),
617e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber      mMonitorQueueGeneration(0),
627e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber      mRefreshState(INITIAL_MINIMUM_RELOAD_DELAY) {
639b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber    if (mUIDValid) {
649b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber        mHTTPDataSource->setUID(mUID);
659b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber    }
66a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
67a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
68a44153c1a57202fb538659eb50706e60454d6273Andreas HuberLiveSession::~LiveSession() {
69a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
70a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
71a44153c1a57202fb538659eb50706e60454d6273Andreas Hubersp<DataSource> LiveSession::getDataSource() {
72a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return mDataSource;
73a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
74a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
75ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Hubervoid LiveSession::connect(
76ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        const char *url, const KeyedVector<String8, String8> *headers) {
77a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<AMessage> msg = new AMessage(kWhatConnect, id());
78a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    msg->setString("url", url);
79ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber
80ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    if (headers != NULL) {
81ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        msg->setPointer(
82ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber                "headers",
83ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber                new KeyedVector<String8, String8>(*headers));
84ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    }
85ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber
86a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    msg->post();
87a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
88a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
89a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::disconnect() {
90ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber    Mutex::Autolock autoLock(mLock);
91ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber    mDisconnectPending = true;
92ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
93ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber    mHTTPDataSource->disconnect();
94ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
95a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    (new AMessage(kWhatDisconnect, id()))->post();
96a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
97a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
98a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::seekTo(int64_t timeUs) {
99a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    Mutex::Autolock autoLock(mLock);
100a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    mSeekDone = false;
101a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
102a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<AMessage> msg = new AMessage(kWhatSeek, id());
103a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    msg->setInt64("timeUs", timeUs);
104a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    msg->post();
105a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
106a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    while (!mSeekDone) {
107a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        mCondition.wait(mLock);
108a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
109a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
110a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
111a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onMessageReceived(const sp<AMessage> &msg) {
112a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    switch (msg->what()) {
113a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        case kWhatConnect:
114a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            onConnect(msg);
115a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
116a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
117a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        case kWhatDisconnect:
118a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            onDisconnect();
119a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
120a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
121a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        case kWhatMonitorQueue:
122a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        {
123a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            int32_t generation;
124a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            CHECK(msg->findInt32("generation", &generation));
125a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
126a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            if (generation != mMonitorQueueGeneration) {
127a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                // Stale event
128a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                break;
129a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            }
130a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
131a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            onMonitorQueue();
132a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
133a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
134a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
135a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        case kWhatSeek:
136a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            onSeek(msg);
137a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
138a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
139a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        default:
140a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            TRESPASS();
141a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
142a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
143a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
144a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
145a44153c1a57202fb538659eb50706e60454d6273Andreas Huber// static
146a44153c1a57202fb538659eb50706e60454d6273Andreas Huberint LiveSession::SortByBandwidth(const BandwidthItem *a, const BandwidthItem *b) {
147a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (a->mBandwidth < b->mBandwidth) {
148a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return -1;
149a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else if (a->mBandwidth == b->mBandwidth) {
150a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return 0;
151a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
152a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
153a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return 1;
154a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
155a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
156a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onConnect(const sp<AMessage> &msg) {
157a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    AString url;
158a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    CHECK(msg->findString("url", &url));
159a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
160ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    KeyedVector<String8, String8> *headers = NULL;
161ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    if (!msg->findPointer("headers", (void **)&headers)) {
162ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        mExtraHeaders.clear();
163ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    } else {
164ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        mExtraHeaders = *headers;
165ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber
166ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        delete headers;
167ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        headers = NULL;
168ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    }
169ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber
1707314fa17093d514199fedcb55ac41136a1b31cb3Andreas Huber    if (!(mFlags & kFlagIncognito)) {
171df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("onConnect '%s'", url.c_str());
1727314fa17093d514199fedcb55ac41136a1b31cb3Andreas Huber    } else {
173df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("onConnect <URL suppressed>");
1747314fa17093d514199fedcb55ac41136a1b31cb3Andreas Huber    }
175a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
176a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    mMasterURL = url;
177a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1787e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    bool dummy;
1797e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    sp<M3UParser> playlist = fetchPlaylist(url.c_str(), &dummy);
180ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
181ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber    if (playlist == NULL) {
18229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("unable to fetch master playlist '%s'.", url.c_str());
183ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
184ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber        mDataSource->queueEOS(ERROR_IO);
185ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber        return;
186ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber    }
187a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
188a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (playlist->isVariantPlaylist()) {
189a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        for (size_t i = 0; i < playlist->size(); ++i) {
190a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            BandwidthItem item;
191a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
192a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            sp<AMessage> meta;
193a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            playlist->itemAt(i, &item.mURI, &meta);
194a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
195a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            unsigned long bandwidth;
196a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            CHECK(meta->findInt32("bandwidth", (int32_t *)&item.mBandwidth));
197a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
198a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            mBandwidthItems.push(item);
199a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
200a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
201a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        CHECK_GT(mBandwidthItems.size(), 0u);
202a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
203a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        mBandwidthItems.sort(SortByBandwidth);
204a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
205a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
206a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    postMonitorQueue();
207a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
208a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
209a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onDisconnect() {
210df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("onDisconnect");
211a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
212a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    mDataSource->queueEOS(ERROR_END_OF_STREAM);
213ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
214ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber    Mutex::Autolock autoLock(mLock);
215ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber    mDisconnectPending = false;
216a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
217a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
2182aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huberstatus_t LiveSession::fetchFile(
2192aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        const char *url, sp<ABuffer> *out,
2202aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        int64_t range_offset, int64_t range_length) {
221a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    *out = NULL;
222a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
223a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<DataSource> source;
224a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
225a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (!strncasecmp(url, "file://", 7)) {
226a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        source = new FileSource(url + 7);
2278cb0c4168bf4b678e4a6edfcf409247016be20d5Andreas Huber    } else if (strncasecmp(url, "http://", 7)
2288cb0c4168bf4b678e4a6edfcf409247016be20d5Andreas Huber            && strncasecmp(url, "https://", 8)) {
229df42f949c8bd05b81d94633767514fff88f52062Andreas Huber        return ERROR_UNSUPPORTED;
230a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else {
231ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber        {
232ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber            Mutex::Autolock autoLock(mLock);
233ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
234ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber            if (mDisconnectPending) {
235ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber                return ERROR_IO;
236ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber            }
237ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber        }
238ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
2392aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        KeyedVector<String8, String8> headers = mExtraHeaders;
2402aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        if (range_offset > 0 || range_length >= 0) {
2412aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber            headers.add(
2422aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                    String8("Range"),
2432aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                    String8(
2442aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                        StringPrintf(
2452aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                            "bytes=%lld-%s",
2462aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                            range_offset,
2472aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                            range_length < 0
2482aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                                ? "" : StringPrintf("%lld", range_offset + range_length - 1).c_str()).c_str()));
2492aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        }
2502aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        status_t err = mHTTPDataSource->connect(url, &headers);
251a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
252a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (err != OK) {
253a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            return err;
254a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
255a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
256a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        source = mHTTPDataSource;
257a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
258a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
259a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    off64_t size;
260a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    status_t err = source->getSize(&size);
261a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
262a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (err != OK) {
263a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        size = 65536;
264a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
265a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
266a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<ABuffer> buffer = new ABuffer(size);
267a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    buffer->setRange(0, 0);
268a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
269a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    for (;;) {
270a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        size_t bufferRemaining = buffer->capacity() - buffer->size();
271a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
272a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (bufferRemaining == 0) {
273a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            bufferRemaining = 32768;
274a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
2753856b090cd04ba5dd4a59a12430ed724d5995909Steve Block            ALOGV("increasing download buffer to %d bytes",
276a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                 buffer->size() + bufferRemaining);
277a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
278a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            sp<ABuffer> copy = new ABuffer(buffer->size() + bufferRemaining);
279a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            memcpy(copy->data(), buffer->data(), buffer->size());
280a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            copy->setRange(0, buffer->size());
281a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
282a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            buffer = copy;
283a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
284a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
2852aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        size_t maxBytesToRead = bufferRemaining;
2862aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        if (range_length >= 0) {
2872aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber            int64_t bytesLeftInRange = range_length - buffer->size();
2882aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber            if (bytesLeftInRange < maxBytesToRead) {
2892aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                maxBytesToRead = bytesLeftInRange;
2902aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber
2912aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                if (bytesLeftInRange == 0) {
2922aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                    break;
2932aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                }
2942aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber            }
2952aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        }
2962aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber
297a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        ssize_t n = source->readAt(
298a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                buffer->size(), buffer->data() + buffer->size(),
2992aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                maxBytesToRead);
300a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
301a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (n < 0) {
30220ad3a341a96e7746015ccb7369fa567897e11f6Andreas Huber            return n;
303a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
304a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
305a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (n == 0) {
306a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
307a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
308a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
309a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        buffer->setRange(0, buffer->size() + (size_t)n);
310a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
311a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
312a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    *out = buffer;
313a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
314a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return OK;
315a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
316a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
3177e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Hubersp<M3UParser> LiveSession::fetchPlaylist(const char *url, bool *unchanged) {
3187e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    *unchanged = false;
3197e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
320a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<ABuffer> buffer;
321a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    status_t err = fetchFile(url, &buffer);
322a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
323a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (err != OK) {
324a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return NULL;
325a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
326a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
3277e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    // MD5 functionality is not available on the simulator, treat all
3287e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    // playlists as changed.
3297e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
3307e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber#if defined(HAVE_ANDROID_OS)
3317e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    uint8_t hash[16];
3327e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
3337e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    MD5_CTX m;
3347e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    MD5_Init(&m);
3357e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    MD5_Update(&m, buffer->data(), buffer->size());
3367e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
3377e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    MD5_Final(hash, &m);
3387e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
3397e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    if (mPlaylist != NULL && !memcmp(hash, mPlaylistHash, 16)) {
3407e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        // playlist unchanged
3417e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
3427e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        if (mRefreshState != THIRD_UNCHANGED_RELOAD_ATTEMPT) {
3437e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            mRefreshState = (RefreshState)(mRefreshState + 1);
3447e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        }
3457e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
3467e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        *unchanged = true;
3477e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
3483856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("Playlist unchanged, refresh state is now %d",
3497e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber             (int)mRefreshState);
3507e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
3517e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        return NULL;
3527e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    }
3537e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
3547e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    memcpy(mPlaylistHash, hash, sizeof(hash));
3557e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
3567e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    mRefreshState = INITIAL_MINIMUM_RELOAD_DELAY;
3577e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber#endif
3587e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
359a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<M3UParser> playlist =
360a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        new M3UParser(url, buffer->data(), buffer->size());
361a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
362a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (playlist->initCheck() != OK) {
36329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("failed to parse .m3u8 playlist");
3649067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber
365a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return NULL;
366a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
367a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
368a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return playlist;
369a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
370a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
371a44153c1a57202fb538659eb50706e60454d6273Andreas Huberstatic double uniformRand() {
372a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return (double)rand() / RAND_MAX;
373a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
374a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
375a44153c1a57202fb538659eb50706e60454d6273Andreas Hubersize_t LiveSession::getBandwidthIndex() {
376a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (mBandwidthItems.size() == 0) {
377a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return 0;
378a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
379a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
380a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#if 1
381a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    int32_t bandwidthBps;
382a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (mHTTPDataSource != NULL
383a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            && mHTTPDataSource->estimateBandwidth(&bandwidthBps)) {
3843856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("bandwidth estimated at %.2f kbps", bandwidthBps / 1024.0f);
385a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else {
3863856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("no bandwidth estimate.");
387a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return 0;  // Pick the lowest bandwidth stream by default.
388a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
389a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
390a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    char value[PROPERTY_VALUE_MAX];
391a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (property_get("media.httplive.max-bw", value, NULL)) {
392a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        char *end;
393a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        long maxBw = strtoul(value, &end, 10);
394a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (end > value && *end == '\0') {
395a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            if (maxBw > 0 && bandwidthBps > maxBw) {
3963856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("bandwidth capped to %ld bps", maxBw);
397a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                bandwidthBps = maxBw;
398a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            }
399a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
400a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
401a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
402a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // Consider only 80% of the available bandwidth usable.
403a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    bandwidthBps = (bandwidthBps * 8) / 10;
404a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
405a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // Pick the highest bandwidth stream below or equal to estimated bandwidth.
406a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
407a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index = mBandwidthItems.size() - 1;
408a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    while (index > 0 && mBandwidthItems.itemAt(index).mBandwidth
409a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                            > (size_t)bandwidthBps) {
410a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        --index;
411a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
412a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0
413a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // Change bandwidth at random()
414a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index = uniformRand() * mBandwidthItems.size();
415a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0
416a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // There's a 50% chance to stay on the current bandwidth and
417a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // a 50% chance to switch to the next higher bandwidth (wrapping around
418a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // to lowest)
419a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    const size_t kMinIndex = 0;
420a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
421a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index;
422a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (mPrevBandwidthIndex < 0) {
423a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        index = kMinIndex;
424a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else if (uniformRand() < 0.5) {
425a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        index = (size_t)mPrevBandwidthIndex;
426a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else {
427a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        index = mPrevBandwidthIndex + 1;
428a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (index == mBandwidthItems.size()) {
429a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            index = kMinIndex;
430a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
431a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
432a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0
433a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // Pick the highest bandwidth stream below or equal to 1.2 Mbit/sec
434a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
435a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index = mBandwidthItems.size() - 1;
436a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    while (index > 0 && mBandwidthItems.itemAt(index).mBandwidth > 1200000) {
437a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        --index;
438a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
439a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#else
440a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index = mBandwidthItems.size() - 1;  // Highest bandwidth stream
441a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#endif
442a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
443a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return index;
444a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
445a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
4467e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huberbool LiveSession::timeToRefreshPlaylist(int64_t nowUs) const {
4477e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    if (mPlaylist == NULL) {
4487e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        CHECK_EQ((int)mRefreshState, (int)INITIAL_MINIMUM_RELOAD_DELAY);
4497e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        return true;
4507e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    }
4517e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
4527e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    int32_t targetDurationSecs;
4537e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    CHECK(mPlaylist->meta()->findInt32("target-duration", &targetDurationSecs));
4547e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
4557e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    int64_t targetDurationUs = targetDurationSecs * 1000000ll;
4567e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
4577e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    int64_t minPlaylistAgeUs;
4587e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
4597e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    switch (mRefreshState) {
4607e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        case INITIAL_MINIMUM_RELOAD_DELAY:
4617e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        {
4627e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            size_t n = mPlaylist->size();
4637e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            if (n > 0) {
4647e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber                sp<AMessage> itemMeta;
4657e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber                CHECK(mPlaylist->itemAt(n - 1, NULL /* uri */, &itemMeta));
4667e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
4677e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber                int64_t itemDurationUs;
4687e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber                CHECK(itemMeta->findInt64("durationUs", &itemDurationUs));
4697e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
4707e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber                minPlaylistAgeUs = itemDurationUs;
4717e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber                break;
4727e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            }
4737e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
4747e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            // fall through
4757e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        }
4767e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
4777e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        case FIRST_UNCHANGED_RELOAD_ATTEMPT:
4787e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        {
4797e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            minPlaylistAgeUs = targetDurationUs / 2;
4807e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            break;
4817e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        }
4827e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
4837e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        case SECOND_UNCHANGED_RELOAD_ATTEMPT:
4847e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        {
4857e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            minPlaylistAgeUs = (targetDurationUs * 3) / 2;
4867e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            break;
4877e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        }
4887e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
4897e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        case THIRD_UNCHANGED_RELOAD_ATTEMPT:
4907e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        {
4917e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            minPlaylistAgeUs = targetDurationUs * 3;
4927e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            break;
4937e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        }
4947e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
4957e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        default:
4967e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            TRESPASS();
4977e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            break;
4987e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    }
4997e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
5007e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    return mLastPlaylistFetchTimeUs + minPlaylistAgeUs <= nowUs;
5017e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber}
5027e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
503a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onDownloadNext() {
504a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t bandwidthIndex = getBandwidthIndex();
505a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
506aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huberrinse_repeat:
507a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    int64_t nowUs = ALooper::GetNowUs();
508a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
509a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (mLastPlaylistFetchTimeUs < 0
510a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            || (ssize_t)bandwidthIndex != mPrevBandwidthIndex
5117e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            || (!mPlaylist->isComplete() && timeToRefreshPlaylist(nowUs))) {
512a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        AString url;
513a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (mBandwidthItems.size() > 0) {
514a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            url = mBandwidthItems.editItemAt(bandwidthIndex).mURI;
515a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        } else {
516a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            url = mMasterURL;
517a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
518a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
519a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        bool firstTime = (mPlaylist == NULL);
520a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
5218dae4ca229d21f68f3ee76c76b49b6f0a47aad53Andreas Huber        if ((ssize_t)bandwidthIndex != mPrevBandwidthIndex) {
5228dae4ca229d21f68f3ee76c76b49b6f0a47aad53Andreas Huber            // If we switch bandwidths, do not pay any heed to whether
5238dae4ca229d21f68f3ee76c76b49b6f0a47aad53Andreas Huber            // playlists changed since the last time...
5248dae4ca229d21f68f3ee76c76b49b6f0a47aad53Andreas Huber            mPlaylist.clear();
5258dae4ca229d21f68f3ee76c76b49b6f0a47aad53Andreas Huber        }
5268dae4ca229d21f68f3ee76c76b49b6f0a47aad53Andreas Huber
5277e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        bool unchanged;
5287e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        sp<M3UParser> playlist = fetchPlaylist(url.c_str(), &unchanged);
5297e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        if (playlist == NULL) {
5307e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            if (unchanged) {
5317e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber                // We succeeded in fetching the playlist, but it was
5327e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber                // unchanged from the last time we tried.
5337e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            } else {
53429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("failed to load playlist at url '%s'", url.c_str());
5357e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber                mDataSource->queueEOS(ERROR_IO);
5367e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber                return;
5377e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            }
5387e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        } else {
5397e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            mPlaylist = playlist;
5406e6b1cae2bac1b78205cefab8e4e9e9538982965Andreas Huber        }
541a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
542a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (firstTime) {
543a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            Mutex::Autolock autoLock(mLock);
544a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
5450f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber            if (!mPlaylist->isComplete()) {
546a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                mDurationUs = -1;
547a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            } else {
5480f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                mDurationUs = 0;
5490f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                for (size_t i = 0; i < mPlaylist->size(); ++i) {
5500f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                    sp<AMessage> itemMeta;
5510f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                    CHECK(mPlaylist->itemAt(
5520f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                                i, NULL /* uri */, &itemMeta));
5530f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber
5540f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                    int64_t itemDurationUs;
5550f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                    CHECK(itemMeta->findInt64("durationUs", &itemDurationUs));
5560f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber
5570f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                    mDurationUs += itemDurationUs;
5580f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                }
559a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            }
560a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
561a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
562a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        mLastPlaylistFetchTimeUs = ALooper::GetNowUs();
563a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
564a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
565a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    int32_t firstSeqNumberInPlaylist;
566a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (mPlaylist->meta() == NULL || !mPlaylist->meta()->findInt32(
567a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                "media-sequence", &firstSeqNumberInPlaylist)) {
568a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        firstSeqNumberInPlaylist = 0;
569a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
570a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
57120f725ebcef13ded1b4b85c61c8a4b37cd030656Andreas Huber    bool seekDiscontinuity = false;
572a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    bool explicitDiscontinuity = false;
57322fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber    bool bandwidthChanged = false;
574a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
575a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (mSeekTimeUs >= 0) {
5760f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber        if (mPlaylist->isComplete()) {
5770f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber            size_t index = 0;
5780f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber            int64_t segmentStartUs = 0;
5790f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber            while (index < mPlaylist->size()) {
5800f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                sp<AMessage> itemMeta;
5810f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                CHECK(mPlaylist->itemAt(
5820f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                            index, NULL /* uri */, &itemMeta));
5830f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber
5840f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                int64_t itemDurationUs;
5850f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                CHECK(itemMeta->findInt64("durationUs", &itemDurationUs));
5860f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber
5870f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                if (mSeekTimeUs < segmentStartUs + itemDurationUs) {
5880f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                    break;
5890f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                }
5900f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber
5910f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                segmentStartUs += itemDurationUs;
5920f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                ++index;
5930f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber            }
5940f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber
5950f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber            if (index < mPlaylist->size()) {
59643c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber                int32_t newSeqNumber = firstSeqNumberInPlaylist + index;
597a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
59843c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber                if (newSeqNumber != mSeqNumber) {
599df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block                    ALOGI("seeking to seq no %d", newSeqNumber);
60043c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
60143c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber                    mSeqNumber = newSeqNumber;
60243c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
60343c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber                    mDataSource->reset();
60443c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
60522fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber                    // reseting the data source will have had the
60622fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber                    // side effect of discarding any previously queued
60722fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber                    // bandwidth change discontinuity.
60820f725ebcef13ded1b4b85c61c8a4b37cd030656Andreas Huber                    // Therefore we'll need to treat these seek
60922fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber                    // discontinuities as involving a bandwidth change
61022fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber                    // even if they aren't directly.
61120f725ebcef13ded1b4b85c61c8a4b37cd030656Andreas Huber                    seekDiscontinuity = true;
61222fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber                    bandwidthChanged = true;
61343c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber                }
614a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            }
615a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
616a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
617a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        mSeekTimeUs = -1;
618a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
619a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        Mutex::Autolock autoLock(mLock);
620a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        mSeekDone = true;
621a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        mCondition.broadcast();
622a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
623a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
624a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (mSeqNumber < 0) {
62520f725ebcef13ded1b4b85c61c8a4b37cd030656Andreas Huber        mSeqNumber = firstSeqNumberInPlaylist;
626a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
627a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
628a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    int32_t lastSeqNumberInPlaylist =
629a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        firstSeqNumberInPlaylist + (int32_t)mPlaylist->size() - 1;
630a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
631a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (mSeqNumber < firstSeqNumberInPlaylist
632a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            || mSeqNumber > lastSeqNumberInPlaylist) {
63388b7ad413c4b6d08697069b18488641d6ce31fd3Andreas Huber        if (mPrevBandwidthIndex != (ssize_t)bandwidthIndex) {
634aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber            // Go back to the previous bandwidth.
635aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber
636df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block            ALOGI("new bandwidth does not have the sequence number "
637aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber                 "we're looking for, switching back to previous bandwidth");
638aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber
639aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber            mLastPlaylistFetchTimeUs = -1;
640aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber            bandwidthIndex = mPrevBandwidthIndex;
641aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber            goto rinse_repeat;
642aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber        }
643aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber
6446801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber        if (!mPlaylist->isComplete() && mNumRetries < kMaxNumRetries) {
645a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            ++mNumRetries;
646a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
6476801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber            if (mSeqNumber > lastSeqNumberInPlaylist) {
6486801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber                mLastPlaylistFetchTimeUs = -1;
6496801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber                postMonitorQueue(3000000ll);
6506801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber                return;
6516801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber            }
652a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
6536801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber            // we've missed the boat, let's start from the lowest sequence
6546801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber            // number available and signal a discontinuity.
655a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
656df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block            ALOGI("We've missed the boat, restarting playback.");
6576801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber            mSeqNumber = lastSeqNumberInPlaylist;
6586801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber            explicitDiscontinuity = true;
6596801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber
6606801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber            // fall through
6616801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber        } else {
66229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Cannot find sequence number %d in playlist "
6636801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber                 "(contains %d - %d)",
6646801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber                 mSeqNumber, firstSeqNumberInPlaylist,
6656801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber                 firstSeqNumberInPlaylist + mPlaylist->size() - 1);
6666801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber
6676801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber            mDataSource->queueEOS(ERROR_END_OF_STREAM);
6686801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber            return;
6696801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber        }
670a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
671a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
672a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    mNumRetries = 0;
673a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
674a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    AString uri;
675a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<AMessage> itemMeta;
676a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    CHECK(mPlaylist->itemAt(
677a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                mSeqNumber - firstSeqNumberInPlaylist,
678a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                &uri,
679a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                &itemMeta));
680a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
681a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    int32_t val;
682a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (itemMeta->findInt32("discontinuity", &val) && val != 0) {
683a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        explicitDiscontinuity = true;
684a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
685a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
6862aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber    int64_t range_offset, range_length;
6872aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber    if (!itemMeta->findInt64("range-offset", &range_offset)
6882aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber            || !itemMeta->findInt64("range-length", &range_length)) {
6892aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        range_offset = 0;
6902aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        range_length = -1;
6912aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber    }
6922aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber
693a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<ABuffer> buffer;
6942aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber    status_t err = fetchFile(uri.c_str(), &buffer, range_offset, range_length);
6956e6b1cae2bac1b78205cefab8e4e9e9538982965Andreas Huber    if (err != OK) {
69629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("failed to fetch .ts segment at url '%s'", uri.c_str());
6976e6b1cae2bac1b78205cefab8e4e9e9538982965Andreas Huber        mDataSource->queueEOS(err);
6986e6b1cae2bac1b78205cefab8e4e9e9538982965Andreas Huber        return;
6996e6b1cae2bac1b78205cefab8e4e9e9538982965Andreas Huber    }
700a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
70143c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber    CHECK(buffer != NULL);
70243c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
70388b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber    err = decryptBuffer(mSeqNumber - firstSeqNumberInPlaylist, buffer);
70488b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber
70588b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber    if (err != OK) {
70629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("decryptBuffer failed w/ error %d", err);
70788b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber
70888b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber        mDataSource->queueEOS(err);
70988b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber        return;
71088b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber    }
711a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
712a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (buffer->size() == 0 || buffer->data()[0] != 0x47) {
713a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        // Not a transport stream???
714a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
71529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("This doesn't look like a transport stream...");
716a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
717bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber        mBandwidthItems.removeAt(bandwidthIndex);
718bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
719bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber        if (mBandwidthItems.isEmpty()) {
720bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber            mDataSource->queueEOS(ERROR_UNSUPPORTED);
721bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber            return;
722bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber        }
723bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
724df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("Retrying with a different bandwidth stream.");
725bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
726bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber        mLastPlaylistFetchTimeUs = -1;
727bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber        bandwidthIndex = getBandwidthIndex();
728bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber        mPrevBandwidthIndex = bandwidthIndex;
729bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber        mSeqNumber = -1;
730bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
731bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber        goto rinse_repeat;
732a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
733a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
73422fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber    if ((size_t)mPrevBandwidthIndex != bandwidthIndex) {
73522fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber        bandwidthChanged = true;
73622fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber    }
73722fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber
73822fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber    if (mPrevBandwidthIndex < 0) {
73922fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber        // Don't signal a bandwidth change at the very beginning of
74022fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber        // playback.
74122fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber        bandwidthChanged = false;
74222fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber    }
7433831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber
74420f725ebcef13ded1b4b85c61c8a4b37cd030656Andreas Huber    if (seekDiscontinuity || explicitDiscontinuity || bandwidthChanged) {
745a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        // Signal discontinuity.
746a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
747df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("queueing discontinuity (seek=%d, explicit=%d, bandwidthChanged=%d)",
74820f725ebcef13ded1b4b85c61c8a4b37cd030656Andreas Huber             seekDiscontinuity, explicitDiscontinuity, bandwidthChanged);
74943c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
750a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        sp<ABuffer> tmp = new ABuffer(188);
751a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        memset(tmp->data(), 0, tmp->size());
75220f725ebcef13ded1b4b85c61c8a4b37cd030656Andreas Huber
75320f725ebcef13ded1b4b85c61c8a4b37cd030656Andreas Huber        // signal a 'hard' discontinuity for explicit or bandwidthChanged.
75420f725ebcef13ded1b4b85c61c8a4b37cd030656Andreas Huber        tmp->data()[1] = (explicitDiscontinuity || bandwidthChanged) ? 1 : 0;
755a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
756a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        mDataSource->queueBuffer(tmp);
757a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
758a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
759a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    mDataSource->queueBuffer(buffer);
760a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
761a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    mPrevBandwidthIndex = bandwidthIndex;
762a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    ++mSeqNumber;
763a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
764a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    postMonitorQueue();
765a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
766a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
767a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onMonitorQueue() {
768a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (mSeekTimeUs >= 0
769a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            || mDataSource->countQueuedBuffers() < kMaxNumQueuedFragments) {
770a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        onDownloadNext();
771a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else {
772a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        postMonitorQueue(1000000ll);
773a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
774a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
775a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
776a44153c1a57202fb538659eb50706e60454d6273Andreas Huberstatus_t LiveSession::decryptBuffer(
777a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        size_t playlistIndex, const sp<ABuffer> &buffer) {
778a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<AMessage> itemMeta;
779a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    bool found = false;
780a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    AString method;
781a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
782a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    for (ssize_t i = playlistIndex; i >= 0; --i) {
783a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        AString uri;
784a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        CHECK(mPlaylist->itemAt(i, &uri, &itemMeta));
785a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
786a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (itemMeta->findString("cipher-method", &method)) {
787a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            found = true;
788a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
789a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
790a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
791a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
792a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (!found) {
793a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        method = "NONE";
794a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
795a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
796a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (method == "NONE") {
797a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return OK;
798a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else if (!(method == "AES-128")) {
79929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Unsupported cipher method '%s'", method.c_str());
800a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return ERROR_UNSUPPORTED;
801a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
802a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
803a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    AString keyURI;
804a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (!itemMeta->findString("cipher-uri", &keyURI)) {
80529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Missing key uri");
806a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return ERROR_MALFORMED;
807a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
808a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
809a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    ssize_t index = mAESKeyForURI.indexOfKey(keyURI);
810a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
811a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<ABuffer> key;
812a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (index >= 0) {
813a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        key = mAESKeyForURI.valueAt(index);
814a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else {
815a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        key = new ABuffer(16);
816a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
8171156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        sp<HTTPBase> keySource =
8181156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber              HTTPBase::Create(
8191156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                  (mFlags & kFlagIncognito)
8201156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                    ? HTTPBase::kFlagIncognito
8211156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                    : 0);
8221156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
8239b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber        if (mUIDValid) {
8249b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber            keySource->setUID(mUID);
8259b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber        }
8269b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber
827d6a46a6bda23667e06ee5ccca3781e407c7d1204Andreas Huber        status_t err =
828d6a46a6bda23667e06ee5ccca3781e407c7d1204Andreas Huber            keySource->connect(
829d6a46a6bda23667e06ee5ccca3781e407c7d1204Andreas Huber                    keyURI.c_str(),
830d6a46a6bda23667e06ee5ccca3781e407c7d1204Andreas Huber                    mExtraHeaders.isEmpty() ? NULL : &mExtraHeaders);
831a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
832a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (err == OK) {
833a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            size_t offset = 0;
834a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            while (offset < 16) {
835a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                ssize_t n = keySource->readAt(
836a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                        offset, key->data() + offset, 16 - offset);
837a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                if (n <= 0) {
838a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                    err = ERROR_IO;
839a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                    break;
840a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                }
841a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
842a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                offset += n;
843a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            }
844a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
845a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
846a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (err != OK) {
84729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("failed to fetch cipher key from '%s'.", keyURI.c_str());
848a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            return ERROR_IO;
849a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
850a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
851a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        mAESKeyForURI.add(keyURI, key);
852a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
853a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
854a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    AES_KEY aes_key;
855a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (AES_set_decrypt_key(key->data(), 128, &aes_key) != 0) {
85629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("failed to set AES decryption key.");
857a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return UNKNOWN_ERROR;
858a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
859a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
860a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    unsigned char aes_ivec[16];
861a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
862a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    AString iv;
863a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (itemMeta->findString("cipher-iv", &iv)) {
864a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if ((!iv.startsWith("0x") && !iv.startsWith("0X"))
865a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                || iv.size() != 16 * 2 + 2) {
86629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("malformed cipher IV '%s'.", iv.c_str());
867a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            return ERROR_MALFORMED;
868a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
869a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
870a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        memset(aes_ivec, 0, sizeof(aes_ivec));
871a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        for (size_t i = 0; i < 16; ++i) {
872a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            char c1 = tolower(iv.c_str()[2 + 2 * i]);
873a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            char c2 = tolower(iv.c_str()[3 + 2 * i]);
874a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            if (!isxdigit(c1) || !isxdigit(c2)) {
87529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("malformed cipher IV '%s'.", iv.c_str());
876a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                return ERROR_MALFORMED;
877a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            }
878a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            uint8_t nibble1 = isdigit(c1) ? c1 - '0' : c1 - 'a' + 10;
879a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            uint8_t nibble2 = isdigit(c2) ? c2 - '0' : c2 - 'a' + 10;
880a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
881a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            aes_ivec[i] = nibble1 << 4 | nibble2;
882a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
883a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else {
884a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        memset(aes_ivec, 0, sizeof(aes_ivec));
885a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        aes_ivec[15] = mSeqNumber & 0xff;
886a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        aes_ivec[14] = (mSeqNumber >> 8) & 0xff;
887a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        aes_ivec[13] = (mSeqNumber >> 16) & 0xff;
888a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        aes_ivec[12] = (mSeqNumber >> 24) & 0xff;
889a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
890a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
891a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    AES_cbc_encrypt(
892a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            buffer->data(), buffer->data(), buffer->size(),
893a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            &aes_key, aes_ivec, AES_DECRYPT);
894a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
895a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // hexdump(buffer->data(), buffer->size());
896a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
897a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t n = buffer->size();
898a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    CHECK_GT(n, 0u);
899a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
900a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t pad = buffer->data()[n - 1];
901a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
902a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    CHECK_GT(pad, 0u);
903a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    CHECK_LE(pad, 16u);
904a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    CHECK_GE((size_t)n, pad);
905a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    for (size_t i = 0; i < pad; ++i) {
906a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        CHECK_EQ((unsigned)buffer->data()[n - 1 - i], pad);
907a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
908a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
909a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    n -= pad;
910a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
911a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    buffer->setRange(buffer->offset(), n);
912a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
913a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return OK;
914a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
915a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
916a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::postMonitorQueue(int64_t delayUs) {
917a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<AMessage> msg = new AMessage(kWhatMonitorQueue, id());
918a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    msg->setInt32("generation", ++mMonitorQueueGeneration);
919a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    msg->post(delayUs);
920a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
921a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
922a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onSeek(const sp<AMessage> &msg) {
923a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    int64_t timeUs;
924a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    CHECK(msg->findInt64("timeUs", &timeUs));
925a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
926a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    mSeekTimeUs = timeUs;
927a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    postMonitorQueue();
928a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
929a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
930a44153c1a57202fb538659eb50706e60454d6273Andreas Huberstatus_t LiveSession::getDuration(int64_t *durationUs) {
931a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    Mutex::Autolock autoLock(mLock);
932a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    *durationUs = mDurationUs;
933a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
934a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return OK;
935a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
936a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
937a44153c1a57202fb538659eb50706e60454d6273Andreas Huberbool LiveSession::isSeekable() {
938a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    int64_t durationUs;
939a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return getDuration(&durationUs) == OK && durationUs >= 0;
940a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
941a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
942a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}  // namespace android
943a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
944