1b5590846c035a28399818451201aaf1256913ec3Andreas Huber/*
2b5590846c035a28399818451201aaf1256913ec3Andreas Huber * Copyright (C) 2010 The Android Open Source Project
3b5590846c035a28399818451201aaf1256913ec3Andreas Huber *
4b5590846c035a28399818451201aaf1256913ec3Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5b5590846c035a28399818451201aaf1256913ec3Andreas Huber * you may not use this file except in compliance with the License.
6b5590846c035a28399818451201aaf1256913ec3Andreas Huber * You may obtain a copy of the License at
7b5590846c035a28399818451201aaf1256913ec3Andreas Huber *
8b5590846c035a28399818451201aaf1256913ec3Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
9b5590846c035a28399818451201aaf1256913ec3Andreas Huber *
10b5590846c035a28399818451201aaf1256913ec3Andreas Huber * Unless required by applicable law or agreed to in writing, software
11b5590846c035a28399818451201aaf1256913ec3Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12b5590846c035a28399818451201aaf1256913ec3Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b5590846c035a28399818451201aaf1256913ec3Andreas Huber * See the License for the specific language governing permissions and
14b5590846c035a28399818451201aaf1256913ec3Andreas Huber * limitations under the License.
15b5590846c035a28399818451201aaf1256913ec3Andreas Huber */
16b5590846c035a28399818451201aaf1256913ec3Andreas Huber
17b5590846c035a28399818451201aaf1256913ec3Andreas Huber//#define LOG_NDEBUG 0
18b5590846c035a28399818451201aaf1256913ec3Andreas Huber#define LOG_TAG "LiveSession"
19b5590846c035a28399818451201aaf1256913ec3Andreas Huber#include <utils/Log.h>
20b5590846c035a28399818451201aaf1256913ec3Andreas Huber
21b5590846c035a28399818451201aaf1256913ec3Andreas Huber#include "include/LiveSession.h"
22b5590846c035a28399818451201aaf1256913ec3Andreas Huber
23b5590846c035a28399818451201aaf1256913ec3Andreas Huber#include "LiveDataSource.h"
24b5590846c035a28399818451201aaf1256913ec3Andreas Huber
25b5590846c035a28399818451201aaf1256913ec3Andreas Huber#include "include/M3UParser.h"
265f5719e45b3c4e3237a45b019e0fcd86060974a8Andreas Huber#include "include/HTTPBase.h"
27b5590846c035a28399818451201aaf1256913ec3Andreas Huber
28b5590846c035a28399818451201aaf1256913ec3Andreas Huber#include <cutils/properties.h>
29b5590846c035a28399818451201aaf1256913ec3Andreas Huber#include <media/stagefright/foundation/hexdump.h>
30b5590846c035a28399818451201aaf1256913ec3Andreas Huber#include <media/stagefright/foundation/ABuffer.h>
31b5590846c035a28399818451201aaf1256913ec3Andreas Huber#include <media/stagefright/foundation/ADebug.h>
32b5590846c035a28399818451201aaf1256913ec3Andreas Huber#include <media/stagefright/foundation/AMessage.h>
33b5590846c035a28399818451201aaf1256913ec3Andreas Huber#include <media/stagefright/DataSource.h>
34b5590846c035a28399818451201aaf1256913ec3Andreas Huber#include <media/stagefright/FileSource.h>
35b5590846c035a28399818451201aaf1256913ec3Andreas Huber#include <media/stagefright/MediaErrors.h>
36b5590846c035a28399818451201aaf1256913ec3Andreas Huber
37b5590846c035a28399818451201aaf1256913ec3Andreas Huber#include <ctype.h>
38b5590846c035a28399818451201aaf1256913ec3Andreas Huber#include <openssl/aes.h>
39cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber#include <openssl/md5.h>
40b5590846c035a28399818451201aaf1256913ec3Andreas Huber
41b5590846c035a28399818451201aaf1256913ec3Andreas Hubernamespace android {
42b5590846c035a28399818451201aaf1256913ec3Andreas Huber
43603d739b5a444c52b63f1ec7cd2098034151ad25Andreas HuberLiveSession::LiveSession(uint32_t flags, bool uidValid, uid_t uid)
4453182c439cf16f910974fd1f9d6c3002dda445ebAndreas Huber    : mFlags(flags),
45603d739b5a444c52b63f1ec7cd2098034151ad25Andreas Huber      mUIDValid(uidValid),
46603d739b5a444c52b63f1ec7cd2098034151ad25Andreas Huber      mUID(uid),
4753182c439cf16f910974fd1f9d6c3002dda445ebAndreas Huber      mDataSource(new LiveDataSource),
4853182c439cf16f910974fd1f9d6c3002dda445ebAndreas Huber      mHTTPDataSource(
495f5719e45b3c4e3237a45b019e0fcd86060974a8Andreas Huber              HTTPBase::Create(
5053182c439cf16f910974fd1f9d6c3002dda445ebAndreas Huber                  (mFlags & kFlagIncognito)
515f5719e45b3c4e3237a45b019e0fcd86060974a8Andreas Huber                    ? HTTPBase::kFlagIncognito
5253182c439cf16f910974fd1f9d6c3002dda445ebAndreas Huber                    : 0)),
53b5590846c035a28399818451201aaf1256913ec3Andreas Huber      mPrevBandwidthIndex(-1),
54b5590846c035a28399818451201aaf1256913ec3Andreas Huber      mLastPlaylistFetchTimeUs(-1),
55b5590846c035a28399818451201aaf1256913ec3Andreas Huber      mSeqNumber(-1),
56b5590846c035a28399818451201aaf1256913ec3Andreas Huber      mSeekTimeUs(-1),
57b5590846c035a28399818451201aaf1256913ec3Andreas Huber      mNumRetries(0),
58b5590846c035a28399818451201aaf1256913ec3Andreas Huber      mDurationUs(-1),
59b5590846c035a28399818451201aaf1256913ec3Andreas Huber      mSeekDone(false),
6017ab86cdb1eb8b44780676177ad37a6c1df4cf5fAndreas Huber      mDisconnectPending(false),
61cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber      mMonitorQueueGeneration(0),
62cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber      mRefreshState(INITIAL_MINIMUM_RELOAD_DELAY) {
63603d739b5a444c52b63f1ec7cd2098034151ad25Andreas Huber    if (mUIDValid) {
64603d739b5a444c52b63f1ec7cd2098034151ad25Andreas Huber        mHTTPDataSource->setUID(mUID);
65603d739b5a444c52b63f1ec7cd2098034151ad25Andreas Huber    }
66b5590846c035a28399818451201aaf1256913ec3Andreas Huber}
67b5590846c035a28399818451201aaf1256913ec3Andreas Huber
68b5590846c035a28399818451201aaf1256913ec3Andreas HuberLiveSession::~LiveSession() {
69b5590846c035a28399818451201aaf1256913ec3Andreas Huber}
70b5590846c035a28399818451201aaf1256913ec3Andreas Huber
71b5590846c035a28399818451201aaf1256913ec3Andreas Hubersp<DataSource> LiveSession::getDataSource() {
72b5590846c035a28399818451201aaf1256913ec3Andreas Huber    return mDataSource;
73b5590846c035a28399818451201aaf1256913ec3Andreas Huber}
74b5590846c035a28399818451201aaf1256913ec3Andreas Huber
75508749401160a083ae02b6864c439f9b2f3068d6Andreas Hubervoid LiveSession::connect(
76508749401160a083ae02b6864c439f9b2f3068d6Andreas Huber        const char *url, const KeyedVector<String8, String8> *headers) {
77b5590846c035a28399818451201aaf1256913ec3Andreas Huber    sp<AMessage> msg = new AMessage(kWhatConnect, id());
78b5590846c035a28399818451201aaf1256913ec3Andreas Huber    msg->setString("url", url);
79508749401160a083ae02b6864c439f9b2f3068d6Andreas Huber
80508749401160a083ae02b6864c439f9b2f3068d6Andreas Huber    if (headers != NULL) {
81508749401160a083ae02b6864c439f9b2f3068d6Andreas Huber        msg->setPointer(
82508749401160a083ae02b6864c439f9b2f3068d6Andreas Huber                "headers",
83508749401160a083ae02b6864c439f9b2f3068d6Andreas Huber                new KeyedVector<String8, String8>(*headers));
84508749401160a083ae02b6864c439f9b2f3068d6Andreas Huber    }
85508749401160a083ae02b6864c439f9b2f3068d6Andreas Huber
86b5590846c035a28399818451201aaf1256913ec3Andreas Huber    msg->post();
87b5590846c035a28399818451201aaf1256913ec3Andreas Huber}
88b5590846c035a28399818451201aaf1256913ec3Andreas Huber
89b5590846c035a28399818451201aaf1256913ec3Andreas Hubervoid LiveSession::disconnect() {
9017ab86cdb1eb8b44780676177ad37a6c1df4cf5fAndreas Huber    Mutex::Autolock autoLock(mLock);
9117ab86cdb1eb8b44780676177ad37a6c1df4cf5fAndreas Huber    mDisconnectPending = true;
9217ab86cdb1eb8b44780676177ad37a6c1df4cf5fAndreas Huber
9317ab86cdb1eb8b44780676177ad37a6c1df4cf5fAndreas Huber    mHTTPDataSource->disconnect();
9417ab86cdb1eb8b44780676177ad37a6c1df4cf5fAndreas Huber
95b5590846c035a28399818451201aaf1256913ec3Andreas Huber    (new AMessage(kWhatDisconnect, id()))->post();
96b5590846c035a28399818451201aaf1256913ec3Andreas Huber}
97b5590846c035a28399818451201aaf1256913ec3Andreas Huber
98b5590846c035a28399818451201aaf1256913ec3Andreas Hubervoid LiveSession::seekTo(int64_t timeUs) {
99b5590846c035a28399818451201aaf1256913ec3Andreas Huber    Mutex::Autolock autoLock(mLock);
100b5590846c035a28399818451201aaf1256913ec3Andreas Huber    mSeekDone = false;
101b5590846c035a28399818451201aaf1256913ec3Andreas Huber
102b5590846c035a28399818451201aaf1256913ec3Andreas Huber    sp<AMessage> msg = new AMessage(kWhatSeek, id());
103b5590846c035a28399818451201aaf1256913ec3Andreas Huber    msg->setInt64("timeUs", timeUs);
104b5590846c035a28399818451201aaf1256913ec3Andreas Huber    msg->post();
105b5590846c035a28399818451201aaf1256913ec3Andreas Huber
106b5590846c035a28399818451201aaf1256913ec3Andreas Huber    while (!mSeekDone) {
107b5590846c035a28399818451201aaf1256913ec3Andreas Huber        mCondition.wait(mLock);
108b5590846c035a28399818451201aaf1256913ec3Andreas Huber    }
109b5590846c035a28399818451201aaf1256913ec3Andreas Huber}
110b5590846c035a28399818451201aaf1256913ec3Andreas Huber
111b5590846c035a28399818451201aaf1256913ec3Andreas Hubervoid LiveSession::onMessageReceived(const sp<AMessage> &msg) {
112b5590846c035a28399818451201aaf1256913ec3Andreas Huber    switch (msg->what()) {
113b5590846c035a28399818451201aaf1256913ec3Andreas Huber        case kWhatConnect:
114b5590846c035a28399818451201aaf1256913ec3Andreas Huber            onConnect(msg);
115b5590846c035a28399818451201aaf1256913ec3Andreas Huber            break;
116b5590846c035a28399818451201aaf1256913ec3Andreas Huber
117b5590846c035a28399818451201aaf1256913ec3Andreas Huber        case kWhatDisconnect:
118b5590846c035a28399818451201aaf1256913ec3Andreas Huber            onDisconnect();
119b5590846c035a28399818451201aaf1256913ec3Andreas Huber            break;
120b5590846c035a28399818451201aaf1256913ec3Andreas Huber
121b5590846c035a28399818451201aaf1256913ec3Andreas Huber        case kWhatMonitorQueue:
122b5590846c035a28399818451201aaf1256913ec3Andreas Huber        {
123b5590846c035a28399818451201aaf1256913ec3Andreas Huber            int32_t generation;
124b5590846c035a28399818451201aaf1256913ec3Andreas Huber            CHECK(msg->findInt32("generation", &generation));
125b5590846c035a28399818451201aaf1256913ec3Andreas Huber
126b5590846c035a28399818451201aaf1256913ec3Andreas Huber            if (generation != mMonitorQueueGeneration) {
127b5590846c035a28399818451201aaf1256913ec3Andreas Huber                // Stale event
128b5590846c035a28399818451201aaf1256913ec3Andreas Huber                break;
129b5590846c035a28399818451201aaf1256913ec3Andreas Huber            }
130b5590846c035a28399818451201aaf1256913ec3Andreas Huber
131b5590846c035a28399818451201aaf1256913ec3Andreas Huber            onMonitorQueue();
132b5590846c035a28399818451201aaf1256913ec3Andreas Huber            break;
133b5590846c035a28399818451201aaf1256913ec3Andreas Huber        }
134b5590846c035a28399818451201aaf1256913ec3Andreas Huber
135b5590846c035a28399818451201aaf1256913ec3Andreas Huber        case kWhatSeek:
136b5590846c035a28399818451201aaf1256913ec3Andreas Huber            onSeek(msg);
137b5590846c035a28399818451201aaf1256913ec3Andreas Huber            break;
138b5590846c035a28399818451201aaf1256913ec3Andreas Huber
139b5590846c035a28399818451201aaf1256913ec3Andreas Huber        default:
140b5590846c035a28399818451201aaf1256913ec3Andreas Huber            TRESPASS();
141b5590846c035a28399818451201aaf1256913ec3Andreas Huber            break;
142b5590846c035a28399818451201aaf1256913ec3Andreas Huber    }
143b5590846c035a28399818451201aaf1256913ec3Andreas Huber}
144b5590846c035a28399818451201aaf1256913ec3Andreas Huber
145b5590846c035a28399818451201aaf1256913ec3Andreas Huber// static
146b5590846c035a28399818451201aaf1256913ec3Andreas Huberint LiveSession::SortByBandwidth(const BandwidthItem *a, const BandwidthItem *b) {
147b5590846c035a28399818451201aaf1256913ec3Andreas Huber    if (a->mBandwidth < b->mBandwidth) {
148b5590846c035a28399818451201aaf1256913ec3Andreas Huber        return -1;
149b5590846c035a28399818451201aaf1256913ec3Andreas Huber    } else if (a->mBandwidth == b->mBandwidth) {
150b5590846c035a28399818451201aaf1256913ec3Andreas Huber        return 0;
151b5590846c035a28399818451201aaf1256913ec3Andreas Huber    }
152b5590846c035a28399818451201aaf1256913ec3Andreas Huber
153b5590846c035a28399818451201aaf1256913ec3Andreas Huber    return 1;
154b5590846c035a28399818451201aaf1256913ec3Andreas Huber}
155b5590846c035a28399818451201aaf1256913ec3Andreas Huber
156b5590846c035a28399818451201aaf1256913ec3Andreas Hubervoid LiveSession::onConnect(const sp<AMessage> &msg) {
157b5590846c035a28399818451201aaf1256913ec3Andreas Huber    AString url;
158b5590846c035a28399818451201aaf1256913ec3Andreas Huber    CHECK(msg->findString("url", &url));
159b5590846c035a28399818451201aaf1256913ec3Andreas Huber
160508749401160a083ae02b6864c439f9b2f3068d6Andreas Huber    KeyedVector<String8, String8> *headers = NULL;
161508749401160a083ae02b6864c439f9b2f3068d6Andreas Huber    if (!msg->findPointer("headers", (void **)&headers)) {
162508749401160a083ae02b6864c439f9b2f3068d6Andreas Huber        mExtraHeaders.clear();
163508749401160a083ae02b6864c439f9b2f3068d6Andreas Huber    } else {
164508749401160a083ae02b6864c439f9b2f3068d6Andreas Huber        mExtraHeaders = *headers;
165508749401160a083ae02b6864c439f9b2f3068d6Andreas Huber
166508749401160a083ae02b6864c439f9b2f3068d6Andreas Huber        delete headers;
167508749401160a083ae02b6864c439f9b2f3068d6Andreas Huber        headers = NULL;
168508749401160a083ae02b6864c439f9b2f3068d6Andreas Huber    }
169508749401160a083ae02b6864c439f9b2f3068d6Andreas Huber
17053182c439cf16f910974fd1f9d6c3002dda445ebAndreas Huber    if (!(mFlags & kFlagIncognito)) {
17153182c439cf16f910974fd1f9d6c3002dda445ebAndreas Huber        LOGI("onConnect '%s'", url.c_str());
17253182c439cf16f910974fd1f9d6c3002dda445ebAndreas Huber    } else {
17353182c439cf16f910974fd1f9d6c3002dda445ebAndreas Huber        LOGI("onConnect <URL suppressed>");
17453182c439cf16f910974fd1f9d6c3002dda445ebAndreas Huber    }
175b5590846c035a28399818451201aaf1256913ec3Andreas Huber
176b5590846c035a28399818451201aaf1256913ec3Andreas Huber    mMasterURL = url;
177b5590846c035a28399818451201aaf1256913ec3Andreas Huber
178cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber    bool dummy;
179cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber    sp<M3UParser> playlist = fetchPlaylist(url.c_str(), &dummy);
18017ab86cdb1eb8b44780676177ad37a6c1df4cf5fAndreas Huber
18117ab86cdb1eb8b44780676177ad37a6c1df4cf5fAndreas Huber    if (playlist == NULL) {
18217ab86cdb1eb8b44780676177ad37a6c1df4cf5fAndreas Huber        LOGE("unable to fetch master playlist '%s'.", url.c_str());
18317ab86cdb1eb8b44780676177ad37a6c1df4cf5fAndreas Huber
18417ab86cdb1eb8b44780676177ad37a6c1df4cf5fAndreas Huber        mDataSource->queueEOS(ERROR_IO);
18517ab86cdb1eb8b44780676177ad37a6c1df4cf5fAndreas Huber        return;
18617ab86cdb1eb8b44780676177ad37a6c1df4cf5fAndreas Huber    }
187b5590846c035a28399818451201aaf1256913ec3Andreas Huber
188b5590846c035a28399818451201aaf1256913ec3Andreas Huber    if (playlist->isVariantPlaylist()) {
189b5590846c035a28399818451201aaf1256913ec3Andreas Huber        for (size_t i = 0; i < playlist->size(); ++i) {
190b5590846c035a28399818451201aaf1256913ec3Andreas Huber            BandwidthItem item;
191b5590846c035a28399818451201aaf1256913ec3Andreas Huber
192b5590846c035a28399818451201aaf1256913ec3Andreas Huber            sp<AMessage> meta;
193b5590846c035a28399818451201aaf1256913ec3Andreas Huber            playlist->itemAt(i, &item.mURI, &meta);
194b5590846c035a28399818451201aaf1256913ec3Andreas Huber
195b5590846c035a28399818451201aaf1256913ec3Andreas Huber            unsigned long bandwidth;
196b5590846c035a28399818451201aaf1256913ec3Andreas Huber            CHECK(meta->findInt32("bandwidth", (int32_t *)&item.mBandwidth));
197b5590846c035a28399818451201aaf1256913ec3Andreas Huber
198b5590846c035a28399818451201aaf1256913ec3Andreas Huber            mBandwidthItems.push(item);
199b5590846c035a28399818451201aaf1256913ec3Andreas Huber        }
200b5590846c035a28399818451201aaf1256913ec3Andreas Huber
201b5590846c035a28399818451201aaf1256913ec3Andreas Huber        CHECK_GT(mBandwidthItems.size(), 0u);
202b5590846c035a28399818451201aaf1256913ec3Andreas Huber
203b5590846c035a28399818451201aaf1256913ec3Andreas Huber        mBandwidthItems.sort(SortByBandwidth);
204b5590846c035a28399818451201aaf1256913ec3Andreas Huber    }
205b5590846c035a28399818451201aaf1256913ec3Andreas Huber
206b5590846c035a28399818451201aaf1256913ec3Andreas Huber    postMonitorQueue();
207b5590846c035a28399818451201aaf1256913ec3Andreas Huber}
208b5590846c035a28399818451201aaf1256913ec3Andreas Huber
209b5590846c035a28399818451201aaf1256913ec3Andreas Hubervoid LiveSession::onDisconnect() {
210b5590846c035a28399818451201aaf1256913ec3Andreas Huber    LOGI("onDisconnect");
211b5590846c035a28399818451201aaf1256913ec3Andreas Huber
212b5590846c035a28399818451201aaf1256913ec3Andreas Huber    mDataSource->queueEOS(ERROR_END_OF_STREAM);
21317ab86cdb1eb8b44780676177ad37a6c1df4cf5fAndreas Huber
21417ab86cdb1eb8b44780676177ad37a6c1df4cf5fAndreas Huber    Mutex::Autolock autoLock(mLock);
21517ab86cdb1eb8b44780676177ad37a6c1df4cf5fAndreas Huber    mDisconnectPending = false;
216b5590846c035a28399818451201aaf1256913ec3Andreas Huber}
217b5590846c035a28399818451201aaf1256913ec3Andreas Huber
218b5590846c035a28399818451201aaf1256913ec3Andreas Huberstatus_t LiveSession::fetchFile(const char *url, sp<ABuffer> *out) {
219b5590846c035a28399818451201aaf1256913ec3Andreas Huber    *out = NULL;
220b5590846c035a28399818451201aaf1256913ec3Andreas Huber
221b5590846c035a28399818451201aaf1256913ec3Andreas Huber    sp<DataSource> source;
222b5590846c035a28399818451201aaf1256913ec3Andreas Huber
223b5590846c035a28399818451201aaf1256913ec3Andreas Huber    if (!strncasecmp(url, "file://", 7)) {
224b5590846c035a28399818451201aaf1256913ec3Andreas Huber        source = new FileSource(url + 7);
225118a150a67f45130755d82491b4d98940c15dbd0Andreas Huber    } else if (strncasecmp(url, "http://", 7)
226118a150a67f45130755d82491b4d98940c15dbd0Andreas Huber            && strncasecmp(url, "https://", 8)) {
227c0bfdb257c95486d2b6d60745deb8f04c07cbb95Andreas Huber        return ERROR_UNSUPPORTED;
228b5590846c035a28399818451201aaf1256913ec3Andreas Huber    } else {
22917ab86cdb1eb8b44780676177ad37a6c1df4cf5fAndreas Huber        {
23017ab86cdb1eb8b44780676177ad37a6c1df4cf5fAndreas Huber            Mutex::Autolock autoLock(mLock);
23117ab86cdb1eb8b44780676177ad37a6c1df4cf5fAndreas Huber
23217ab86cdb1eb8b44780676177ad37a6c1df4cf5fAndreas Huber            if (mDisconnectPending) {
23317ab86cdb1eb8b44780676177ad37a6c1df4cf5fAndreas Huber                return ERROR_IO;
23417ab86cdb1eb8b44780676177ad37a6c1df4cf5fAndreas Huber            }
23517ab86cdb1eb8b44780676177ad37a6c1df4cf5fAndreas Huber        }
23617ab86cdb1eb8b44780676177ad37a6c1df4cf5fAndreas Huber
237508749401160a083ae02b6864c439f9b2f3068d6Andreas Huber        status_t err = mHTTPDataSource->connect(
238508749401160a083ae02b6864c439f9b2f3068d6Andreas Huber                url, mExtraHeaders.isEmpty() ? NULL : &mExtraHeaders);
239b5590846c035a28399818451201aaf1256913ec3Andreas Huber
240b5590846c035a28399818451201aaf1256913ec3Andreas Huber        if (err != OK) {
241b5590846c035a28399818451201aaf1256913ec3Andreas Huber            return err;
242b5590846c035a28399818451201aaf1256913ec3Andreas Huber        }
243b5590846c035a28399818451201aaf1256913ec3Andreas Huber
244b5590846c035a28399818451201aaf1256913ec3Andreas Huber        source = mHTTPDataSource;
245b5590846c035a28399818451201aaf1256913ec3Andreas Huber    }
246b5590846c035a28399818451201aaf1256913ec3Andreas Huber
247b5590846c035a28399818451201aaf1256913ec3Andreas Huber    off64_t size;
248b5590846c035a28399818451201aaf1256913ec3Andreas Huber    status_t err = source->getSize(&size);
249b5590846c035a28399818451201aaf1256913ec3Andreas Huber
250b5590846c035a28399818451201aaf1256913ec3Andreas Huber    if (err != OK) {
251b5590846c035a28399818451201aaf1256913ec3Andreas Huber        size = 65536;
252b5590846c035a28399818451201aaf1256913ec3Andreas Huber    }
253b5590846c035a28399818451201aaf1256913ec3Andreas Huber
254b5590846c035a28399818451201aaf1256913ec3Andreas Huber    sp<ABuffer> buffer = new ABuffer(size);
255b5590846c035a28399818451201aaf1256913ec3Andreas Huber    buffer->setRange(0, 0);
256b5590846c035a28399818451201aaf1256913ec3Andreas Huber
257b5590846c035a28399818451201aaf1256913ec3Andreas Huber    for (;;) {
258b5590846c035a28399818451201aaf1256913ec3Andreas Huber        size_t bufferRemaining = buffer->capacity() - buffer->size();
259b5590846c035a28399818451201aaf1256913ec3Andreas Huber
260b5590846c035a28399818451201aaf1256913ec3Andreas Huber        if (bufferRemaining == 0) {
261b5590846c035a28399818451201aaf1256913ec3Andreas Huber            bufferRemaining = 32768;
262b5590846c035a28399818451201aaf1256913ec3Andreas Huber
263b5590846c035a28399818451201aaf1256913ec3Andreas Huber            LOGV("increasing download buffer to %d bytes",
264b5590846c035a28399818451201aaf1256913ec3Andreas Huber                 buffer->size() + bufferRemaining);
265b5590846c035a28399818451201aaf1256913ec3Andreas Huber
266b5590846c035a28399818451201aaf1256913ec3Andreas Huber            sp<ABuffer> copy = new ABuffer(buffer->size() + bufferRemaining);
267b5590846c035a28399818451201aaf1256913ec3Andreas Huber            memcpy(copy->data(), buffer->data(), buffer->size());
268b5590846c035a28399818451201aaf1256913ec3Andreas Huber            copy->setRange(0, buffer->size());
269b5590846c035a28399818451201aaf1256913ec3Andreas Huber
270b5590846c035a28399818451201aaf1256913ec3Andreas Huber            buffer = copy;
271b5590846c035a28399818451201aaf1256913ec3Andreas Huber        }
272b5590846c035a28399818451201aaf1256913ec3Andreas Huber
273b5590846c035a28399818451201aaf1256913ec3Andreas Huber        ssize_t n = source->readAt(
274b5590846c035a28399818451201aaf1256913ec3Andreas Huber                buffer->size(), buffer->data() + buffer->size(),
275b5590846c035a28399818451201aaf1256913ec3Andreas Huber                bufferRemaining);
276b5590846c035a28399818451201aaf1256913ec3Andreas Huber
277b5590846c035a28399818451201aaf1256913ec3Andreas Huber        if (n < 0) {
27824b3a4ccd6943dfb9f2cb69d5c9d78a05e16561bAndreas Huber            return n;
279b5590846c035a28399818451201aaf1256913ec3Andreas Huber        }
280b5590846c035a28399818451201aaf1256913ec3Andreas Huber
281b5590846c035a28399818451201aaf1256913ec3Andreas Huber        if (n == 0) {
282b5590846c035a28399818451201aaf1256913ec3Andreas Huber            break;
283b5590846c035a28399818451201aaf1256913ec3Andreas Huber        }
284b5590846c035a28399818451201aaf1256913ec3Andreas Huber
285b5590846c035a28399818451201aaf1256913ec3Andreas Huber        buffer->setRange(0, buffer->size() + (size_t)n);
286b5590846c035a28399818451201aaf1256913ec3Andreas Huber    }
287b5590846c035a28399818451201aaf1256913ec3Andreas Huber
288b5590846c035a28399818451201aaf1256913ec3Andreas Huber    *out = buffer;
289b5590846c035a28399818451201aaf1256913ec3Andreas Huber
290b5590846c035a28399818451201aaf1256913ec3Andreas Huber    return OK;
291b5590846c035a28399818451201aaf1256913ec3Andreas Huber}
292b5590846c035a28399818451201aaf1256913ec3Andreas Huber
293cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Hubersp<M3UParser> LiveSession::fetchPlaylist(const char *url, bool *unchanged) {
294cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber    *unchanged = false;
295cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber
296b5590846c035a28399818451201aaf1256913ec3Andreas Huber    sp<ABuffer> buffer;
297b5590846c035a28399818451201aaf1256913ec3Andreas Huber    status_t err = fetchFile(url, &buffer);
298b5590846c035a28399818451201aaf1256913ec3Andreas Huber
299b5590846c035a28399818451201aaf1256913ec3Andreas Huber    if (err != OK) {
300b5590846c035a28399818451201aaf1256913ec3Andreas Huber        return NULL;
301b5590846c035a28399818451201aaf1256913ec3Andreas Huber    }
302b5590846c035a28399818451201aaf1256913ec3Andreas Huber
303cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber    // MD5 functionality is not available on the simulator, treat all
304cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber    // playlists as changed.
305cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber
306cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber#if defined(HAVE_ANDROID_OS)
307cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber    uint8_t hash[16];
308cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber
309cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber    MD5_CTX m;
310cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber    MD5_Init(&m);
311cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber    MD5_Update(&m, buffer->data(), buffer->size());
312cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber
313cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber    MD5_Final(hash, &m);
314cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber
315cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber    if (mPlaylist != NULL && !memcmp(hash, mPlaylistHash, 16)) {
316cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber        // playlist unchanged
317cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber
318cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber        if (mRefreshState != THIRD_UNCHANGED_RELOAD_ATTEMPT) {
319cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber            mRefreshState = (RefreshState)(mRefreshState + 1);
320cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber        }
321cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber
322cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber        *unchanged = true;
323cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber
324cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber        LOGV("Playlist unchanged, refresh state is now %d",
325cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber             (int)mRefreshState);
326cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber
327cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber        return NULL;
328cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber    }
329cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber
330cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber    memcpy(mPlaylistHash, hash, sizeof(hash));
331cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber
332cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber    mRefreshState = INITIAL_MINIMUM_RELOAD_DELAY;
333cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber#endif
334cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber
335b5590846c035a28399818451201aaf1256913ec3Andreas Huber    sp<M3UParser> playlist =
336b5590846c035a28399818451201aaf1256913ec3Andreas Huber        new M3UParser(url, buffer->data(), buffer->size());
337b5590846c035a28399818451201aaf1256913ec3Andreas Huber
338b5590846c035a28399818451201aaf1256913ec3Andreas Huber    if (playlist->initCheck() != OK) {
339467bc257556a02a71164bcd03fec8b1ec99e460bAndreas Huber        LOGE("failed to parse .m3u8 playlist");
340467bc257556a02a71164bcd03fec8b1ec99e460bAndreas Huber
341b5590846c035a28399818451201aaf1256913ec3Andreas Huber        return NULL;
342b5590846c035a28399818451201aaf1256913ec3Andreas Huber    }
343b5590846c035a28399818451201aaf1256913ec3Andreas Huber
344b5590846c035a28399818451201aaf1256913ec3Andreas Huber    return playlist;
345b5590846c035a28399818451201aaf1256913ec3Andreas Huber}
346b5590846c035a28399818451201aaf1256913ec3Andreas Huber
347b5590846c035a28399818451201aaf1256913ec3Andreas Huberstatic double uniformRand() {
348b5590846c035a28399818451201aaf1256913ec3Andreas Huber    return (double)rand() / RAND_MAX;
349b5590846c035a28399818451201aaf1256913ec3Andreas Huber}
350b5590846c035a28399818451201aaf1256913ec3Andreas Huber
351b5590846c035a28399818451201aaf1256913ec3Andreas Hubersize_t LiveSession::getBandwidthIndex() {
352b5590846c035a28399818451201aaf1256913ec3Andreas Huber    if (mBandwidthItems.size() == 0) {
353b5590846c035a28399818451201aaf1256913ec3Andreas Huber        return 0;
354b5590846c035a28399818451201aaf1256913ec3Andreas Huber    }
355b5590846c035a28399818451201aaf1256913ec3Andreas Huber
356b5590846c035a28399818451201aaf1256913ec3Andreas Huber#if 1
357b5590846c035a28399818451201aaf1256913ec3Andreas Huber    int32_t bandwidthBps;
358b5590846c035a28399818451201aaf1256913ec3Andreas Huber    if (mHTTPDataSource != NULL
359b5590846c035a28399818451201aaf1256913ec3Andreas Huber            && mHTTPDataSource->estimateBandwidth(&bandwidthBps)) {
360b5590846c035a28399818451201aaf1256913ec3Andreas Huber        LOGV("bandwidth estimated at %.2f kbps", bandwidthBps / 1024.0f);
361b5590846c035a28399818451201aaf1256913ec3Andreas Huber    } else {
362b5590846c035a28399818451201aaf1256913ec3Andreas Huber        LOGV("no bandwidth estimate.");
363b5590846c035a28399818451201aaf1256913ec3Andreas Huber        return 0;  // Pick the lowest bandwidth stream by default.
364b5590846c035a28399818451201aaf1256913ec3Andreas Huber    }
365b5590846c035a28399818451201aaf1256913ec3Andreas Huber
366b5590846c035a28399818451201aaf1256913ec3Andreas Huber    char value[PROPERTY_VALUE_MAX];
367b5590846c035a28399818451201aaf1256913ec3Andreas Huber    if (property_get("media.httplive.max-bw", value, NULL)) {
368b5590846c035a28399818451201aaf1256913ec3Andreas Huber        char *end;
369b5590846c035a28399818451201aaf1256913ec3Andreas Huber        long maxBw = strtoul(value, &end, 10);
370b5590846c035a28399818451201aaf1256913ec3Andreas Huber        if (end > value && *end == '\0') {
371b5590846c035a28399818451201aaf1256913ec3Andreas Huber            if (maxBw > 0 && bandwidthBps > maxBw) {
372b5590846c035a28399818451201aaf1256913ec3Andreas Huber                LOGV("bandwidth capped to %ld bps", maxBw);
373b5590846c035a28399818451201aaf1256913ec3Andreas Huber                bandwidthBps = maxBw;
374b5590846c035a28399818451201aaf1256913ec3Andreas Huber            }
375b5590846c035a28399818451201aaf1256913ec3Andreas Huber        }
376b5590846c035a28399818451201aaf1256913ec3Andreas Huber    }
377b5590846c035a28399818451201aaf1256913ec3Andreas Huber
378b5590846c035a28399818451201aaf1256913ec3Andreas Huber    // Consider only 80% of the available bandwidth usable.
379b5590846c035a28399818451201aaf1256913ec3Andreas Huber    bandwidthBps = (bandwidthBps * 8) / 10;
380b5590846c035a28399818451201aaf1256913ec3Andreas Huber
381b5590846c035a28399818451201aaf1256913ec3Andreas Huber    // Pick the highest bandwidth stream below or equal to estimated bandwidth.
382b5590846c035a28399818451201aaf1256913ec3Andreas Huber
383b5590846c035a28399818451201aaf1256913ec3Andreas Huber    size_t index = mBandwidthItems.size() - 1;
384b5590846c035a28399818451201aaf1256913ec3Andreas Huber    while (index > 0 && mBandwidthItems.itemAt(index).mBandwidth
385b5590846c035a28399818451201aaf1256913ec3Andreas Huber                            > (size_t)bandwidthBps) {
386b5590846c035a28399818451201aaf1256913ec3Andreas Huber        --index;
387b5590846c035a28399818451201aaf1256913ec3Andreas Huber    }
388b5590846c035a28399818451201aaf1256913ec3Andreas Huber#elif 0
389b5590846c035a28399818451201aaf1256913ec3Andreas Huber    // Change bandwidth at random()
390b5590846c035a28399818451201aaf1256913ec3Andreas Huber    size_t index = uniformRand() * mBandwidthItems.size();
391b5590846c035a28399818451201aaf1256913ec3Andreas Huber#elif 0
392b5590846c035a28399818451201aaf1256913ec3Andreas Huber    // There's a 50% chance to stay on the current bandwidth and
393b5590846c035a28399818451201aaf1256913ec3Andreas Huber    // a 50% chance to switch to the next higher bandwidth (wrapping around
394b5590846c035a28399818451201aaf1256913ec3Andreas Huber    // to lowest)
395b5590846c035a28399818451201aaf1256913ec3Andreas Huber    const size_t kMinIndex = 0;
396b5590846c035a28399818451201aaf1256913ec3Andreas Huber
397b5590846c035a28399818451201aaf1256913ec3Andreas Huber    size_t index;
398b5590846c035a28399818451201aaf1256913ec3Andreas Huber    if (mPrevBandwidthIndex < 0) {
399b5590846c035a28399818451201aaf1256913ec3Andreas Huber        index = kMinIndex;
400b5590846c035a28399818451201aaf1256913ec3Andreas Huber    } else if (uniformRand() < 0.5) {
401b5590846c035a28399818451201aaf1256913ec3Andreas Huber        index = (size_t)mPrevBandwidthIndex;
402b5590846c035a28399818451201aaf1256913ec3Andreas Huber    } else {
403b5590846c035a28399818451201aaf1256913ec3Andreas Huber        index = mPrevBandwidthIndex + 1;
404b5590846c035a28399818451201aaf1256913ec3Andreas Huber        if (index == mBandwidthItems.size()) {
405b5590846c035a28399818451201aaf1256913ec3Andreas Huber            index = kMinIndex;
406b5590846c035a28399818451201aaf1256913ec3Andreas Huber        }
407b5590846c035a28399818451201aaf1256913ec3Andreas Huber    }
408b5590846c035a28399818451201aaf1256913ec3Andreas Huber#elif 0
409b5590846c035a28399818451201aaf1256913ec3Andreas Huber    // Pick the highest bandwidth stream below or equal to 1.2 Mbit/sec
410b5590846c035a28399818451201aaf1256913ec3Andreas Huber
411b5590846c035a28399818451201aaf1256913ec3Andreas Huber    size_t index = mBandwidthItems.size() - 1;
412b5590846c035a28399818451201aaf1256913ec3Andreas Huber    while (index > 0 && mBandwidthItems.itemAt(index).mBandwidth > 1200000) {
413b5590846c035a28399818451201aaf1256913ec3Andreas Huber        --index;
414b5590846c035a28399818451201aaf1256913ec3Andreas Huber    }
415b5590846c035a28399818451201aaf1256913ec3Andreas Huber#else
416b5590846c035a28399818451201aaf1256913ec3Andreas Huber    size_t index = mBandwidthItems.size() - 1;  // Highest bandwidth stream
417b5590846c035a28399818451201aaf1256913ec3Andreas Huber#endif
418b5590846c035a28399818451201aaf1256913ec3Andreas Huber
419b5590846c035a28399818451201aaf1256913ec3Andreas Huber    return index;
420b5590846c035a28399818451201aaf1256913ec3Andreas Huber}
421b5590846c035a28399818451201aaf1256913ec3Andreas Huber
422cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huberbool LiveSession::timeToRefreshPlaylist(int64_t nowUs) const {
423cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber    if (mPlaylist == NULL) {
424cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber        CHECK_EQ((int)mRefreshState, (int)INITIAL_MINIMUM_RELOAD_DELAY);
425cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber        return true;
426cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber    }
427cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber
428cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber    int32_t targetDurationSecs;
429cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber    CHECK(mPlaylist->meta()->findInt32("target-duration", &targetDurationSecs));
430cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber
431cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber    int64_t targetDurationUs = targetDurationSecs * 1000000ll;
432cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber
433cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber    int64_t minPlaylistAgeUs;
434cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber
435cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber    switch (mRefreshState) {
436cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber        case INITIAL_MINIMUM_RELOAD_DELAY:
437cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber        {
438cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber            size_t n = mPlaylist->size();
439cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber            if (n > 0) {
440cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber                sp<AMessage> itemMeta;
441cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber                CHECK(mPlaylist->itemAt(n - 1, NULL /* uri */, &itemMeta));
442cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber
443cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber                int64_t itemDurationUs;
444cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber                CHECK(itemMeta->findInt64("durationUs", &itemDurationUs));
445cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber
446cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber                minPlaylistAgeUs = itemDurationUs;
447cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber                break;
448cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber            }
449cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber
450cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber            // fall through
451cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber        }
452cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber
453cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber        case FIRST_UNCHANGED_RELOAD_ATTEMPT:
454cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber        {
455cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber            minPlaylistAgeUs = targetDurationUs / 2;
456cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber            break;
457cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber        }
458cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber
459cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber        case SECOND_UNCHANGED_RELOAD_ATTEMPT:
460cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber        {
461cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber            minPlaylistAgeUs = (targetDurationUs * 3) / 2;
462cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber            break;
463cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber        }
464cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber
465cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber        case THIRD_UNCHANGED_RELOAD_ATTEMPT:
466cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber        {
467cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber            minPlaylistAgeUs = targetDurationUs * 3;
468cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber            break;
469cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber        }
470cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber
471cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber        default:
472cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber            TRESPASS();
473cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber            break;
474cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber    }
475cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber
476cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber    return mLastPlaylistFetchTimeUs + minPlaylistAgeUs <= nowUs;
477cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber}
478cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber
479b5590846c035a28399818451201aaf1256913ec3Andreas Hubervoid LiveSession::onDownloadNext() {
480b5590846c035a28399818451201aaf1256913ec3Andreas Huber    size_t bandwidthIndex = getBandwidthIndex();
481b5590846c035a28399818451201aaf1256913ec3Andreas Huber
482ba572aaea62ba5d220891ff58642ccee3ad20decAndreas Huberrinse_repeat:
483b5590846c035a28399818451201aaf1256913ec3Andreas Huber    int64_t nowUs = ALooper::GetNowUs();
484b5590846c035a28399818451201aaf1256913ec3Andreas Huber
485b5590846c035a28399818451201aaf1256913ec3Andreas Huber    if (mLastPlaylistFetchTimeUs < 0
486b5590846c035a28399818451201aaf1256913ec3Andreas Huber            || (ssize_t)bandwidthIndex != mPrevBandwidthIndex
487cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber            || (!mPlaylist->isComplete() && timeToRefreshPlaylist(nowUs))) {
488b5590846c035a28399818451201aaf1256913ec3Andreas Huber        AString url;
489b5590846c035a28399818451201aaf1256913ec3Andreas Huber        if (mBandwidthItems.size() > 0) {
490b5590846c035a28399818451201aaf1256913ec3Andreas Huber            url = mBandwidthItems.editItemAt(bandwidthIndex).mURI;
491b5590846c035a28399818451201aaf1256913ec3Andreas Huber        } else {
492b5590846c035a28399818451201aaf1256913ec3Andreas Huber            url = mMasterURL;
493b5590846c035a28399818451201aaf1256913ec3Andreas Huber        }
494b5590846c035a28399818451201aaf1256913ec3Andreas Huber
495b5590846c035a28399818451201aaf1256913ec3Andreas Huber        bool firstTime = (mPlaylist == NULL);
496b5590846c035a28399818451201aaf1256913ec3Andreas Huber
49786806f75b49a18c4d7f7b2c986a628a0f7c1864fAndreas Huber        if ((ssize_t)bandwidthIndex != mPrevBandwidthIndex) {
49886806f75b49a18c4d7f7b2c986a628a0f7c1864fAndreas Huber            // If we switch bandwidths, do not pay any heed to whether
49986806f75b49a18c4d7f7b2c986a628a0f7c1864fAndreas Huber            // playlists changed since the last time...
50086806f75b49a18c4d7f7b2c986a628a0f7c1864fAndreas Huber            mPlaylist.clear();
50186806f75b49a18c4d7f7b2c986a628a0f7c1864fAndreas Huber        }
50286806f75b49a18c4d7f7b2c986a628a0f7c1864fAndreas Huber
503cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber        bool unchanged;
504cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber        sp<M3UParser> playlist = fetchPlaylist(url.c_str(), &unchanged);
505cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber        if (playlist == NULL) {
506cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber            if (unchanged) {
507cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber                // We succeeded in fetching the playlist, but it was
508cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber                // unchanged from the last time we tried.
509cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber            } else {
510cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber                LOGE("failed to load playlist at url '%s'", url.c_str());
511cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber                mDataSource->queueEOS(ERROR_IO);
512cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber                return;
513cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber            }
514cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber        } else {
515cc0b9f139fd0552baf942f60d965d280f7b5af89Andreas Huber            mPlaylist = playlist;
516c4f297d612a06a1f5eeac0adca03852d51c85f72Andreas Huber        }
517b5590846c035a28399818451201aaf1256913ec3Andreas Huber
518b5590846c035a28399818451201aaf1256913ec3Andreas Huber        if (firstTime) {
519b5590846c035a28399818451201aaf1256913ec3Andreas Huber            Mutex::Autolock autoLock(mLock);
520b5590846c035a28399818451201aaf1256913ec3Andreas Huber
521e9a418811957280bd4de1d16c77488fae2ff990fAndreas Huber            if (!mPlaylist->isComplete()) {
522b5590846c035a28399818451201aaf1256913ec3Andreas Huber                mDurationUs = -1;
523b5590846c035a28399818451201aaf1256913ec3Andreas Huber            } else {
524e9a418811957280bd4de1d16c77488fae2ff990fAndreas Huber                mDurationUs = 0;
525e9a418811957280bd4de1d16c77488fae2ff990fAndreas Huber                for (size_t i = 0; i < mPlaylist->size(); ++i) {
526e9a418811957280bd4de1d16c77488fae2ff990fAndreas Huber                    sp<AMessage> itemMeta;
527e9a418811957280bd4de1d16c77488fae2ff990fAndreas Huber                    CHECK(mPlaylist->itemAt(
528e9a418811957280bd4de1d16c77488fae2ff990fAndreas Huber                                i, NULL /* uri */, &itemMeta));
529e9a418811957280bd4de1d16c77488fae2ff990fAndreas Huber
530e9a418811957280bd4de1d16c77488fae2ff990fAndreas Huber                    int64_t itemDurationUs;
531e9a418811957280bd4de1d16c77488fae2ff990fAndreas Huber                    CHECK(itemMeta->findInt64("durationUs", &itemDurationUs));
532e9a418811957280bd4de1d16c77488fae2ff990fAndreas Huber
533e9a418811957280bd4de1d16c77488fae2ff990fAndreas Huber                    mDurationUs += itemDurationUs;
534e9a418811957280bd4de1d16c77488fae2ff990fAndreas Huber                }
535b5590846c035a28399818451201aaf1256913ec3Andreas Huber            }
536b5590846c035a28399818451201aaf1256913ec3Andreas Huber        }
537b5590846c035a28399818451201aaf1256913ec3Andreas Huber
538b5590846c035a28399818451201aaf1256913ec3Andreas Huber        mLastPlaylistFetchTimeUs = ALooper::GetNowUs();
539b5590846c035a28399818451201aaf1256913ec3Andreas Huber    }
540b5590846c035a28399818451201aaf1256913ec3Andreas Huber
541b5590846c035a28399818451201aaf1256913ec3Andreas Huber    int32_t firstSeqNumberInPlaylist;
542b5590846c035a28399818451201aaf1256913ec3Andreas Huber    if (mPlaylist->meta() == NULL || !mPlaylist->meta()->findInt32(
543b5590846c035a28399818451201aaf1256913ec3Andreas Huber                "media-sequence", &firstSeqNumberInPlaylist)) {
544b5590846c035a28399818451201aaf1256913ec3Andreas Huber        firstSeqNumberInPlaylist = 0;
545b5590846c035a28399818451201aaf1256913ec3Andreas Huber    }
546b5590846c035a28399818451201aaf1256913ec3Andreas Huber
54737e477c22730655ffb09485aeee18cff59f9edfbAndreas Huber    bool seekDiscontinuity = false;
548b5590846c035a28399818451201aaf1256913ec3Andreas Huber    bool explicitDiscontinuity = false;
549847551cff3fc824e898a2652e4c6a8dd1b049cb5Andreas Huber    bool bandwidthChanged = false;
550b5590846c035a28399818451201aaf1256913ec3Andreas Huber
551b5590846c035a28399818451201aaf1256913ec3Andreas Huber    if (mSeekTimeUs >= 0) {
552e9a418811957280bd4de1d16c77488fae2ff990fAndreas Huber        if (mPlaylist->isComplete()) {
553e9a418811957280bd4de1d16c77488fae2ff990fAndreas Huber            size_t index = 0;
554e9a418811957280bd4de1d16c77488fae2ff990fAndreas Huber            int64_t segmentStartUs = 0;
555e9a418811957280bd4de1d16c77488fae2ff990fAndreas Huber            while (index < mPlaylist->size()) {
556e9a418811957280bd4de1d16c77488fae2ff990fAndreas Huber                sp<AMessage> itemMeta;
557e9a418811957280bd4de1d16c77488fae2ff990fAndreas Huber                CHECK(mPlaylist->itemAt(
558e9a418811957280bd4de1d16c77488fae2ff990fAndreas Huber                            index, NULL /* uri */, &itemMeta));
559e9a418811957280bd4de1d16c77488fae2ff990fAndreas Huber
560e9a418811957280bd4de1d16c77488fae2ff990fAndreas Huber                int64_t itemDurationUs;
561e9a418811957280bd4de1d16c77488fae2ff990fAndreas Huber                CHECK(itemMeta->findInt64("durationUs", &itemDurationUs));
562e9a418811957280bd4de1d16c77488fae2ff990fAndreas Huber
563e9a418811957280bd4de1d16c77488fae2ff990fAndreas Huber                if (mSeekTimeUs < segmentStartUs + itemDurationUs) {
564e9a418811957280bd4de1d16c77488fae2ff990fAndreas Huber                    break;
565e9a418811957280bd4de1d16c77488fae2ff990fAndreas Huber                }
566e9a418811957280bd4de1d16c77488fae2ff990fAndreas Huber
567e9a418811957280bd4de1d16c77488fae2ff990fAndreas Huber                segmentStartUs += itemDurationUs;
568e9a418811957280bd4de1d16c77488fae2ff990fAndreas Huber                ++index;
569e9a418811957280bd4de1d16c77488fae2ff990fAndreas Huber            }
570e9a418811957280bd4de1d16c77488fae2ff990fAndreas Huber
571e9a418811957280bd4de1d16c77488fae2ff990fAndreas Huber            if (index < mPlaylist->size()) {
57208e10cb404c0f1620ca9db7494ccbb8adcca5ee5Andreas Huber                int32_t newSeqNumber = firstSeqNumberInPlaylist + index;
573b5590846c035a28399818451201aaf1256913ec3Andreas Huber
57408e10cb404c0f1620ca9db7494ccbb8adcca5ee5Andreas Huber                if (newSeqNumber != mSeqNumber) {
57508e10cb404c0f1620ca9db7494ccbb8adcca5ee5Andreas Huber                    LOGI("seeking to seq no %d", newSeqNumber);
57608e10cb404c0f1620ca9db7494ccbb8adcca5ee5Andreas Huber
57708e10cb404c0f1620ca9db7494ccbb8adcca5ee5Andreas Huber                    mSeqNumber = newSeqNumber;
57808e10cb404c0f1620ca9db7494ccbb8adcca5ee5Andreas Huber
57908e10cb404c0f1620ca9db7494ccbb8adcca5ee5Andreas Huber                    mDataSource->reset();
58008e10cb404c0f1620ca9db7494ccbb8adcca5ee5Andreas Huber
581847551cff3fc824e898a2652e4c6a8dd1b049cb5Andreas Huber                    // reseting the data source will have had the
582847551cff3fc824e898a2652e4c6a8dd1b049cb5Andreas Huber                    // side effect of discarding any previously queued
583847551cff3fc824e898a2652e4c6a8dd1b049cb5Andreas Huber                    // bandwidth change discontinuity.
58437e477c22730655ffb09485aeee18cff59f9edfbAndreas Huber                    // Therefore we'll need to treat these seek
585847551cff3fc824e898a2652e4c6a8dd1b049cb5Andreas Huber                    // discontinuities as involving a bandwidth change
586847551cff3fc824e898a2652e4c6a8dd1b049cb5Andreas Huber                    // even if they aren't directly.
58737e477c22730655ffb09485aeee18cff59f9edfbAndreas Huber                    seekDiscontinuity = true;
588847551cff3fc824e898a2652e4c6a8dd1b049cb5Andreas Huber                    bandwidthChanged = true;
58908e10cb404c0f1620ca9db7494ccbb8adcca5ee5Andreas Huber                }
590b5590846c035a28399818451201aaf1256913ec3Andreas Huber            }
591b5590846c035a28399818451201aaf1256913ec3Andreas Huber        }
592b5590846c035a28399818451201aaf1256913ec3Andreas Huber
593b5590846c035a28399818451201aaf1256913ec3Andreas Huber        mSeekTimeUs = -1;
594b5590846c035a28399818451201aaf1256913ec3Andreas Huber
595b5590846c035a28399818451201aaf1256913ec3Andreas Huber        Mutex::Autolock autoLock(mLock);
596b5590846c035a28399818451201aaf1256913ec3Andreas Huber        mSeekDone = true;
597b5590846c035a28399818451201aaf1256913ec3Andreas Huber        mCondition.broadcast();
598b5590846c035a28399818451201aaf1256913ec3Andreas Huber    }
599b5590846c035a28399818451201aaf1256913ec3Andreas Huber
600b5590846c035a28399818451201aaf1256913ec3Andreas Huber    if (mSeqNumber < 0) {
60137e477c22730655ffb09485aeee18cff59f9edfbAndreas Huber        mSeqNumber = firstSeqNumberInPlaylist;
602b5590846c035a28399818451201aaf1256913ec3Andreas Huber    }
603b5590846c035a28399818451201aaf1256913ec3Andreas Huber
604b5590846c035a28399818451201aaf1256913ec3Andreas Huber    int32_t lastSeqNumberInPlaylist =
605b5590846c035a28399818451201aaf1256913ec3Andreas Huber        firstSeqNumberInPlaylist + (int32_t)mPlaylist->size() - 1;
606b5590846c035a28399818451201aaf1256913ec3Andreas Huber
607b5590846c035a28399818451201aaf1256913ec3Andreas Huber    if (mSeqNumber < firstSeqNumberInPlaylist
608b5590846c035a28399818451201aaf1256913ec3Andreas Huber            || mSeqNumber > lastSeqNumberInPlaylist) {
609283e031d112f5897c4a4124307ff4e4055bf666dAndreas Huber        if (mPrevBandwidthIndex != (ssize_t)bandwidthIndex) {
610ba572aaea62ba5d220891ff58642ccee3ad20decAndreas Huber            // Go back to the previous bandwidth.
611ba572aaea62ba5d220891ff58642ccee3ad20decAndreas Huber
612ba572aaea62ba5d220891ff58642ccee3ad20decAndreas Huber            LOGI("new bandwidth does not have the sequence number "
613ba572aaea62ba5d220891ff58642ccee3ad20decAndreas Huber                 "we're looking for, switching back to previous bandwidth");
614ba572aaea62ba5d220891ff58642ccee3ad20decAndreas Huber
615ba572aaea62ba5d220891ff58642ccee3ad20decAndreas Huber            mLastPlaylistFetchTimeUs = -1;
616ba572aaea62ba5d220891ff58642ccee3ad20decAndreas Huber            bandwidthIndex = mPrevBandwidthIndex;
617ba572aaea62ba5d220891ff58642ccee3ad20decAndreas Huber            goto rinse_repeat;
618ba572aaea62ba5d220891ff58642ccee3ad20decAndreas Huber        }
619ba572aaea62ba5d220891ff58642ccee3ad20decAndreas Huber
620323e31754c3ba31e537e712e818f90381b8eb6d1Andreas Huber        if (!mPlaylist->isComplete() && mNumRetries < kMaxNumRetries) {
621b5590846c035a28399818451201aaf1256913ec3Andreas Huber            ++mNumRetries;
622b5590846c035a28399818451201aaf1256913ec3Andreas Huber
623323e31754c3ba31e537e712e818f90381b8eb6d1Andreas Huber            if (mSeqNumber > lastSeqNumberInPlaylist) {
624323e31754c3ba31e537e712e818f90381b8eb6d1Andreas Huber                mLastPlaylistFetchTimeUs = -1;
625323e31754c3ba31e537e712e818f90381b8eb6d1Andreas Huber                postMonitorQueue(3000000ll);
626323e31754c3ba31e537e712e818f90381b8eb6d1Andreas Huber                return;
627323e31754c3ba31e537e712e818f90381b8eb6d1Andreas Huber            }
628b5590846c035a28399818451201aaf1256913ec3Andreas Huber
629323e31754c3ba31e537e712e818f90381b8eb6d1Andreas Huber            // we've missed the boat, let's start from the lowest sequence
630323e31754c3ba31e537e712e818f90381b8eb6d1Andreas Huber            // number available and signal a discontinuity.
631b5590846c035a28399818451201aaf1256913ec3Andreas Huber
632323e31754c3ba31e537e712e818f90381b8eb6d1Andreas Huber            LOGI("We've missed the boat, restarting playback.");
633323e31754c3ba31e537e712e818f90381b8eb6d1Andreas Huber            mSeqNumber = lastSeqNumberInPlaylist;
634323e31754c3ba31e537e712e818f90381b8eb6d1Andreas Huber            explicitDiscontinuity = true;
635323e31754c3ba31e537e712e818f90381b8eb6d1Andreas Huber
636323e31754c3ba31e537e712e818f90381b8eb6d1Andreas Huber            // fall through
637323e31754c3ba31e537e712e818f90381b8eb6d1Andreas Huber        } else {
638323e31754c3ba31e537e712e818f90381b8eb6d1Andreas Huber            LOGE("Cannot find sequence number %d in playlist "
639323e31754c3ba31e537e712e818f90381b8eb6d1Andreas Huber                 "(contains %d - %d)",
640323e31754c3ba31e537e712e818f90381b8eb6d1Andreas Huber                 mSeqNumber, firstSeqNumberInPlaylist,
641323e31754c3ba31e537e712e818f90381b8eb6d1Andreas Huber                 firstSeqNumberInPlaylist + mPlaylist->size() - 1);
642323e31754c3ba31e537e712e818f90381b8eb6d1Andreas Huber
643323e31754c3ba31e537e712e818f90381b8eb6d1Andreas Huber            mDataSource->queueEOS(ERROR_END_OF_STREAM);
644323e31754c3ba31e537e712e818f90381b8eb6d1Andreas Huber            return;
645323e31754c3ba31e537e712e818f90381b8eb6d1Andreas Huber        }
646b5590846c035a28399818451201aaf1256913ec3Andreas Huber    }
647b5590846c035a28399818451201aaf1256913ec3Andreas Huber
648b5590846c035a28399818451201aaf1256913ec3Andreas Huber    mNumRetries = 0;
649b5590846c035a28399818451201aaf1256913ec3Andreas Huber
650b5590846c035a28399818451201aaf1256913ec3Andreas Huber    AString uri;
651b5590846c035a28399818451201aaf1256913ec3Andreas Huber    sp<AMessage> itemMeta;
652b5590846c035a28399818451201aaf1256913ec3Andreas Huber    CHECK(mPlaylist->itemAt(
653b5590846c035a28399818451201aaf1256913ec3Andreas Huber                mSeqNumber - firstSeqNumberInPlaylist,
654b5590846c035a28399818451201aaf1256913ec3Andreas Huber                &uri,
655b5590846c035a28399818451201aaf1256913ec3Andreas Huber                &itemMeta));
656b5590846c035a28399818451201aaf1256913ec3Andreas Huber
657b5590846c035a28399818451201aaf1256913ec3Andreas Huber    int32_t val;
658b5590846c035a28399818451201aaf1256913ec3Andreas Huber    if (itemMeta->findInt32("discontinuity", &val) && val != 0) {
659b5590846c035a28399818451201aaf1256913ec3Andreas Huber        explicitDiscontinuity = true;
660b5590846c035a28399818451201aaf1256913ec3Andreas Huber    }
661b5590846c035a28399818451201aaf1256913ec3Andreas Huber
662b5590846c035a28399818451201aaf1256913ec3Andreas Huber    sp<ABuffer> buffer;
663b5590846c035a28399818451201aaf1256913ec3Andreas Huber    status_t err = fetchFile(uri.c_str(), &buffer);
664c4f297d612a06a1f5eeac0adca03852d51c85f72Andreas Huber    if (err != OK) {
665c4f297d612a06a1f5eeac0adca03852d51c85f72Andreas Huber        LOGE("failed to fetch .ts segment at url '%s'", uri.c_str());
666c4f297d612a06a1f5eeac0adca03852d51c85f72Andreas Huber        mDataSource->queueEOS(err);
667c4f297d612a06a1f5eeac0adca03852d51c85f72Andreas Huber        return;
668c4f297d612a06a1f5eeac0adca03852d51c85f72Andreas Huber    }
669b5590846c035a28399818451201aaf1256913ec3Andreas Huber
67008e10cb404c0f1620ca9db7494ccbb8adcca5ee5Andreas Huber    CHECK(buffer != NULL);
67108e10cb404c0f1620ca9db7494ccbb8adcca5ee5Andreas Huber
6720cf2616faca9110a761f9d85c7e6cc5c1a5c689fAndreas Huber    err = decryptBuffer(mSeqNumber - firstSeqNumberInPlaylist, buffer);
6730cf2616faca9110a761f9d85c7e6cc5c1a5c689fAndreas Huber
6740cf2616faca9110a761f9d85c7e6cc5c1a5c689fAndreas Huber    if (err != OK) {
6750cf2616faca9110a761f9d85c7e6cc5c1a5c689fAndreas Huber        LOGE("decryptBuffer failed w/ error %d", err);
6760cf2616faca9110a761f9d85c7e6cc5c1a5c689fAndreas Huber
6770cf2616faca9110a761f9d85c7e6cc5c1a5c689fAndreas Huber        mDataSource->queueEOS(err);
6780cf2616faca9110a761f9d85c7e6cc5c1a5c689fAndreas Huber        return;
6790cf2616faca9110a761f9d85c7e6cc5c1a5c689fAndreas Huber    }
680b5590846c035a28399818451201aaf1256913ec3Andreas Huber
681b5590846c035a28399818451201aaf1256913ec3Andreas Huber    if (buffer->size() == 0 || buffer->data()[0] != 0x47) {
682b5590846c035a28399818451201aaf1256913ec3Andreas Huber        // Not a transport stream???
683b5590846c035a28399818451201aaf1256913ec3Andreas Huber
684b5590846c035a28399818451201aaf1256913ec3Andreas Huber        LOGE("This doesn't look like a transport stream...");
685b5590846c035a28399818451201aaf1256913ec3Andreas Huber
68619922adceb29a3192a63e35a07fb02412aa2a4a2Andreas Huber        mBandwidthItems.removeAt(bandwidthIndex);
68719922adceb29a3192a63e35a07fb02412aa2a4a2Andreas Huber
68819922adceb29a3192a63e35a07fb02412aa2a4a2Andreas Huber        if (mBandwidthItems.isEmpty()) {
68919922adceb29a3192a63e35a07fb02412aa2a4a2Andreas Huber            mDataSource->queueEOS(ERROR_UNSUPPORTED);
69019922adceb29a3192a63e35a07fb02412aa2a4a2Andreas Huber            return;
69119922adceb29a3192a63e35a07fb02412aa2a4a2Andreas Huber        }
69219922adceb29a3192a63e35a07fb02412aa2a4a2Andreas Huber
69319922adceb29a3192a63e35a07fb02412aa2a4a2Andreas Huber        LOGI("Retrying with a different bandwidth stream.");
69419922adceb29a3192a63e35a07fb02412aa2a4a2Andreas Huber
69519922adceb29a3192a63e35a07fb02412aa2a4a2Andreas Huber        mLastPlaylistFetchTimeUs = -1;
69619922adceb29a3192a63e35a07fb02412aa2a4a2Andreas Huber        bandwidthIndex = getBandwidthIndex();
69719922adceb29a3192a63e35a07fb02412aa2a4a2Andreas Huber        mPrevBandwidthIndex = bandwidthIndex;
69819922adceb29a3192a63e35a07fb02412aa2a4a2Andreas Huber        mSeqNumber = -1;
69919922adceb29a3192a63e35a07fb02412aa2a4a2Andreas Huber
70019922adceb29a3192a63e35a07fb02412aa2a4a2Andreas Huber        goto rinse_repeat;
701b5590846c035a28399818451201aaf1256913ec3Andreas Huber    }
702b5590846c035a28399818451201aaf1256913ec3Andreas Huber
703847551cff3fc824e898a2652e4c6a8dd1b049cb5Andreas Huber    if ((size_t)mPrevBandwidthIndex != bandwidthIndex) {
704847551cff3fc824e898a2652e4c6a8dd1b049cb5Andreas Huber        bandwidthChanged = true;
705847551cff3fc824e898a2652e4c6a8dd1b049cb5Andreas Huber    }
706847551cff3fc824e898a2652e4c6a8dd1b049cb5Andreas Huber
707847551cff3fc824e898a2652e4c6a8dd1b049cb5Andreas Huber    if (mPrevBandwidthIndex < 0) {
708847551cff3fc824e898a2652e4c6a8dd1b049cb5Andreas Huber        // Don't signal a bandwidth change at the very beginning of
709847551cff3fc824e898a2652e4c6a8dd1b049cb5Andreas Huber        // playback.
710847551cff3fc824e898a2652e4c6a8dd1b049cb5Andreas Huber        bandwidthChanged = false;
711847551cff3fc824e898a2652e4c6a8dd1b049cb5Andreas Huber    }
71241c3f740485a069bf101d5a1e5263880ca1035efAndreas Huber
71337e477c22730655ffb09485aeee18cff59f9edfbAndreas Huber    if (seekDiscontinuity || explicitDiscontinuity || bandwidthChanged) {
714b5590846c035a28399818451201aaf1256913ec3Andreas Huber        // Signal discontinuity.
715b5590846c035a28399818451201aaf1256913ec3Andreas Huber
71637e477c22730655ffb09485aeee18cff59f9edfbAndreas Huber        LOGI("queueing discontinuity (seek=%d, explicit=%d, bandwidthChanged=%d)",
71737e477c22730655ffb09485aeee18cff59f9edfbAndreas Huber             seekDiscontinuity, explicitDiscontinuity, bandwidthChanged);
71808e10cb404c0f1620ca9db7494ccbb8adcca5ee5Andreas Huber
719b5590846c035a28399818451201aaf1256913ec3Andreas Huber        sp<ABuffer> tmp = new ABuffer(188);
720b5590846c035a28399818451201aaf1256913ec3Andreas Huber        memset(tmp->data(), 0, tmp->size());
72137e477c22730655ffb09485aeee18cff59f9edfbAndreas Huber
72237e477c22730655ffb09485aeee18cff59f9edfbAndreas Huber        // signal a 'hard' discontinuity for explicit or bandwidthChanged.
72337e477c22730655ffb09485aeee18cff59f9edfbAndreas Huber        tmp->data()[1] = (explicitDiscontinuity || bandwidthChanged) ? 1 : 0;
724b5590846c035a28399818451201aaf1256913ec3Andreas Huber
725b5590846c035a28399818451201aaf1256913ec3Andreas Huber        mDataSource->queueBuffer(tmp);
726b5590846c035a28399818451201aaf1256913ec3Andreas Huber    }
727b5590846c035a28399818451201aaf1256913ec3Andreas Huber
728b5590846c035a28399818451201aaf1256913ec3Andreas Huber    mDataSource->queueBuffer(buffer);
729b5590846c035a28399818451201aaf1256913ec3Andreas Huber
730b5590846c035a28399818451201aaf1256913ec3Andreas Huber    mPrevBandwidthIndex = bandwidthIndex;
731b5590846c035a28399818451201aaf1256913ec3Andreas Huber    ++mSeqNumber;
732b5590846c035a28399818451201aaf1256913ec3Andreas Huber
733b5590846c035a28399818451201aaf1256913ec3Andreas Huber    postMonitorQueue();
734b5590846c035a28399818451201aaf1256913ec3Andreas Huber}
735b5590846c035a28399818451201aaf1256913ec3Andreas Huber
736b5590846c035a28399818451201aaf1256913ec3Andreas Hubervoid LiveSession::onMonitorQueue() {
737b5590846c035a28399818451201aaf1256913ec3Andreas Huber    if (mSeekTimeUs >= 0
738b5590846c035a28399818451201aaf1256913ec3Andreas Huber            || mDataSource->countQueuedBuffers() < kMaxNumQueuedFragments) {
739b5590846c035a28399818451201aaf1256913ec3Andreas Huber        onDownloadNext();
740b5590846c035a28399818451201aaf1256913ec3Andreas Huber    } else {
741b5590846c035a28399818451201aaf1256913ec3Andreas Huber        postMonitorQueue(1000000ll);
742b5590846c035a28399818451201aaf1256913ec3Andreas Huber    }
743b5590846c035a28399818451201aaf1256913ec3Andreas Huber}
744b5590846c035a28399818451201aaf1256913ec3Andreas Huber
745b5590846c035a28399818451201aaf1256913ec3Andreas Huberstatus_t LiveSession::decryptBuffer(
746b5590846c035a28399818451201aaf1256913ec3Andreas Huber        size_t playlistIndex, const sp<ABuffer> &buffer) {
747b5590846c035a28399818451201aaf1256913ec3Andreas Huber    sp<AMessage> itemMeta;
748b5590846c035a28399818451201aaf1256913ec3Andreas Huber    bool found = false;
749b5590846c035a28399818451201aaf1256913ec3Andreas Huber    AString method;
750b5590846c035a28399818451201aaf1256913ec3Andreas Huber
751b5590846c035a28399818451201aaf1256913ec3Andreas Huber    for (ssize_t i = playlistIndex; i >= 0; --i) {
752b5590846c035a28399818451201aaf1256913ec3Andreas Huber        AString uri;
753b5590846c035a28399818451201aaf1256913ec3Andreas Huber        CHECK(mPlaylist->itemAt(i, &uri, &itemMeta));
754b5590846c035a28399818451201aaf1256913ec3Andreas Huber
755b5590846c035a28399818451201aaf1256913ec3Andreas Huber        if (itemMeta->findString("cipher-method", &method)) {
756b5590846c035a28399818451201aaf1256913ec3Andreas Huber            found = true;
757b5590846c035a28399818451201aaf1256913ec3Andreas Huber            break;
758b5590846c035a28399818451201aaf1256913ec3Andreas Huber        }
759b5590846c035a28399818451201aaf1256913ec3Andreas Huber    }
760b5590846c035a28399818451201aaf1256913ec3Andreas Huber
761b5590846c035a28399818451201aaf1256913ec3Andreas Huber    if (!found) {
762b5590846c035a28399818451201aaf1256913ec3Andreas Huber        method = "NONE";
763b5590846c035a28399818451201aaf1256913ec3Andreas Huber    }
764b5590846c035a28399818451201aaf1256913ec3Andreas Huber
765b5590846c035a28399818451201aaf1256913ec3Andreas Huber    if (method == "NONE") {
766b5590846c035a28399818451201aaf1256913ec3Andreas Huber        return OK;
767b5590846c035a28399818451201aaf1256913ec3Andreas Huber    } else if (!(method == "AES-128")) {
768b5590846c035a28399818451201aaf1256913ec3Andreas Huber        LOGE("Unsupported cipher method '%s'", method.c_str());
769b5590846c035a28399818451201aaf1256913ec3Andreas Huber        return ERROR_UNSUPPORTED;
770b5590846c035a28399818451201aaf1256913ec3Andreas Huber    }
771b5590846c035a28399818451201aaf1256913ec3Andreas Huber
772b5590846c035a28399818451201aaf1256913ec3Andreas Huber    AString keyURI;
773b5590846c035a28399818451201aaf1256913ec3Andreas Huber    if (!itemMeta->findString("cipher-uri", &keyURI)) {
774b5590846c035a28399818451201aaf1256913ec3Andreas Huber        LOGE("Missing key uri");
775b5590846c035a28399818451201aaf1256913ec3Andreas Huber        return ERROR_MALFORMED;
776b5590846c035a28399818451201aaf1256913ec3Andreas Huber    }
777b5590846c035a28399818451201aaf1256913ec3Andreas Huber
778b5590846c035a28399818451201aaf1256913ec3Andreas Huber    ssize_t index = mAESKeyForURI.indexOfKey(keyURI);
779b5590846c035a28399818451201aaf1256913ec3Andreas Huber
780b5590846c035a28399818451201aaf1256913ec3Andreas Huber    sp<ABuffer> key;
781b5590846c035a28399818451201aaf1256913ec3Andreas Huber    if (index >= 0) {
782b5590846c035a28399818451201aaf1256913ec3Andreas Huber        key = mAESKeyForURI.valueAt(index);
783b5590846c035a28399818451201aaf1256913ec3Andreas Huber    } else {
784b5590846c035a28399818451201aaf1256913ec3Andreas Huber        key = new ABuffer(16);
785b5590846c035a28399818451201aaf1256913ec3Andreas Huber
7865f5719e45b3c4e3237a45b019e0fcd86060974a8Andreas Huber        sp<HTTPBase> keySource =
7875f5719e45b3c4e3237a45b019e0fcd86060974a8Andreas Huber              HTTPBase::Create(
7885f5719e45b3c4e3237a45b019e0fcd86060974a8Andreas Huber                  (mFlags & kFlagIncognito)
7895f5719e45b3c4e3237a45b019e0fcd86060974a8Andreas Huber                    ? HTTPBase::kFlagIncognito
7905f5719e45b3c4e3237a45b019e0fcd86060974a8Andreas Huber                    : 0);
7915f5719e45b3c4e3237a45b019e0fcd86060974a8Andreas Huber
792603d739b5a444c52b63f1ec7cd2098034151ad25Andreas Huber        if (mUIDValid) {
793603d739b5a444c52b63f1ec7cd2098034151ad25Andreas Huber            keySource->setUID(mUID);
794603d739b5a444c52b63f1ec7cd2098034151ad25Andreas Huber        }
795603d739b5a444c52b63f1ec7cd2098034151ad25Andreas Huber
7969073725c1b53eaa1930d28a4bffea8076ed2d314Andreas Huber        status_t err =
7979073725c1b53eaa1930d28a4bffea8076ed2d314Andreas Huber            keySource->connect(
7989073725c1b53eaa1930d28a4bffea8076ed2d314Andreas Huber                    keyURI.c_str(),
7999073725c1b53eaa1930d28a4bffea8076ed2d314Andreas Huber                    mExtraHeaders.isEmpty() ? NULL : &mExtraHeaders);
800b5590846c035a28399818451201aaf1256913ec3Andreas Huber
801b5590846c035a28399818451201aaf1256913ec3Andreas Huber        if (err == OK) {
802b5590846c035a28399818451201aaf1256913ec3Andreas Huber            size_t offset = 0;
803b5590846c035a28399818451201aaf1256913ec3Andreas Huber            while (offset < 16) {
804b5590846c035a28399818451201aaf1256913ec3Andreas Huber                ssize_t n = keySource->readAt(
805b5590846c035a28399818451201aaf1256913ec3Andreas Huber                        offset, key->data() + offset, 16 - offset);
806b5590846c035a28399818451201aaf1256913ec3Andreas Huber                if (n <= 0) {
807b5590846c035a28399818451201aaf1256913ec3Andreas Huber                    err = ERROR_IO;
808b5590846c035a28399818451201aaf1256913ec3Andreas Huber                    break;
809b5590846c035a28399818451201aaf1256913ec3Andreas Huber                }
810b5590846c035a28399818451201aaf1256913ec3Andreas Huber
811b5590846c035a28399818451201aaf1256913ec3Andreas Huber                offset += n;
812b5590846c035a28399818451201aaf1256913ec3Andreas Huber            }
813b5590846c035a28399818451201aaf1256913ec3Andreas Huber        }
814b5590846c035a28399818451201aaf1256913ec3Andreas Huber
815b5590846c035a28399818451201aaf1256913ec3Andreas Huber        if (err != OK) {
816b5590846c035a28399818451201aaf1256913ec3Andreas Huber            LOGE("failed to fetch cipher key from '%s'.", keyURI.c_str());
817b5590846c035a28399818451201aaf1256913ec3Andreas Huber            return ERROR_IO;
818b5590846c035a28399818451201aaf1256913ec3Andreas Huber        }
819b5590846c035a28399818451201aaf1256913ec3Andreas Huber
820b5590846c035a28399818451201aaf1256913ec3Andreas Huber        mAESKeyForURI.add(keyURI, key);
821b5590846c035a28399818451201aaf1256913ec3Andreas Huber    }
822b5590846c035a28399818451201aaf1256913ec3Andreas Huber
823b5590846c035a28399818451201aaf1256913ec3Andreas Huber    AES_KEY aes_key;
824b5590846c035a28399818451201aaf1256913ec3Andreas Huber    if (AES_set_decrypt_key(key->data(), 128, &aes_key) != 0) {
825b5590846c035a28399818451201aaf1256913ec3Andreas Huber        LOGE("failed to set AES decryption key.");
826b5590846c035a28399818451201aaf1256913ec3Andreas Huber        return UNKNOWN_ERROR;
827b5590846c035a28399818451201aaf1256913ec3Andreas Huber    }
828b5590846c035a28399818451201aaf1256913ec3Andreas Huber
829b5590846c035a28399818451201aaf1256913ec3Andreas Huber    unsigned char aes_ivec[16];
830b5590846c035a28399818451201aaf1256913ec3Andreas Huber
831b5590846c035a28399818451201aaf1256913ec3Andreas Huber    AString iv;
832b5590846c035a28399818451201aaf1256913ec3Andreas Huber    if (itemMeta->findString("cipher-iv", &iv)) {
833b5590846c035a28399818451201aaf1256913ec3Andreas Huber        if ((!iv.startsWith("0x") && !iv.startsWith("0X"))
834b5590846c035a28399818451201aaf1256913ec3Andreas Huber                || iv.size() != 16 * 2 + 2) {
835b5590846c035a28399818451201aaf1256913ec3Andreas Huber            LOGE("malformed cipher IV '%s'.", iv.c_str());
836b5590846c035a28399818451201aaf1256913ec3Andreas Huber            return ERROR_MALFORMED;
837b5590846c035a28399818451201aaf1256913ec3Andreas Huber        }
838b5590846c035a28399818451201aaf1256913ec3Andreas Huber
839b5590846c035a28399818451201aaf1256913ec3Andreas Huber        memset(aes_ivec, 0, sizeof(aes_ivec));
840b5590846c035a28399818451201aaf1256913ec3Andreas Huber        for (size_t i = 0; i < 16; ++i) {
841b5590846c035a28399818451201aaf1256913ec3Andreas Huber            char c1 = tolower(iv.c_str()[2 + 2 * i]);
842b5590846c035a28399818451201aaf1256913ec3Andreas Huber            char c2 = tolower(iv.c_str()[3 + 2 * i]);
843b5590846c035a28399818451201aaf1256913ec3Andreas Huber            if (!isxdigit(c1) || !isxdigit(c2)) {
844b5590846c035a28399818451201aaf1256913ec3Andreas Huber                LOGE("malformed cipher IV '%s'.", iv.c_str());
845b5590846c035a28399818451201aaf1256913ec3Andreas Huber                return ERROR_MALFORMED;
846b5590846c035a28399818451201aaf1256913ec3Andreas Huber            }
847b5590846c035a28399818451201aaf1256913ec3Andreas Huber            uint8_t nibble1 = isdigit(c1) ? c1 - '0' : c1 - 'a' + 10;
848b5590846c035a28399818451201aaf1256913ec3Andreas Huber            uint8_t nibble2 = isdigit(c2) ? c2 - '0' : c2 - 'a' + 10;
849b5590846c035a28399818451201aaf1256913ec3Andreas Huber
850b5590846c035a28399818451201aaf1256913ec3Andreas Huber            aes_ivec[i] = nibble1 << 4 | nibble2;
851b5590846c035a28399818451201aaf1256913ec3Andreas Huber        }
852b5590846c035a28399818451201aaf1256913ec3Andreas Huber    } else {
853b5590846c035a28399818451201aaf1256913ec3Andreas Huber        memset(aes_ivec, 0, sizeof(aes_ivec));
854b5590846c035a28399818451201aaf1256913ec3Andreas Huber        aes_ivec[15] = mSeqNumber & 0xff;
855b5590846c035a28399818451201aaf1256913ec3Andreas Huber        aes_ivec[14] = (mSeqNumber >> 8) & 0xff;
856b5590846c035a28399818451201aaf1256913ec3Andreas Huber        aes_ivec[13] = (mSeqNumber >> 16) & 0xff;
857b5590846c035a28399818451201aaf1256913ec3Andreas Huber        aes_ivec[12] = (mSeqNumber >> 24) & 0xff;
858b5590846c035a28399818451201aaf1256913ec3Andreas Huber    }
859b5590846c035a28399818451201aaf1256913ec3Andreas Huber
860b5590846c035a28399818451201aaf1256913ec3Andreas Huber    AES_cbc_encrypt(
861b5590846c035a28399818451201aaf1256913ec3Andreas Huber            buffer->data(), buffer->data(), buffer->size(),
862b5590846c035a28399818451201aaf1256913ec3Andreas Huber            &aes_key, aes_ivec, AES_DECRYPT);
863b5590846c035a28399818451201aaf1256913ec3Andreas Huber
864b5590846c035a28399818451201aaf1256913ec3Andreas Huber    // hexdump(buffer->data(), buffer->size());
865b5590846c035a28399818451201aaf1256913ec3Andreas Huber
866b5590846c035a28399818451201aaf1256913ec3Andreas Huber    size_t n = buffer->size();
867b5590846c035a28399818451201aaf1256913ec3Andreas Huber    CHECK_GT(n, 0u);
868b5590846c035a28399818451201aaf1256913ec3Andreas Huber
869b5590846c035a28399818451201aaf1256913ec3Andreas Huber    size_t pad = buffer->data()[n - 1];
870b5590846c035a28399818451201aaf1256913ec3Andreas Huber
871b5590846c035a28399818451201aaf1256913ec3Andreas Huber    CHECK_GT(pad, 0u);
872b5590846c035a28399818451201aaf1256913ec3Andreas Huber    CHECK_LE(pad, 16u);
873b5590846c035a28399818451201aaf1256913ec3Andreas Huber    CHECK_GE((size_t)n, pad);
874b5590846c035a28399818451201aaf1256913ec3Andreas Huber    for (size_t i = 0; i < pad; ++i) {
875b5590846c035a28399818451201aaf1256913ec3Andreas Huber        CHECK_EQ((unsigned)buffer->data()[n - 1 - i], pad);
876b5590846c035a28399818451201aaf1256913ec3Andreas Huber    }
877b5590846c035a28399818451201aaf1256913ec3Andreas Huber
878b5590846c035a28399818451201aaf1256913ec3Andreas Huber    n -= pad;
879b5590846c035a28399818451201aaf1256913ec3Andreas Huber
880b5590846c035a28399818451201aaf1256913ec3Andreas Huber    buffer->setRange(buffer->offset(), n);
881b5590846c035a28399818451201aaf1256913ec3Andreas Huber
882b5590846c035a28399818451201aaf1256913ec3Andreas Huber    return OK;
883b5590846c035a28399818451201aaf1256913ec3Andreas Huber}
884b5590846c035a28399818451201aaf1256913ec3Andreas Huber
885b5590846c035a28399818451201aaf1256913ec3Andreas Hubervoid LiveSession::postMonitorQueue(int64_t delayUs) {
886b5590846c035a28399818451201aaf1256913ec3Andreas Huber    sp<AMessage> msg = new AMessage(kWhatMonitorQueue, id());
887b5590846c035a28399818451201aaf1256913ec3Andreas Huber    msg->setInt32("generation", ++mMonitorQueueGeneration);
888b5590846c035a28399818451201aaf1256913ec3Andreas Huber    msg->post(delayUs);
889b5590846c035a28399818451201aaf1256913ec3Andreas Huber}
890b5590846c035a28399818451201aaf1256913ec3Andreas Huber
891b5590846c035a28399818451201aaf1256913ec3Andreas Hubervoid LiveSession::onSeek(const sp<AMessage> &msg) {
892b5590846c035a28399818451201aaf1256913ec3Andreas Huber    int64_t timeUs;
893b5590846c035a28399818451201aaf1256913ec3Andreas Huber    CHECK(msg->findInt64("timeUs", &timeUs));
894b5590846c035a28399818451201aaf1256913ec3Andreas Huber
895b5590846c035a28399818451201aaf1256913ec3Andreas Huber    mSeekTimeUs = timeUs;
896b5590846c035a28399818451201aaf1256913ec3Andreas Huber    postMonitorQueue();
897b5590846c035a28399818451201aaf1256913ec3Andreas Huber}
898b5590846c035a28399818451201aaf1256913ec3Andreas Huber
899b5590846c035a28399818451201aaf1256913ec3Andreas Huberstatus_t LiveSession::getDuration(int64_t *durationUs) {
900b5590846c035a28399818451201aaf1256913ec3Andreas Huber    Mutex::Autolock autoLock(mLock);
901b5590846c035a28399818451201aaf1256913ec3Andreas Huber    *durationUs = mDurationUs;
902b5590846c035a28399818451201aaf1256913ec3Andreas Huber
903b5590846c035a28399818451201aaf1256913ec3Andreas Huber    return OK;
904b5590846c035a28399818451201aaf1256913ec3Andreas Huber}
905b5590846c035a28399818451201aaf1256913ec3Andreas Huber
906b5590846c035a28399818451201aaf1256913ec3Andreas Huberbool LiveSession::isSeekable() {
907b5590846c035a28399818451201aaf1256913ec3Andreas Huber    int64_t durationUs;
908b5590846c035a28399818451201aaf1256913ec3Andreas Huber    return getDuration(&durationUs) == OK && durationUs >= 0;
909b5590846c035a28399818451201aaf1256913ec3Andreas Huber}
910b5590846c035a28399818451201aaf1256913ec3Andreas Huber
911b5590846c035a28399818451201aaf1256913ec3Andreas Huber}  // namespace android
912b5590846c035a28399818451201aaf1256913ec3Andreas Huber
913