LiveSession.cpp revision 3856b090cd04ba5dd4a59a12430ed724d5995909
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)) {
1717314fa17093d514199fedcb55ac41136a1b31cb3Andreas Huber        LOGI("onConnect '%s'", url.c_str());
1727314fa17093d514199fedcb55ac41136a1b31cb3Andreas Huber    } else {
1737314fa17093d514199fedcb55ac41136a1b31cb3Andreas Huber        LOGI("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) {
182ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber        LOGE("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() {
210a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    LOGI("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
218a44153c1a57202fb538659eb50706e60454d6273Andreas Huberstatus_t LiveSession::fetchFile(const char *url, sp<ABuffer> *out) {
219a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    *out = NULL;
220a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
221a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<DataSource> source;
222a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
223a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (!strncasecmp(url, "file://", 7)) {
224a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        source = new FileSource(url + 7);
2258cb0c4168bf4b678e4a6edfcf409247016be20d5Andreas Huber    } else if (strncasecmp(url, "http://", 7)
2268cb0c4168bf4b678e4a6edfcf409247016be20d5Andreas Huber            && strncasecmp(url, "https://", 8)) {
227df42f949c8bd05b81d94633767514fff88f52062Andreas Huber        return ERROR_UNSUPPORTED;
228a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else {
229ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber        {
230ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber            Mutex::Autolock autoLock(mLock);
231ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
232ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber            if (mDisconnectPending) {
233ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber                return ERROR_IO;
234ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber            }
235ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber        }
236ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
237ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        status_t err = mHTTPDataSource->connect(
238ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber                url, mExtraHeaders.isEmpty() ? NULL : &mExtraHeaders);
239a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
240a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (err != OK) {
241a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            return err;
242a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
243a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
244a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        source = mHTTPDataSource;
245a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
246a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
247a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    off64_t size;
248a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    status_t err = source->getSize(&size);
249a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
250a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (err != OK) {
251a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        size = 65536;
252a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
253a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
254a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<ABuffer> buffer = new ABuffer(size);
255a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    buffer->setRange(0, 0);
256a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
257a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    for (;;) {
258a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        size_t bufferRemaining = buffer->capacity() - buffer->size();
259a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
260a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (bufferRemaining == 0) {
261a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            bufferRemaining = 32768;
262a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
2633856b090cd04ba5dd4a59a12430ed724d5995909Steve Block            ALOGV("increasing download buffer to %d bytes",
264a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                 buffer->size() + bufferRemaining);
265a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
266a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            sp<ABuffer> copy = new ABuffer(buffer->size() + bufferRemaining);
267a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            memcpy(copy->data(), buffer->data(), buffer->size());
268a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            copy->setRange(0, buffer->size());
269a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
270a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            buffer = copy;
271a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
272a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
273a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        ssize_t n = source->readAt(
274a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                buffer->size(), buffer->data() + buffer->size(),
275a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                bufferRemaining);
276a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
277a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (n < 0) {
27820ad3a341a96e7746015ccb7369fa567897e11f6Andreas Huber            return n;
279a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
280a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
281a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (n == 0) {
282a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
283a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
284a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
285a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        buffer->setRange(0, buffer->size() + (size_t)n);
286a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
287a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
288a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    *out = buffer;
289a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
290a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return OK;
291a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
292a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
2937e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Hubersp<M3UParser> LiveSession::fetchPlaylist(const char *url, bool *unchanged) {
2947e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    *unchanged = false;
2957e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
296a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<ABuffer> buffer;
297a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    status_t err = fetchFile(url, &buffer);
298a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
299a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (err != OK) {
300a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return NULL;
301a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
302a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
3037e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    // MD5 functionality is not available on the simulator, treat all
3047e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    // playlists as changed.
3057e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
3067e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber#if defined(HAVE_ANDROID_OS)
3077e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    uint8_t hash[16];
3087e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
3097e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    MD5_CTX m;
3107e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    MD5_Init(&m);
3117e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    MD5_Update(&m, buffer->data(), buffer->size());
3127e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
3137e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    MD5_Final(hash, &m);
3147e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
3157e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    if (mPlaylist != NULL && !memcmp(hash, mPlaylistHash, 16)) {
3167e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        // playlist unchanged
3177e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
3187e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        if (mRefreshState != THIRD_UNCHANGED_RELOAD_ATTEMPT) {
3197e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            mRefreshState = (RefreshState)(mRefreshState + 1);
3207e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        }
3217e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
3227e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        *unchanged = true;
3237e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
3243856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("Playlist unchanged, refresh state is now %d",
3257e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber             (int)mRefreshState);
3267e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
3277e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        return NULL;
3287e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    }
3297e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
3307e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    memcpy(mPlaylistHash, hash, sizeof(hash));
3317e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
3327e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    mRefreshState = INITIAL_MINIMUM_RELOAD_DELAY;
3337e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber#endif
3347e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
335a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<M3UParser> playlist =
336a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        new M3UParser(url, buffer->data(), buffer->size());
337a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
338a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (playlist->initCheck() != OK) {
3399067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber        LOGE("failed to parse .m3u8 playlist");
3409067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber
341a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return NULL;
342a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
343a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
344a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return playlist;
345a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
346a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
347a44153c1a57202fb538659eb50706e60454d6273Andreas Huberstatic double uniformRand() {
348a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return (double)rand() / RAND_MAX;
349a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
350a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
351a44153c1a57202fb538659eb50706e60454d6273Andreas Hubersize_t LiveSession::getBandwidthIndex() {
352a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (mBandwidthItems.size() == 0) {
353a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return 0;
354a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
355a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
356a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#if 1
357a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    int32_t bandwidthBps;
358a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (mHTTPDataSource != NULL
359a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            && mHTTPDataSource->estimateBandwidth(&bandwidthBps)) {
3603856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("bandwidth estimated at %.2f kbps", bandwidthBps / 1024.0f);
361a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else {
3623856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("no bandwidth estimate.");
363a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return 0;  // Pick the lowest bandwidth stream by default.
364a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
365a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
366a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    char value[PROPERTY_VALUE_MAX];
367a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (property_get("media.httplive.max-bw", value, NULL)) {
368a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        char *end;
369a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        long maxBw = strtoul(value, &end, 10);
370a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (end > value && *end == '\0') {
371a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            if (maxBw > 0 && bandwidthBps > maxBw) {
3723856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("bandwidth capped to %ld bps", maxBw);
373a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                bandwidthBps = maxBw;
374a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            }
375a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
376a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
377a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
378a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // Consider only 80% of the available bandwidth usable.
379a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    bandwidthBps = (bandwidthBps * 8) / 10;
380a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
381a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // Pick the highest bandwidth stream below or equal to estimated bandwidth.
382a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
383a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index = mBandwidthItems.size() - 1;
384a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    while (index > 0 && mBandwidthItems.itemAt(index).mBandwidth
385a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                            > (size_t)bandwidthBps) {
386a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        --index;
387a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
388a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0
389a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // Change bandwidth at random()
390a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index = uniformRand() * mBandwidthItems.size();
391a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0
392a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // There's a 50% chance to stay on the current bandwidth and
393a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // a 50% chance to switch to the next higher bandwidth (wrapping around
394a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // to lowest)
395a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    const size_t kMinIndex = 0;
396a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
397a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index;
398a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (mPrevBandwidthIndex < 0) {
399a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        index = kMinIndex;
400a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else if (uniformRand() < 0.5) {
401a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        index = (size_t)mPrevBandwidthIndex;
402a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else {
403a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        index = mPrevBandwidthIndex + 1;
404a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (index == mBandwidthItems.size()) {
405a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            index = kMinIndex;
406a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
407a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
408a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0
409a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // Pick the highest bandwidth stream below or equal to 1.2 Mbit/sec
410a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
411a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index = mBandwidthItems.size() - 1;
412a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    while (index > 0 && mBandwidthItems.itemAt(index).mBandwidth > 1200000) {
413a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        --index;
414a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
415a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#else
416a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index = mBandwidthItems.size() - 1;  // Highest bandwidth stream
417a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#endif
418a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
419a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return index;
420a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
421a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
4227e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huberbool LiveSession::timeToRefreshPlaylist(int64_t nowUs) const {
4237e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    if (mPlaylist == NULL) {
4247e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        CHECK_EQ((int)mRefreshState, (int)INITIAL_MINIMUM_RELOAD_DELAY);
4257e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        return true;
4267e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    }
4277e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
4287e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    int32_t targetDurationSecs;
4297e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    CHECK(mPlaylist->meta()->findInt32("target-duration", &targetDurationSecs));
4307e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
4317e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    int64_t targetDurationUs = targetDurationSecs * 1000000ll;
4327e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
4337e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    int64_t minPlaylistAgeUs;
4347e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
4357e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    switch (mRefreshState) {
4367e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        case INITIAL_MINIMUM_RELOAD_DELAY:
4377e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        {
4387e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            size_t n = mPlaylist->size();
4397e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            if (n > 0) {
4407e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber                sp<AMessage> itemMeta;
4417e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber                CHECK(mPlaylist->itemAt(n - 1, NULL /* uri */, &itemMeta));
4427e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
4437e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber                int64_t itemDurationUs;
4447e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber                CHECK(itemMeta->findInt64("durationUs", &itemDurationUs));
4457e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
4467e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber                minPlaylistAgeUs = itemDurationUs;
4477e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber                break;
4487e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            }
4497e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
4507e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            // fall through
4517e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        }
4527e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
4537e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        case FIRST_UNCHANGED_RELOAD_ATTEMPT:
4547e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        {
4557e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            minPlaylistAgeUs = targetDurationUs / 2;
4567e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            break;
4577e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        }
4587e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
4597e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        case SECOND_UNCHANGED_RELOAD_ATTEMPT:
4607e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        {
4617e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            minPlaylistAgeUs = (targetDurationUs * 3) / 2;
4627e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            break;
4637e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        }
4647e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
4657e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        case THIRD_UNCHANGED_RELOAD_ATTEMPT:
4667e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        {
4677e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            minPlaylistAgeUs = targetDurationUs * 3;
4687e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            break;
4697e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        }
4707e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
4717e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        default:
4727e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            TRESPASS();
4737e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            break;
4747e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    }
4757e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
4767e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    return mLastPlaylistFetchTimeUs + minPlaylistAgeUs <= nowUs;
4777e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber}
4787e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
479a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onDownloadNext() {
480a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t bandwidthIndex = getBandwidthIndex();
481a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
482aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huberrinse_repeat:
483a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    int64_t nowUs = ALooper::GetNowUs();
484a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
485a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (mLastPlaylistFetchTimeUs < 0
486a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            || (ssize_t)bandwidthIndex != mPrevBandwidthIndex
4877e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            || (!mPlaylist->isComplete() && timeToRefreshPlaylist(nowUs))) {
488a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        AString url;
489a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (mBandwidthItems.size() > 0) {
490a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            url = mBandwidthItems.editItemAt(bandwidthIndex).mURI;
491a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        } else {
492a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            url = mMasterURL;
493a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
494a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
495a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        bool firstTime = (mPlaylist == NULL);
496a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
4978dae4ca229d21f68f3ee76c76b49b6f0a47aad53Andreas Huber        if ((ssize_t)bandwidthIndex != mPrevBandwidthIndex) {
4988dae4ca229d21f68f3ee76c76b49b6f0a47aad53Andreas Huber            // If we switch bandwidths, do not pay any heed to whether
4998dae4ca229d21f68f3ee76c76b49b6f0a47aad53Andreas Huber            // playlists changed since the last time...
5008dae4ca229d21f68f3ee76c76b49b6f0a47aad53Andreas Huber            mPlaylist.clear();
5018dae4ca229d21f68f3ee76c76b49b6f0a47aad53Andreas Huber        }
5028dae4ca229d21f68f3ee76c76b49b6f0a47aad53Andreas Huber
5037e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        bool unchanged;
5047e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        sp<M3UParser> playlist = fetchPlaylist(url.c_str(), &unchanged);
5057e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        if (playlist == NULL) {
5067e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            if (unchanged) {
5077e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber                // We succeeded in fetching the playlist, but it was
5087e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber                // unchanged from the last time we tried.
5097e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            } else {
5107e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber                LOGE("failed to load playlist at url '%s'", url.c_str());
5117e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber                mDataSource->queueEOS(ERROR_IO);
5127e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber                return;
5137e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            }
5147e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        } else {
5157e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            mPlaylist = playlist;
5166e6b1cae2bac1b78205cefab8e4e9e9538982965Andreas Huber        }
517a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
518a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (firstTime) {
519a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            Mutex::Autolock autoLock(mLock);
520a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
5210f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber            if (!mPlaylist->isComplete()) {
522a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                mDurationUs = -1;
523a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            } else {
5240f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                mDurationUs = 0;
5250f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                for (size_t i = 0; i < mPlaylist->size(); ++i) {
5260f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                    sp<AMessage> itemMeta;
5270f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                    CHECK(mPlaylist->itemAt(
5280f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                                i, NULL /* uri */, &itemMeta));
5290f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber
5300f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                    int64_t itemDurationUs;
5310f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                    CHECK(itemMeta->findInt64("durationUs", &itemDurationUs));
5320f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber
5330f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                    mDurationUs += itemDurationUs;
5340f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                }
535a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            }
536a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
537a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
538a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        mLastPlaylistFetchTimeUs = ALooper::GetNowUs();
539a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
540a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
541a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    int32_t firstSeqNumberInPlaylist;
542a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (mPlaylist->meta() == NULL || !mPlaylist->meta()->findInt32(
543a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                "media-sequence", &firstSeqNumberInPlaylist)) {
544a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        firstSeqNumberInPlaylist = 0;
545a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
546a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
54720f725ebcef13ded1b4b85c61c8a4b37cd030656Andreas Huber    bool seekDiscontinuity = false;
548a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    bool explicitDiscontinuity = false;
54922fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber    bool bandwidthChanged = false;
550a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
551a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (mSeekTimeUs >= 0) {
5520f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber        if (mPlaylist->isComplete()) {
5530f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber            size_t index = 0;
5540f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber            int64_t segmentStartUs = 0;
5550f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber            while (index < mPlaylist->size()) {
5560f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                sp<AMessage> itemMeta;
5570f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                CHECK(mPlaylist->itemAt(
5580f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                            index, NULL /* uri */, &itemMeta));
5590f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber
5600f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                int64_t itemDurationUs;
5610f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                CHECK(itemMeta->findInt64("durationUs", &itemDurationUs));
5620f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber
5630f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                if (mSeekTimeUs < segmentStartUs + itemDurationUs) {
5640f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                    break;
5650f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                }
5660f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber
5670f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                segmentStartUs += itemDurationUs;
5680f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber                ++index;
5690f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber            }
5700f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber
5710f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber            if (index < mPlaylist->size()) {
57243c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber                int32_t newSeqNumber = firstSeqNumberInPlaylist + index;
573a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
57443c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber                if (newSeqNumber != mSeqNumber) {
57543c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber                    LOGI("seeking to seq no %d", newSeqNumber);
57643c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
57743c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber                    mSeqNumber = newSeqNumber;
57843c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
57943c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber                    mDataSource->reset();
58043c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
58122fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber                    // reseting the data source will have had the
58222fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber                    // side effect of discarding any previously queued
58322fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber                    // bandwidth change discontinuity.
58420f725ebcef13ded1b4b85c61c8a4b37cd030656Andreas Huber                    // Therefore we'll need to treat these seek
58522fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber                    // discontinuities as involving a bandwidth change
58622fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber                    // even if they aren't directly.
58720f725ebcef13ded1b4b85c61c8a4b37cd030656Andreas Huber                    seekDiscontinuity = true;
58822fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber                    bandwidthChanged = true;
58943c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber                }
590a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            }
591a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
592a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
593a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        mSeekTimeUs = -1;
594a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
595a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        Mutex::Autolock autoLock(mLock);
596a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        mSeekDone = true;
597a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        mCondition.broadcast();
598a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
599a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
600a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (mSeqNumber < 0) {
60120f725ebcef13ded1b4b85c61c8a4b37cd030656Andreas Huber        mSeqNumber = firstSeqNumberInPlaylist;
602a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
603a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
604a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    int32_t lastSeqNumberInPlaylist =
605a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        firstSeqNumberInPlaylist + (int32_t)mPlaylist->size() - 1;
606a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
607a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (mSeqNumber < firstSeqNumberInPlaylist
608a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            || mSeqNumber > lastSeqNumberInPlaylist) {
60988b7ad413c4b6d08697069b18488641d6ce31fd3Andreas Huber        if (mPrevBandwidthIndex != (ssize_t)bandwidthIndex) {
610aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber            // Go back to the previous bandwidth.
611aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber
612aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber            LOGI("new bandwidth does not have the sequence number "
613aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber                 "we're looking for, switching back to previous bandwidth");
614aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber
615aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber            mLastPlaylistFetchTimeUs = -1;
616aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber            bandwidthIndex = mPrevBandwidthIndex;
617aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber            goto rinse_repeat;
618aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber        }
619aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber
6206801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber        if (!mPlaylist->isComplete() && mNumRetries < kMaxNumRetries) {
621a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            ++mNumRetries;
622a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
6236801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber            if (mSeqNumber > lastSeqNumberInPlaylist) {
6246801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber                mLastPlaylistFetchTimeUs = -1;
6256801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber                postMonitorQueue(3000000ll);
6266801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber                return;
6276801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber            }
628a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
6296801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber            // we've missed the boat, let's start from the lowest sequence
6306801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber            // number available and signal a discontinuity.
631a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
6326801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber            LOGI("We've missed the boat, restarting playback.");
6336801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber            mSeqNumber = lastSeqNumberInPlaylist;
6346801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber            explicitDiscontinuity = true;
6356801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber
6366801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber            // fall through
6376801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber        } else {
6386801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber            LOGE("Cannot find sequence number %d in playlist "
6396801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber                 "(contains %d - %d)",
6406801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber                 mSeqNumber, firstSeqNumberInPlaylist,
6416801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber                 firstSeqNumberInPlaylist + mPlaylist->size() - 1);
6426801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber
6436801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber            mDataSource->queueEOS(ERROR_END_OF_STREAM);
6446801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber            return;
6456801b4dbd00b485ecdcd31b517ed885a8fa21c63Andreas Huber        }
646a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
647a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
648a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    mNumRetries = 0;
649a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
650a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    AString uri;
651a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<AMessage> itemMeta;
652a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    CHECK(mPlaylist->itemAt(
653a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                mSeqNumber - firstSeqNumberInPlaylist,
654a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                &uri,
655a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                &itemMeta));
656a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
657a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    int32_t val;
658a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (itemMeta->findInt32("discontinuity", &val) && val != 0) {
659a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        explicitDiscontinuity = true;
660a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
661a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
662a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<ABuffer> buffer;
663a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    status_t err = fetchFile(uri.c_str(), &buffer);
6646e6b1cae2bac1b78205cefab8e4e9e9538982965Andreas Huber    if (err != OK) {
6656e6b1cae2bac1b78205cefab8e4e9e9538982965Andreas Huber        LOGE("failed to fetch .ts segment at url '%s'", uri.c_str());
6666e6b1cae2bac1b78205cefab8e4e9e9538982965Andreas Huber        mDataSource->queueEOS(err);
6676e6b1cae2bac1b78205cefab8e4e9e9538982965Andreas Huber        return;
6686e6b1cae2bac1b78205cefab8e4e9e9538982965Andreas Huber    }
669a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
67043c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber    CHECK(buffer != NULL);
67143c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
67288b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber    err = decryptBuffer(mSeqNumber - firstSeqNumberInPlaylist, buffer);
67388b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber
67488b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber    if (err != OK) {
67588b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber        LOGE("decryptBuffer failed w/ error %d", err);
67688b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber
67788b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber        mDataSource->queueEOS(err);
67888b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber        return;
67988b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber    }
680a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
681a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (buffer->size() == 0 || buffer->data()[0] != 0x47) {
682a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        // Not a transport stream???
683a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
684a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        LOGE("This doesn't look like a transport stream...");
685a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
686bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber        mBandwidthItems.removeAt(bandwidthIndex);
687bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
688bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber        if (mBandwidthItems.isEmpty()) {
689bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber            mDataSource->queueEOS(ERROR_UNSUPPORTED);
690bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber            return;
691bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber        }
692bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
693bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber        LOGI("Retrying with a different bandwidth stream.");
694bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
695bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber        mLastPlaylistFetchTimeUs = -1;
696bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber        bandwidthIndex = getBandwidthIndex();
697bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber        mPrevBandwidthIndex = bandwidthIndex;
698bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber        mSeqNumber = -1;
699bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
700bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber        goto rinse_repeat;
701a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
702a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
70322fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber    if ((size_t)mPrevBandwidthIndex != bandwidthIndex) {
70422fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber        bandwidthChanged = true;
70522fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber    }
70622fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber
70722fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber    if (mPrevBandwidthIndex < 0) {
70822fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber        // Don't signal a bandwidth change at the very beginning of
70922fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber        // playback.
71022fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber        bandwidthChanged = false;
71122fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber    }
7123831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber
71320f725ebcef13ded1b4b85c61c8a4b37cd030656Andreas Huber    if (seekDiscontinuity || explicitDiscontinuity || bandwidthChanged) {
714a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        // Signal discontinuity.
715a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
71620f725ebcef13ded1b4b85c61c8a4b37cd030656Andreas Huber        LOGI("queueing discontinuity (seek=%d, explicit=%d, bandwidthChanged=%d)",
71720f725ebcef13ded1b4b85c61c8a4b37cd030656Andreas Huber             seekDiscontinuity, explicitDiscontinuity, bandwidthChanged);
71843c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
719a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        sp<ABuffer> tmp = new ABuffer(188);
720a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        memset(tmp->data(), 0, tmp->size());
72120f725ebcef13ded1b4b85c61c8a4b37cd030656Andreas Huber
72220f725ebcef13ded1b4b85c61c8a4b37cd030656Andreas Huber        // signal a 'hard' discontinuity for explicit or bandwidthChanged.
72320f725ebcef13ded1b4b85c61c8a4b37cd030656Andreas Huber        tmp->data()[1] = (explicitDiscontinuity || bandwidthChanged) ? 1 : 0;
724a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
725a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        mDataSource->queueBuffer(tmp);
726a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
727a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
728a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    mDataSource->queueBuffer(buffer);
729a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
730a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    mPrevBandwidthIndex = bandwidthIndex;
731a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    ++mSeqNumber;
732a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
733a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    postMonitorQueue();
734a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
735a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
736a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onMonitorQueue() {
737a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (mSeekTimeUs >= 0
738a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            || mDataSource->countQueuedBuffers() < kMaxNumQueuedFragments) {
739a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        onDownloadNext();
740a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else {
741a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        postMonitorQueue(1000000ll);
742a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
743a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
744a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
745a44153c1a57202fb538659eb50706e60454d6273Andreas Huberstatus_t LiveSession::decryptBuffer(
746a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        size_t playlistIndex, const sp<ABuffer> &buffer) {
747a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<AMessage> itemMeta;
748a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    bool found = false;
749a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    AString method;
750a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
751a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    for (ssize_t i = playlistIndex; i >= 0; --i) {
752a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        AString uri;
753a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        CHECK(mPlaylist->itemAt(i, &uri, &itemMeta));
754a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
755a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (itemMeta->findString("cipher-method", &method)) {
756a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            found = true;
757a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
758a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
759a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
760a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
761a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (!found) {
762a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        method = "NONE";
763a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
764a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
765a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (method == "NONE") {
766a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return OK;
767a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else if (!(method == "AES-128")) {
768a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        LOGE("Unsupported cipher method '%s'", method.c_str());
769a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return ERROR_UNSUPPORTED;
770a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
771a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
772a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    AString keyURI;
773a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (!itemMeta->findString("cipher-uri", &keyURI)) {
774a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        LOGE("Missing key uri");
775a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return ERROR_MALFORMED;
776a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
777a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
778a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    ssize_t index = mAESKeyForURI.indexOfKey(keyURI);
779a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
780a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<ABuffer> key;
781a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (index >= 0) {
782a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        key = mAESKeyForURI.valueAt(index);
783a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else {
784a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        key = new ABuffer(16);
785a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
7861156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        sp<HTTPBase> keySource =
7871156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber              HTTPBase::Create(
7881156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                  (mFlags & kFlagIncognito)
7891156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                    ? HTTPBase::kFlagIncognito
7901156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                    : 0);
7911156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
7929b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber        if (mUIDValid) {
7939b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber            keySource->setUID(mUID);
7949b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber        }
7959b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber
796d6a46a6bda23667e06ee5ccca3781e407c7d1204Andreas Huber        status_t err =
797d6a46a6bda23667e06ee5ccca3781e407c7d1204Andreas Huber            keySource->connect(
798d6a46a6bda23667e06ee5ccca3781e407c7d1204Andreas Huber                    keyURI.c_str(),
799d6a46a6bda23667e06ee5ccca3781e407c7d1204Andreas Huber                    mExtraHeaders.isEmpty() ? NULL : &mExtraHeaders);
800a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
801a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (err == OK) {
802a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            size_t offset = 0;
803a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            while (offset < 16) {
804a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                ssize_t n = keySource->readAt(
805a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                        offset, key->data() + offset, 16 - offset);
806a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                if (n <= 0) {
807a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                    err = ERROR_IO;
808a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                    break;
809a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                }
810a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
811a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                offset += n;
812a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            }
813a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
814a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
815a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (err != OK) {
816a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            LOGE("failed to fetch cipher key from '%s'.", keyURI.c_str());
817a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            return ERROR_IO;
818a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
819a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
820a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        mAESKeyForURI.add(keyURI, key);
821a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
822a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
823a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    AES_KEY aes_key;
824a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (AES_set_decrypt_key(key->data(), 128, &aes_key) != 0) {
825a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        LOGE("failed to set AES decryption key.");
826a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return UNKNOWN_ERROR;
827a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
828a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
829a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    unsigned char aes_ivec[16];
830a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
831a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    AString iv;
832a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (itemMeta->findString("cipher-iv", &iv)) {
833a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if ((!iv.startsWith("0x") && !iv.startsWith("0X"))
834a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                || iv.size() != 16 * 2 + 2) {
835a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            LOGE("malformed cipher IV '%s'.", iv.c_str());
836a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            return ERROR_MALFORMED;
837a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
838a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
839a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        memset(aes_ivec, 0, sizeof(aes_ivec));
840a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        for (size_t i = 0; i < 16; ++i) {
841a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            char c1 = tolower(iv.c_str()[2 + 2 * i]);
842a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            char c2 = tolower(iv.c_str()[3 + 2 * i]);
843a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            if (!isxdigit(c1) || !isxdigit(c2)) {
844a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                LOGE("malformed cipher IV '%s'.", iv.c_str());
845a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                return ERROR_MALFORMED;
846a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            }
847a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            uint8_t nibble1 = isdigit(c1) ? c1 - '0' : c1 - 'a' + 10;
848a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            uint8_t nibble2 = isdigit(c2) ? c2 - '0' : c2 - 'a' + 10;
849a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
850a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            aes_ivec[i] = nibble1 << 4 | nibble2;
851a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
852a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else {
853a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        memset(aes_ivec, 0, sizeof(aes_ivec));
854a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        aes_ivec[15] = mSeqNumber & 0xff;
855a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        aes_ivec[14] = (mSeqNumber >> 8) & 0xff;
856a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        aes_ivec[13] = (mSeqNumber >> 16) & 0xff;
857a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        aes_ivec[12] = (mSeqNumber >> 24) & 0xff;
858a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
859a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
860a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    AES_cbc_encrypt(
861a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            buffer->data(), buffer->data(), buffer->size(),
862a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            &aes_key, aes_ivec, AES_DECRYPT);
863a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
864a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // hexdump(buffer->data(), buffer->size());
865a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
866a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t n = buffer->size();
867a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    CHECK_GT(n, 0u);
868a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
869a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t pad = buffer->data()[n - 1];
870a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
871a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    CHECK_GT(pad, 0u);
872a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    CHECK_LE(pad, 16u);
873a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    CHECK_GE((size_t)n, pad);
874a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    for (size_t i = 0; i < pad; ++i) {
875a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        CHECK_EQ((unsigned)buffer->data()[n - 1 - i], pad);
876a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
877a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
878a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    n -= pad;
879a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
880a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    buffer->setRange(buffer->offset(), n);
881a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
882a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return OK;
883a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
884a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
885a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::postMonitorQueue(int64_t delayUs) {
886a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<AMessage> msg = new AMessage(kWhatMonitorQueue, id());
887a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    msg->setInt32("generation", ++mMonitorQueueGeneration);
888a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    msg->post(delayUs);
889a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
890a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
891a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onSeek(const sp<AMessage> &msg) {
892a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    int64_t timeUs;
893a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    CHECK(msg->findInt64("timeUs", &timeUs));
894a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
895a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    mSeekTimeUs = timeUs;
896a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    postMonitorQueue();
897a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
898a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
899a44153c1a57202fb538659eb50706e60454d6273Andreas Huberstatus_t LiveSession::getDuration(int64_t *durationUs) {
900a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    Mutex::Autolock autoLock(mLock);
901a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    *durationUs = mDurationUs;
902a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
903a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return OK;
904a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
905a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
906a44153c1a57202fb538659eb50706e60454d6273Andreas Huberbool LiveSession::isSeekable() {
907a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    int64_t durationUs;
908a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return getDuration(&durationUs) == OK && durationUs >= 0;
909a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
910a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
911a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}  // namespace android
912a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
913