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
17053ae1640ffbfc690962f7f94694b02680c6f66cbJames Dong    ALOGI("onConnect <URL suppressed>");
171a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
172a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    mMasterURL = url;
173a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1747e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    bool dummy;
1757e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    sp<M3UParser> playlist = fetchPlaylist(url.c_str(), &dummy);
176ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
177ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber    if (playlist == NULL) {
17829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("unable to fetch master playlist '%s'.", url.c_str());
179ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
180ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber        mDataSource->queueEOS(ERROR_IO);
181ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber        return;
182ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber    }
183a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
184a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (playlist->isVariantPlaylist()) {
185a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        for (size_t i = 0; i < playlist->size(); ++i) {
186a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            BandwidthItem item;
187a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
188a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            sp<AMessage> meta;
189a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            playlist->itemAt(i, &item.mURI, &meta);
190a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
191a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            unsigned long bandwidth;
192a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            CHECK(meta->findInt32("bandwidth", (int32_t *)&item.mBandwidth));
193a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
194a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            mBandwidthItems.push(item);
195a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
196a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
197a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        CHECK_GT(mBandwidthItems.size(), 0u);
198a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
199a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        mBandwidthItems.sort(SortByBandwidth);
200a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
201a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
202a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    postMonitorQueue();
203a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
204a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
205a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onDisconnect() {
206df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("onDisconnect");
207a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
208a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    mDataSource->queueEOS(ERROR_END_OF_STREAM);
209ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
210ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber    Mutex::Autolock autoLock(mLock);
211ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber    mDisconnectPending = false;
212a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
213a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
2142aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huberstatus_t LiveSession::fetchFile(
2152aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        const char *url, sp<ABuffer> *out,
2162aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        int64_t range_offset, int64_t range_length) {
217a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    *out = NULL;
218a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
219a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<DataSource> source;
220a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
221a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (!strncasecmp(url, "file://", 7)) {
222a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        source = new FileSource(url + 7);
2238cb0c4168bf4b678e4a6edfcf409247016be20d5Andreas Huber    } else if (strncasecmp(url, "http://", 7)
2248cb0c4168bf4b678e4a6edfcf409247016be20d5Andreas Huber            && strncasecmp(url, "https://", 8)) {
225df42f949c8bd05b81d94633767514fff88f52062Andreas Huber        return ERROR_UNSUPPORTED;
226a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else {
227ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber        {
228ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber            Mutex::Autolock autoLock(mLock);
229ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
230ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber            if (mDisconnectPending) {
231ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber                return ERROR_IO;
232ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber            }
233ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber        }
234ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
2352aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        KeyedVector<String8, String8> headers = mExtraHeaders;
2362aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        if (range_offset > 0 || range_length >= 0) {
2372aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber            headers.add(
2382aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                    String8("Range"),
2392aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                    String8(
2402aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                        StringPrintf(
2412aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                            "bytes=%lld-%s",
2422aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                            range_offset,
2432aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                            range_length < 0
2442aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                                ? "" : StringPrintf("%lld", range_offset + range_length - 1).c_str()).c_str()));
2452aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        }
2462aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        status_t err = mHTTPDataSource->connect(url, &headers);
247a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
248a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (err != OK) {
249a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            return err;
250a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
251a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
252a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        source = mHTTPDataSource;
253a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
254a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
255a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    off64_t size;
256a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    status_t err = source->getSize(&size);
257a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
258a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (err != OK) {
259a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        size = 65536;
260a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
261a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
262a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<ABuffer> buffer = new ABuffer(size);
263a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    buffer->setRange(0, 0);
264a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
265a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    for (;;) {
266a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        size_t bufferRemaining = buffer->capacity() - buffer->size();
267a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
268a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (bufferRemaining == 0) {
269a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            bufferRemaining = 32768;
270a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
2713856b090cd04ba5dd4a59a12430ed724d5995909Steve Block            ALOGV("increasing download buffer to %d bytes",
272a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                 buffer->size() + bufferRemaining);
273a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
274a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            sp<ABuffer> copy = new ABuffer(buffer->size() + bufferRemaining);
275a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            memcpy(copy->data(), buffer->data(), buffer->size());
276a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            copy->setRange(0, buffer->size());
277a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
278a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            buffer = copy;
279a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
280a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
2812aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        size_t maxBytesToRead = bufferRemaining;
2822aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        if (range_length >= 0) {
2832aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber            int64_t bytesLeftInRange = range_length - buffer->size();
2842aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber            if (bytesLeftInRange < maxBytesToRead) {
2852aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                maxBytesToRead = bytesLeftInRange;
2862aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber
2872aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                if (bytesLeftInRange == 0) {
2882aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                    break;
2892aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                }
2902aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber            }
2912aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        }
2922aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber
293a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        ssize_t n = source->readAt(
294a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                buffer->size(), buffer->data() + buffer->size(),
2952aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                maxBytesToRead);
296a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
297a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (n < 0) {
29820ad3a341a96e7746015ccb7369fa567897e11f6Andreas Huber            return n;
299a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
300a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
301a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (n == 0) {
302a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
303a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
304a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
305a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        buffer->setRange(0, buffer->size() + (size_t)n);
306a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
307a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
308a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    *out = buffer;
309a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
310a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return OK;
311a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
312a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
3137e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Hubersp<M3UParser> LiveSession::fetchPlaylist(const char *url, bool *unchanged) {
3147e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    *unchanged = false;
3157e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
316a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<ABuffer> buffer;
317a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    status_t err = fetchFile(url, &buffer);
318a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
319a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (err != OK) {
320a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return NULL;
321a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
322a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
3237e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    // MD5 functionality is not available on the simulator, treat all
3247e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    // playlists as changed.
3257e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
3267e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber#if defined(HAVE_ANDROID_OS)
3277e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    uint8_t hash[16];
3287e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
3297e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    MD5_CTX m;
3307e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    MD5_Init(&m);
3317e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    MD5_Update(&m, buffer->data(), buffer->size());
3327e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
3337e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    MD5_Final(hash, &m);
3347e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
3357e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    if (mPlaylist != NULL && !memcmp(hash, mPlaylistHash, 16)) {
3367e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        // playlist unchanged
3377e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
3387e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        if (mRefreshState != THIRD_UNCHANGED_RELOAD_ATTEMPT) {
3397e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            mRefreshState = (RefreshState)(mRefreshState + 1);
3407e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        }
3417e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
3427e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        *unchanged = true;
3437e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
3443856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("Playlist unchanged, refresh state is now %d",
3457e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber             (int)mRefreshState);
3467e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
3477e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        return NULL;
3487e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    }
3497e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
3507e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    memcpy(mPlaylistHash, hash, sizeof(hash));
3517e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
3527e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    mRefreshState = INITIAL_MINIMUM_RELOAD_DELAY;
3537e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber#endif
3547e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
355a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<M3UParser> playlist =
356a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        new M3UParser(url, buffer->data(), buffer->size());
357a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
358a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (playlist->initCheck() != OK) {
35929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("failed to parse .m3u8 playlist");
3609067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber
361a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return NULL;
362a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
363a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
364a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return playlist;
365a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
366a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
367a44153c1a57202fb538659eb50706e60454d6273Andreas Huberstatic double uniformRand() {
368a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return (double)rand() / RAND_MAX;
369a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
370a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
371a44153c1a57202fb538659eb50706e60454d6273Andreas Hubersize_t LiveSession::getBandwidthIndex() {
372a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (mBandwidthItems.size() == 0) {
373a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return 0;
374a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
375a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
376a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#if 1
377a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    int32_t bandwidthBps;
378a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (mHTTPDataSource != NULL
379a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            && mHTTPDataSource->estimateBandwidth(&bandwidthBps)) {
3803856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("bandwidth estimated at %.2f kbps", bandwidthBps / 1024.0f);
381a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else {
3823856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("no bandwidth estimate.");
383a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return 0;  // Pick the lowest bandwidth stream by default.
384a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
385a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
386a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    char value[PROPERTY_VALUE_MAX];
387a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (property_get("media.httplive.max-bw", value, NULL)) {
388a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        char *end;
389a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        long maxBw = strtoul(value, &end, 10);
390a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (end > value && *end == '\0') {
391a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            if (maxBw > 0 && bandwidthBps > maxBw) {
3923856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("bandwidth capped to %ld bps", maxBw);
393a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                bandwidthBps = maxBw;
394a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            }
395a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
396a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
397a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
398a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // Consider only 80% of the available bandwidth usable.
399a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    bandwidthBps = (bandwidthBps * 8) / 10;
400a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
401a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // Pick the highest bandwidth stream below or equal to estimated bandwidth.
402a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
403a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index = mBandwidthItems.size() - 1;
404a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    while (index > 0 && mBandwidthItems.itemAt(index).mBandwidth
405a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                            > (size_t)bandwidthBps) {
406a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        --index;
407a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
408a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0
409a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // Change bandwidth at random()
410a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index = uniformRand() * mBandwidthItems.size();
411a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0
412a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // There's a 50% chance to stay on the current bandwidth and
413a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // a 50% chance to switch to the next higher bandwidth (wrapping around
414a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // to lowest)
415a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    const size_t kMinIndex = 0;
416a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
417a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index;
418a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (mPrevBandwidthIndex < 0) {
419a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        index = kMinIndex;
420a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else if (uniformRand() < 0.5) {
421a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        index = (size_t)mPrevBandwidthIndex;
422a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else {
423a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        index = mPrevBandwidthIndex + 1;
424a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (index == mBandwidthItems.size()) {
425a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            index = kMinIndex;
426a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
427a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
428a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0
429a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // Pick the highest bandwidth stream below or equal to 1.2 Mbit/sec
430a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
431a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index = mBandwidthItems.size() - 1;
432a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    while (index > 0 && mBandwidthItems.itemAt(index).mBandwidth > 1200000) {
433a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        --index;
434a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
435a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#else
436a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index = mBandwidthItems.size() - 1;  // Highest bandwidth stream
437a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#endif
438a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
439a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return index;
440a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
441a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
4427e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huberbool LiveSession::timeToRefreshPlaylist(int64_t nowUs) const {
4437e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    if (mPlaylist == NULL) {
4447e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        CHECK_EQ((int)mRefreshState, (int)INITIAL_MINIMUM_RELOAD_DELAY);
4457e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        return true;
4467e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    }
4477e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
4487e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    int32_t targetDurationSecs;
4497e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    CHECK(mPlaylist->meta()->findInt32("target-duration", &targetDurationSecs));
4507e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
4517e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    int64_t targetDurationUs = targetDurationSecs * 1000000ll;
4527e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
4537e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    int64_t minPlaylistAgeUs;
4547e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
4557e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    switch (mRefreshState) {
4567e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        case INITIAL_MINIMUM_RELOAD_DELAY:
4577e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        {
4587e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            size_t n = mPlaylist->size();
4597e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            if (n > 0) {
4607e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber                sp<AMessage> itemMeta;
4617e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber                CHECK(mPlaylist->itemAt(n - 1, NULL /* uri */, &itemMeta));
4627e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
4637e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber                int64_t itemDurationUs;
4647e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber                CHECK(itemMeta->findInt64("durationUs", &itemDurationUs));
4657e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
4667e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber                minPlaylistAgeUs = itemDurationUs;
4677e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber                break;
4687e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            }
4697e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
4707e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            // fall through
4717e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        }
4727e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
4737e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        case FIRST_UNCHANGED_RELOAD_ATTEMPT:
4747e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        {
4757e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            minPlaylistAgeUs = targetDurationUs / 2;
4767e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            break;
4777e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        }
4787e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
4797e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        case SECOND_UNCHANGED_RELOAD_ATTEMPT:
4807e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        {
4817e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            minPlaylistAgeUs = (targetDurationUs * 3) / 2;
4827e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            break;
4837e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        }
4847e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
4857e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        case THIRD_UNCHANGED_RELOAD_ATTEMPT:
4867e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        {
4877e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            minPlaylistAgeUs = targetDurationUs * 3;
4887e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            break;
4897e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        }
4907e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
4917e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        default:
4927e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            TRESPASS();
4937e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            break;
4947e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    }
4957e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
4967e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    return mLastPlaylistFetchTimeUs + minPlaylistAgeUs <= nowUs;
4977e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber}
4987e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
499a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onDownloadNext() {
500a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t bandwidthIndex = getBandwidthIndex();
501a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
502aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huberrinse_repeat:
503a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    int64_t nowUs = ALooper::GetNowUs();
504a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
505a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (mLastPlaylistFetchTimeUs < 0
506a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            || (ssize_t)bandwidthIndex != mPrevBandwidthIndex
5077e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            || (!mPlaylist->isComplete() && timeToRefreshPlaylist(nowUs))) {
508a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        AString url;
509a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (mBandwidthItems.size() > 0) {
510a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            url = mBandwidthItems.editItemAt(bandwidthIndex).mURI;
511a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        } else {
512a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            url = mMasterURL;
513a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
514a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
515a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        bool firstTime = (mPlaylist == NULL);
516a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
5178dae4ca229d21f68f3ee76c76b49b6f0a47aad53Andreas Huber        if ((ssize_t)bandwidthIndex != mPrevBandwidthIndex) {
5188dae4ca229d21f68f3ee76c76b49b6f0a47aad53Andreas Huber            // If we switch bandwidths, do not pay any heed to whether
5198dae4ca229d21f68f3ee76c76b49b6f0a47aad53Andreas Huber            // playlists changed since the last time...
5208dae4ca229d21f68f3ee76c76b49b6f0a47aad53Andreas Huber            mPlaylist.clear();
5218dae4ca229d21f68f3ee76c76b49b6f0a47aad53Andreas Huber        }
5228dae4ca229d21f68f3ee76c76b49b6f0a47aad53Andreas Huber
5237e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        bool unchanged;
5247e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        sp<M3UParser> playlist = fetchPlaylist(url.c_str(), &unchanged);
5257e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        if (playlist == NULL) {
5267e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            if (unchanged) {
5277e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber                // We succeeded in fetching the playlist, but it was
5287e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber                // unchanged from the last time we tried.
5297e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            } else {
53029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("failed to load playlist at url '%s'", url.c_str());
5317e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber                mDataSource->queueEOS(ERROR_IO);
5327e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber                return;
5337e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            }
5347e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        } else {
5357e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            mPlaylist = playlist;
5366e6b1cae2bac1b78205cefab8e4e9e9538982965Andreas Huber        }
537a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
538a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (firstTime) {
539a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            Mutex::Autolock autoLock(mLock);
540a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
5410f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber            if (!mPlaylist->isComplete()) {
542a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                mDurationUs = -1;
543a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            } else {
5440f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                mDurationUs = 0;
5450f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                for (size_t i = 0; i < mPlaylist->size(); ++i) {
5460f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                    sp<AMessage> itemMeta;
5470f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                    CHECK(mPlaylist->itemAt(
5480f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                                i, NULL /* uri */, &itemMeta));
5490f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber
5500f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                    int64_t itemDurationUs;
5510f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                    CHECK(itemMeta->findInt64("durationUs", &itemDurationUs));
5520f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber
5530f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                    mDurationUs += itemDurationUs;
5540f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                }
555a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            }
556a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
557a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
558a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        mLastPlaylistFetchTimeUs = ALooper::GetNowUs();
559a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
560a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
561a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    int32_t firstSeqNumberInPlaylist;
562a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (mPlaylist->meta() == NULL || !mPlaylist->meta()->findInt32(
563a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                "media-sequence", &firstSeqNumberInPlaylist)) {
564a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        firstSeqNumberInPlaylist = 0;
565a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
566a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
56720f725ebcef13ded1b4b85c61c8a4b37cd030656Andreas Huber    bool seekDiscontinuity = false;
568a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    bool explicitDiscontinuity = false;
56922fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber    bool bandwidthChanged = false;
570a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
571a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (mSeekTimeUs >= 0) {
5720f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber        if (mPlaylist->isComplete()) {
5730f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber            size_t index = 0;
5740f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber            int64_t segmentStartUs = 0;
5750f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber            while (index < mPlaylist->size()) {
5760f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                sp<AMessage> itemMeta;
5770f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                CHECK(mPlaylist->itemAt(
5780f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                            index, NULL /* uri */, &itemMeta));
5790f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber
5800f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                int64_t itemDurationUs;
5810f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                CHECK(itemMeta->findInt64("durationUs", &itemDurationUs));
5820f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber
5830f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                if (mSeekTimeUs < segmentStartUs + itemDurationUs) {
5840f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                    break;
5850f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                }
5860f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber
5870f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                segmentStartUs += itemDurationUs;
5880f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                ++index;
5890f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber            }
5900f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber
5910f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber            if (index < mPlaylist->size()) {
59243c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber                int32_t newSeqNumber = firstSeqNumberInPlaylist + index;
593a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
59443c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber                if (newSeqNumber != mSeqNumber) {
595df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block                    ALOGI("seeking to seq no %d", newSeqNumber);
59643c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
59743c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber                    mSeqNumber = newSeqNumber;
59843c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
59943c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber                    mDataSource->reset();
60043c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
60122fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber                    // reseting the data source will have had the
60222fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber                    // side effect of discarding any previously queued
60322fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber                    // bandwidth change discontinuity.
60420f725ebcef13ded1b4b85c61c8a4b37cd030656Andreas Huber                    // Therefore we'll need to treat these seek
60522fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber                    // discontinuities as involving a bandwidth change
60622fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber                    // even if they aren't directly.
60720f725ebcef13ded1b4b85c61c8a4b37cd030656Andreas Huber                    seekDiscontinuity = true;
60822fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber                    bandwidthChanged = true;
60943c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber                }
610a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            }
611a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
612a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
613a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        mSeekTimeUs = -1;
614a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
615a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        Mutex::Autolock autoLock(mLock);
616a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        mSeekDone = true;
617a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        mCondition.broadcast();
618a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
619a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
620a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (mSeqNumber < 0) {
62120f725ebcef13ded1b4b85c61c8a4b37cd030656Andreas Huber        mSeqNumber = firstSeqNumberInPlaylist;
622a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
623a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
624a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    int32_t lastSeqNumberInPlaylist =
625a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        firstSeqNumberInPlaylist + (int32_t)mPlaylist->size() - 1;
626a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
627a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (mSeqNumber < firstSeqNumberInPlaylist
628a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            || mSeqNumber > lastSeqNumberInPlaylist) {
62988b7ad413c4b6d08697069b18488641d6ce31fd3Andreas Huber        if (mPrevBandwidthIndex != (ssize_t)bandwidthIndex) {
630aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber            // Go back to the previous bandwidth.
631aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber
632df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block            ALOGI("new bandwidth does not have the sequence number "
633aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber                 "we're looking for, switching back to previous bandwidth");
634aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber
635aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber            mLastPlaylistFetchTimeUs = -1;
636aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber            bandwidthIndex = mPrevBandwidthIndex;
637aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber            goto rinse_repeat;
638aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber        }
639aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber
6406801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber        if (!mPlaylist->isComplete() && mNumRetries < kMaxNumRetries) {
641a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            ++mNumRetries;
642a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
6436801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber            if (mSeqNumber > lastSeqNumberInPlaylist) {
6446801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber                mLastPlaylistFetchTimeUs = -1;
6456801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber                postMonitorQueue(3000000ll);
6466801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber                return;
6476801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber            }
648a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
6496801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber            // we've missed the boat, let's start from the lowest sequence
6506801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber            // number available and signal a discontinuity.
651a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
652df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block            ALOGI("We've missed the boat, restarting playback.");
6536801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber            mSeqNumber = lastSeqNumberInPlaylist;
6546801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber            explicitDiscontinuity = true;
6556801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber
6566801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber            // fall through
6576801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber        } else {
65829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Cannot find sequence number %d in playlist "
6596801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber                 "(contains %d - %d)",
6606801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber                 mSeqNumber, firstSeqNumberInPlaylist,
6616801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber                 firstSeqNumberInPlaylist + mPlaylist->size() - 1);
6626801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber
6636801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber            mDataSource->queueEOS(ERROR_END_OF_STREAM);
6646801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber            return;
6656801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber        }
666a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
667a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
668a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    mNumRetries = 0;
669a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
670a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    AString uri;
671a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<AMessage> itemMeta;
672a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    CHECK(mPlaylist->itemAt(
673a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                mSeqNumber - firstSeqNumberInPlaylist,
674a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                &uri,
675a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                &itemMeta));
676a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
677a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    int32_t val;
678a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (itemMeta->findInt32("discontinuity", &val) && val != 0) {
679a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        explicitDiscontinuity = true;
680a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
681a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
6822aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber    int64_t range_offset, range_length;
6832aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber    if (!itemMeta->findInt64("range-offset", &range_offset)
6842aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber            || !itemMeta->findInt64("range-length", &range_length)) {
6852aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        range_offset = 0;
6862aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        range_length = -1;
6872aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber    }
6882aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber
689a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<ABuffer> buffer;
6902aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber    status_t err = fetchFile(uri.c_str(), &buffer, range_offset, range_length);
6916e6b1cae2bac1b78205cefab8e4e9e9538982965Andreas Huber    if (err != OK) {
69229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("failed to fetch .ts segment at url '%s'", uri.c_str());
6936e6b1cae2bac1b78205cefab8e4e9e9538982965Andreas Huber        mDataSource->queueEOS(err);
6946e6b1cae2bac1b78205cefab8e4e9e9538982965Andreas Huber        return;
6956e6b1cae2bac1b78205cefab8e4e9e9538982965Andreas Huber    }
696a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
69743c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber    CHECK(buffer != NULL);
69843c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
69988b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber    err = decryptBuffer(mSeqNumber - firstSeqNumberInPlaylist, buffer);
70088b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber
70188b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber    if (err != OK) {
70229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("decryptBuffer failed w/ error %d", err);
70388b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber
70488b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber        mDataSource->queueEOS(err);
70588b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber        return;
70688b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber    }
707a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
708a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (buffer->size() == 0 || buffer->data()[0] != 0x47) {
709a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        // Not a transport stream???
710a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
71129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("This doesn't look like a transport stream...");
712a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
713bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber        mBandwidthItems.removeAt(bandwidthIndex);
714bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
715bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber        if (mBandwidthItems.isEmpty()) {
716bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber            mDataSource->queueEOS(ERROR_UNSUPPORTED);
717bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber            return;
718bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber        }
719bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
720df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("Retrying with a different bandwidth stream.");
721bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
722bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber        mLastPlaylistFetchTimeUs = -1;
723bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber        bandwidthIndex = getBandwidthIndex();
724bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber        mPrevBandwidthIndex = bandwidthIndex;
725bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber        mSeqNumber = -1;
726bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
727bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber        goto rinse_repeat;
728a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
729a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
73022fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber    if ((size_t)mPrevBandwidthIndex != bandwidthIndex) {
73122fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber        bandwidthChanged = true;
73222fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber    }
73322fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber
73422fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber    if (mPrevBandwidthIndex < 0) {
73522fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber        // Don't signal a bandwidth change at the very beginning of
73622fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber        // playback.
73722fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber        bandwidthChanged = false;
73822fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber    }
7393831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber
74020f725ebcef13ded1b4b85c61c8a4b37cd030656Andreas Huber    if (seekDiscontinuity || explicitDiscontinuity || bandwidthChanged) {
741a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        // Signal discontinuity.
742a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
743df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("queueing discontinuity (seek=%d, explicit=%d, bandwidthChanged=%d)",
74420f725ebcef13ded1b4b85c61c8a4b37cd030656Andreas Huber             seekDiscontinuity, explicitDiscontinuity, bandwidthChanged);
74543c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
746a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        sp<ABuffer> tmp = new ABuffer(188);
747a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        memset(tmp->data(), 0, tmp->size());
74820f725ebcef13ded1b4b85c61c8a4b37cd030656Andreas Huber
74920f725ebcef13ded1b4b85c61c8a4b37cd030656Andreas Huber        // signal a 'hard' discontinuity for explicit or bandwidthChanged.
75020f725ebcef13ded1b4b85c61c8a4b37cd030656Andreas Huber        tmp->data()[1] = (explicitDiscontinuity || bandwidthChanged) ? 1 : 0;
751a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
752a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        mDataSource->queueBuffer(tmp);
753a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
754a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
755a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    mDataSource->queueBuffer(buffer);
756a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
757a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    mPrevBandwidthIndex = bandwidthIndex;
758a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    ++mSeqNumber;
759a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
760a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    postMonitorQueue();
761a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
762a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
763a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onMonitorQueue() {
764a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (mSeekTimeUs >= 0
765a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            || mDataSource->countQueuedBuffers() < kMaxNumQueuedFragments) {
766a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        onDownloadNext();
767a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else {
768a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        postMonitorQueue(1000000ll);
769a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
770a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
771a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
772a44153c1a57202fb538659eb50706e60454d6273Andreas Huberstatus_t LiveSession::decryptBuffer(
773a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        size_t playlistIndex, const sp<ABuffer> &buffer) {
774a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<AMessage> itemMeta;
775a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    bool found = false;
776a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    AString method;
777a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
778a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    for (ssize_t i = playlistIndex; i >= 0; --i) {
779a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        AString uri;
780a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        CHECK(mPlaylist->itemAt(i, &uri, &itemMeta));
781a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
782a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (itemMeta->findString("cipher-method", &method)) {
783a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            found = true;
784a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
785a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
786a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
787a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
788a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (!found) {
789a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        method = "NONE";
790a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
791a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
792a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (method == "NONE") {
793a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return OK;
794a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else if (!(method == "AES-128")) {
79529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Unsupported cipher method '%s'", method.c_str());
796a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return ERROR_UNSUPPORTED;
797a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
798a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
799a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    AString keyURI;
800a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (!itemMeta->findString("cipher-uri", &keyURI)) {
80129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Missing key uri");
802a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return ERROR_MALFORMED;
803a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
804a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
805a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    ssize_t index = mAESKeyForURI.indexOfKey(keyURI);
806a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
807a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<ABuffer> key;
808a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (index >= 0) {
809a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        key = mAESKeyForURI.valueAt(index);
810a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else {
811a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        key = new ABuffer(16);
812a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
8131156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        sp<HTTPBase> keySource =
8141156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber              HTTPBase::Create(
8151156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                  (mFlags & kFlagIncognito)
8161156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                    ? HTTPBase::kFlagIncognito
8171156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                    : 0);
8181156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
8199b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber        if (mUIDValid) {
8209b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber            keySource->setUID(mUID);
8219b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber        }
8229b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber
823d6a46a6bda23667e06ee5ccca3781e407c7d1204Andreas Huber        status_t err =
824d6a46a6bda23667e06ee5ccca3781e407c7d1204Andreas Huber            keySource->connect(
825d6a46a6bda23667e06ee5ccca3781e407c7d1204Andreas Huber                    keyURI.c_str(),
826d6a46a6bda23667e06ee5ccca3781e407c7d1204Andreas Huber                    mExtraHeaders.isEmpty() ? NULL : &mExtraHeaders);
827a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
828a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (err == OK) {
829a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            size_t offset = 0;
830a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            while (offset < 16) {
831a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                ssize_t n = keySource->readAt(
832a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                        offset, key->data() + offset, 16 - offset);
833a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                if (n <= 0) {
834a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                    err = ERROR_IO;
835a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                    break;
836a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                }
837a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
838a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                offset += n;
839a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            }
840a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
841a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
842a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (err != OK) {
84329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("failed to fetch cipher key from '%s'.", keyURI.c_str());
844a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            return ERROR_IO;
845a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
846a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
847a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        mAESKeyForURI.add(keyURI, key);
848a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
849a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
850a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    AES_KEY aes_key;
851a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (AES_set_decrypt_key(key->data(), 128, &aes_key) != 0) {
85229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("failed to set AES decryption key.");
853a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return UNKNOWN_ERROR;
854a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
855a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
856a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    unsigned char aes_ivec[16];
857a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
858a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    AString iv;
859a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (itemMeta->findString("cipher-iv", &iv)) {
860a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if ((!iv.startsWith("0x") && !iv.startsWith("0X"))
861a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                || iv.size() != 16 * 2 + 2) {
86229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("malformed cipher IV '%s'.", iv.c_str());
863a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            return ERROR_MALFORMED;
864a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
865a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
866a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        memset(aes_ivec, 0, sizeof(aes_ivec));
867a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        for (size_t i = 0; i < 16; ++i) {
868a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            char c1 = tolower(iv.c_str()[2 + 2 * i]);
869a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            char c2 = tolower(iv.c_str()[3 + 2 * i]);
870a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            if (!isxdigit(c1) || !isxdigit(c2)) {
87129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("malformed cipher IV '%s'.", iv.c_str());
872a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                return ERROR_MALFORMED;
873a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            }
874a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            uint8_t nibble1 = isdigit(c1) ? c1 - '0' : c1 - 'a' + 10;
875a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            uint8_t nibble2 = isdigit(c2) ? c2 - '0' : c2 - 'a' + 10;
876a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
877a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            aes_ivec[i] = nibble1 << 4 | nibble2;
878a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
879a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else {
880a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        memset(aes_ivec, 0, sizeof(aes_ivec));
881a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        aes_ivec[15] = mSeqNumber & 0xff;
882a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        aes_ivec[14] = (mSeqNumber >> 8) & 0xff;
883a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        aes_ivec[13] = (mSeqNumber >> 16) & 0xff;
884a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        aes_ivec[12] = (mSeqNumber >> 24) & 0xff;
885a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
886a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
887a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    AES_cbc_encrypt(
888a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            buffer->data(), buffer->data(), buffer->size(),
889a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            &aes_key, aes_ivec, AES_DECRYPT);
890a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
891a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // hexdump(buffer->data(), buffer->size());
892a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
893a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t n = buffer->size();
894a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    CHECK_GT(n, 0u);
895a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
896a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t pad = buffer->data()[n - 1];
897a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
898a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    CHECK_GT(pad, 0u);
899a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    CHECK_LE(pad, 16u);
900a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    CHECK_GE((size_t)n, pad);
901a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    for (size_t i = 0; i < pad; ++i) {
902a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        CHECK_EQ((unsigned)buffer->data()[n - 1 - i], pad);
903a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
904a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
905a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    n -= pad;
906a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
907a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    buffer->setRange(buffer->offset(), n);
908a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
909a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return OK;
910a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
911a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
912a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::postMonitorQueue(int64_t delayUs) {
913a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<AMessage> msg = new AMessage(kWhatMonitorQueue, id());
914a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    msg->setInt32("generation", ++mMonitorQueueGeneration);
915a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    msg->post(delayUs);
916a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
917a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
918a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onSeek(const sp<AMessage> &msg) {
919a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    int64_t timeUs;
920a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    CHECK(msg->findInt64("timeUs", &timeUs));
921a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
922a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    mSeekTimeUs = timeUs;
923a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    postMonitorQueue();
924a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
925a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
926a44153c1a57202fb538659eb50706e60454d6273Andreas Huberstatus_t LiveSession::getDuration(int64_t *durationUs) {
927a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    Mutex::Autolock autoLock(mLock);
928a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    *durationUs = mDurationUs;
929a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
930a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return OK;
931a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
932a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
933a44153c1a57202fb538659eb50706e60454d6273Andreas Huberbool LiveSession::isSeekable() {
934a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    int64_t durationUs;
935a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return getDuration(&durationUs) == OK && durationUs >= 0;
936a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
937a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
938a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}  // namespace android
939a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
940