LiveSession.cpp revision ad0d9c9c39a24b7fbd94e935a5855c9025341929
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>
39a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
40a44153c1a57202fb538659eb50706e60454d6273Andreas Hubernamespace android {
41a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
42a44153c1a57202fb538659eb50706e60454d6273Andreas Huberconst int64_t LiveSession::kMaxPlaylistAgeUs = 15000000ll;
43a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
447314fa17093d514199fedcb55ac41136a1b31cb3Andreas HuberLiveSession::LiveSession(uint32_t flags)
457314fa17093d514199fedcb55ac41136a1b31cb3Andreas Huber    : mFlags(flags),
467314fa17093d514199fedcb55ac41136a1b31cb3Andreas Huber      mDataSource(new LiveDataSource),
477314fa17093d514199fedcb55ac41136a1b31cb3Andreas Huber      mHTTPDataSource(
481156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber              HTTPBase::Create(
497314fa17093d514199fedcb55ac41136a1b31cb3Andreas Huber                  (mFlags & kFlagIncognito)
501156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                    ? HTTPBase::kFlagIncognito
517314fa17093d514199fedcb55ac41136a1b31cb3Andreas Huber                    : 0)),
52a44153c1a57202fb538659eb50706e60454d6273Andreas Huber      mPrevBandwidthIndex(-1),
53a44153c1a57202fb538659eb50706e60454d6273Andreas Huber      mLastPlaylistFetchTimeUs(-1),
54a44153c1a57202fb538659eb50706e60454d6273Andreas Huber      mSeqNumber(-1),
55a44153c1a57202fb538659eb50706e60454d6273Andreas Huber      mSeekTimeUs(-1),
56a44153c1a57202fb538659eb50706e60454d6273Andreas Huber      mNumRetries(0),
57a44153c1a57202fb538659eb50706e60454d6273Andreas Huber      mDurationUs(-1),
58a44153c1a57202fb538659eb50706e60454d6273Andreas Huber      mSeekDone(false),
59ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber      mDisconnectPending(false),
60a44153c1a57202fb538659eb50706e60454d6273Andreas Huber      mMonitorQueueGeneration(0) {
61a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
62a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
63a44153c1a57202fb538659eb50706e60454d6273Andreas HuberLiveSession::~LiveSession() {
64a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
65a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
66a44153c1a57202fb538659eb50706e60454d6273Andreas Hubersp<DataSource> LiveSession::getDataSource() {
67a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return mDataSource;
68a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
69a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
70ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Hubervoid LiveSession::connect(
71ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        const char *url, const KeyedVector<String8, String8> *headers) {
72a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<AMessage> msg = new AMessage(kWhatConnect, id());
73a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    msg->setString("url", url);
74ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber
75ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    if (headers != NULL) {
76ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        msg->setPointer(
77ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber                "headers",
78ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber                new KeyedVector<String8, String8>(*headers));
79ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    }
80ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber
81a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    msg->post();
82a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
83a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
84a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::disconnect() {
85ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber    Mutex::Autolock autoLock(mLock);
86ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber    mDisconnectPending = true;
87ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
88ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber    mHTTPDataSource->disconnect();
89ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
90a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    (new AMessage(kWhatDisconnect, id()))->post();
91a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
92a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
93a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::seekTo(int64_t timeUs) {
94a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    Mutex::Autolock autoLock(mLock);
95a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    mSeekDone = false;
96a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
97a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<AMessage> msg = new AMessage(kWhatSeek, id());
98a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    msg->setInt64("timeUs", timeUs);
99a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    msg->post();
100a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
101a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    while (!mSeekDone) {
102a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        mCondition.wait(mLock);
103a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
104a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
105a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
106a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onMessageReceived(const sp<AMessage> &msg) {
107a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    switch (msg->what()) {
108a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        case kWhatConnect:
109a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            onConnect(msg);
110a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
111a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
112a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        case kWhatDisconnect:
113a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            onDisconnect();
114a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
115a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
116a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        case kWhatMonitorQueue:
117a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        {
118a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            int32_t generation;
119a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            CHECK(msg->findInt32("generation", &generation));
120a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
121a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            if (generation != mMonitorQueueGeneration) {
122a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                // Stale event
123a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                break;
124a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            }
125a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
126a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            onMonitorQueue();
127a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
128a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
129a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
130a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        case kWhatSeek:
131a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            onSeek(msg);
132a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
133a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
134a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        default:
135a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            TRESPASS();
136a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
137a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
138a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
139a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
140a44153c1a57202fb538659eb50706e60454d6273Andreas Huber// static
141a44153c1a57202fb538659eb50706e60454d6273Andreas Huberint LiveSession::SortByBandwidth(const BandwidthItem *a, const BandwidthItem *b) {
142a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (a->mBandwidth < b->mBandwidth) {
143a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return -1;
144a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else if (a->mBandwidth == b->mBandwidth) {
145a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return 0;
146a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
147a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
148a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return 1;
149a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
150a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
151a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onConnect(const sp<AMessage> &msg) {
152a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    AString url;
153a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    CHECK(msg->findString("url", &url));
154a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
155ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    KeyedVector<String8, String8> *headers = NULL;
156ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    if (!msg->findPointer("headers", (void **)&headers)) {
157ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        mExtraHeaders.clear();
158ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    } else {
159ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        mExtraHeaders = *headers;
160ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber
161ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        delete headers;
162ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        headers = NULL;
163ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    }
164ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber
1657314fa17093d514199fedcb55ac41136a1b31cb3Andreas Huber    if (!(mFlags & kFlagIncognito)) {
1667314fa17093d514199fedcb55ac41136a1b31cb3Andreas Huber        LOGI("onConnect '%s'", url.c_str());
1677314fa17093d514199fedcb55ac41136a1b31cb3Andreas Huber    } else {
1687314fa17093d514199fedcb55ac41136a1b31cb3Andreas Huber        LOGI("onConnect <URL suppressed>");
1697314fa17093d514199fedcb55ac41136a1b31cb3Andreas Huber    }
170a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
171a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    mMasterURL = url;
172a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
173a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<M3UParser> playlist = fetchPlaylist(url.c_str());
174ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
175ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber    if (playlist == NULL) {
176ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber        LOGE("unable to fetch master playlist '%s'.", url.c_str());
177ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
178ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber        mDataSource->queueEOS(ERROR_IO);
179ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber        return;
180ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber    }
181a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
182a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (playlist->isVariantPlaylist()) {
183a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        for (size_t i = 0; i < playlist->size(); ++i) {
184a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            BandwidthItem item;
185a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
186a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            sp<AMessage> meta;
187a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            playlist->itemAt(i, &item.mURI, &meta);
188a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
189a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            unsigned long bandwidth;
190a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            CHECK(meta->findInt32("bandwidth", (int32_t *)&item.mBandwidth));
191a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
192a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            mBandwidthItems.push(item);
193a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
194a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
195a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        CHECK_GT(mBandwidthItems.size(), 0u);
196a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
197a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        mBandwidthItems.sort(SortByBandwidth);
198a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
199a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
200a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    postMonitorQueue();
201a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
202a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
203a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onDisconnect() {
204a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    LOGI("onDisconnect");
205a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
206a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    mDataSource->queueEOS(ERROR_END_OF_STREAM);
207ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
208ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber    Mutex::Autolock autoLock(mLock);
209ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber    mDisconnectPending = false;
210a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
211a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
212a44153c1a57202fb538659eb50706e60454d6273Andreas Huberstatus_t LiveSession::fetchFile(const char *url, sp<ABuffer> *out) {
213a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    *out = NULL;
214a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
215a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<DataSource> source;
216a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
217a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (!strncasecmp(url, "file://", 7)) {
218a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        source = new FileSource(url + 7);
2198cb0c4168bf4b678e4a6edfcf409247016be20d5Andreas Huber    } else if (strncasecmp(url, "http://", 7)
2208cb0c4168bf4b678e4a6edfcf409247016be20d5Andreas Huber            && strncasecmp(url, "https://", 8)) {
221df42f949c8bd05b81d94633767514fff88f52062Andreas Huber        return ERROR_UNSUPPORTED;
222a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else {
223ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber        {
224ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber            Mutex::Autolock autoLock(mLock);
225ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
226ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber            if (mDisconnectPending) {
227ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber                return ERROR_IO;
228ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber            }
229ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber        }
230ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
231ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        status_t err = mHTTPDataSource->connect(
232ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber                url, mExtraHeaders.isEmpty() ? NULL : &mExtraHeaders);
233a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
234a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (err != OK) {
235a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            return err;
236a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
237a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
238a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        source = mHTTPDataSource;
239a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
240a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
241a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    off64_t size;
242a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    status_t err = source->getSize(&size);
243a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
244a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (err != OK) {
245a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        size = 65536;
246a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
247a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
248a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<ABuffer> buffer = new ABuffer(size);
249a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    buffer->setRange(0, 0);
250a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
251a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    for (;;) {
252a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        size_t bufferRemaining = buffer->capacity() - buffer->size();
253a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
254a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (bufferRemaining == 0) {
255a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            bufferRemaining = 32768;
256a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
257a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            LOGV("increasing download buffer to %d bytes",
258a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                 buffer->size() + bufferRemaining);
259a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
260a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            sp<ABuffer> copy = new ABuffer(buffer->size() + bufferRemaining);
261a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            memcpy(copy->data(), buffer->data(), buffer->size());
262a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            copy->setRange(0, buffer->size());
263a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
264a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            buffer = copy;
265a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
266a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
267a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        ssize_t n = source->readAt(
268a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                buffer->size(), buffer->data() + buffer->size(),
269a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                bufferRemaining);
270a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
271a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (n < 0) {
27220ad3a341a96e7746015ccb7369fa567897e11f6Andreas Huber            return n;
273a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
274a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
275a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (n == 0) {
276a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
277a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
278a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
279a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        buffer->setRange(0, buffer->size() + (size_t)n);
280a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
281a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
282a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    *out = buffer;
283a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
284a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return OK;
285a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
286a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
287a44153c1a57202fb538659eb50706e60454d6273Andreas Hubersp<M3UParser> LiveSession::fetchPlaylist(const char *url) {
288a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<ABuffer> buffer;
289a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    status_t err = fetchFile(url, &buffer);
290a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
291a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (err != OK) {
292a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return NULL;
293a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
294a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
295a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<M3UParser> playlist =
296a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        new M3UParser(url, buffer->data(), buffer->size());
297a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
298a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (playlist->initCheck() != OK) {
299a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return NULL;
300a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
301a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
302a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return playlist;
303a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
304a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
305a44153c1a57202fb538659eb50706e60454d6273Andreas Huberstatic double uniformRand() {
306a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return (double)rand() / RAND_MAX;
307a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
308a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
309a44153c1a57202fb538659eb50706e60454d6273Andreas Hubersize_t LiveSession::getBandwidthIndex() {
310a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (mBandwidthItems.size() == 0) {
311a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return 0;
312a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
313a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
314a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#if 1
315a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    int32_t bandwidthBps;
316a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (mHTTPDataSource != NULL
317a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            && mHTTPDataSource->estimateBandwidth(&bandwidthBps)) {
318a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        LOGV("bandwidth estimated at %.2f kbps", bandwidthBps / 1024.0f);
319a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else {
320a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        LOGV("no bandwidth estimate.");
321a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return 0;  // Pick the lowest bandwidth stream by default.
322a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
323a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
324a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    char value[PROPERTY_VALUE_MAX];
325a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (property_get("media.httplive.max-bw", value, NULL)) {
326a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        char *end;
327a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        long maxBw = strtoul(value, &end, 10);
328a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (end > value && *end == '\0') {
329a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            if (maxBw > 0 && bandwidthBps > maxBw) {
330a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                LOGV("bandwidth capped to %ld bps", maxBw);
331a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                bandwidthBps = maxBw;
332a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            }
333a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
334a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
335a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
336a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // Consider only 80% of the available bandwidth usable.
337a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    bandwidthBps = (bandwidthBps * 8) / 10;
338a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
339a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // Pick the highest bandwidth stream below or equal to estimated bandwidth.
340a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
341a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index = mBandwidthItems.size() - 1;
342a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    while (index > 0 && mBandwidthItems.itemAt(index).mBandwidth
343a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                            > (size_t)bandwidthBps) {
344a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        --index;
345a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
346a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0
347a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // Change bandwidth at random()
348a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index = uniformRand() * mBandwidthItems.size();
349a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0
350a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // There's a 50% chance to stay on the current bandwidth and
351a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // a 50% chance to switch to the next higher bandwidth (wrapping around
352a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // to lowest)
353a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    const size_t kMinIndex = 0;
354a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
355a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index;
356a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (mPrevBandwidthIndex < 0) {
357a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        index = kMinIndex;
358a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else if (uniformRand() < 0.5) {
359a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        index = (size_t)mPrevBandwidthIndex;
360a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else {
361a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        index = mPrevBandwidthIndex + 1;
362a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (index == mBandwidthItems.size()) {
363a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            index = kMinIndex;
364a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
365a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
366a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#elif 0
367a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // Pick the highest bandwidth stream below or equal to 1.2 Mbit/sec
368a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
369a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index = mBandwidthItems.size() - 1;
370a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    while (index > 0 && mBandwidthItems.itemAt(index).mBandwidth > 1200000) {
371a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        --index;
372a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
373a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#else
374a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t index = mBandwidthItems.size() - 1;  // Highest bandwidth stream
375a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#endif
376a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
377a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return index;
378a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
379a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
380a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onDownloadNext() {
381a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t bandwidthIndex = getBandwidthIndex();
382a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
383aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huberrinse_repeat:
384a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    int64_t nowUs = ALooper::GetNowUs();
385a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
386a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (mLastPlaylistFetchTimeUs < 0
387a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            || (ssize_t)bandwidthIndex != mPrevBandwidthIndex
388a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            || (!mPlaylist->isComplete()
389a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                && mLastPlaylistFetchTimeUs + kMaxPlaylistAgeUs <= nowUs)) {
390a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        AString url;
391a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (mBandwidthItems.size() > 0) {
392a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            url = mBandwidthItems.editItemAt(bandwidthIndex).mURI;
393a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        } else {
394a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            url = mMasterURL;
395a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
396a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
397a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        bool firstTime = (mPlaylist == NULL);
398a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
399a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        mPlaylist = fetchPlaylist(url.c_str());
4006e6b1cae2bac1b78205cefab8e4e9e9538982965Andreas Huber        if (mPlaylist == NULL) {
4016e6b1cae2bac1b78205cefab8e4e9e9538982965Andreas Huber            LOGE("failed to load playlist at url '%s'", url.c_str());
4026e6b1cae2bac1b78205cefab8e4e9e9538982965Andreas Huber            mDataSource->queueEOS(ERROR_IO);
4036e6b1cae2bac1b78205cefab8e4e9e9538982965Andreas Huber            return;
4046e6b1cae2bac1b78205cefab8e4e9e9538982965Andreas Huber        }
405a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
406a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (firstTime) {
407a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            Mutex::Autolock autoLock(mLock);
408a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
409a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            int32_t targetDuration;
410a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            if (!mPlaylist->isComplete()
411a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                    || !mPlaylist->meta()->findInt32(
412a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                    "target-duration", &targetDuration)) {
413a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                mDurationUs = -1;
414a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            } else {
415a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                mDurationUs = 1000000ll * targetDuration * mPlaylist->size();
416a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            }
417a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
418a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
419a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        mLastPlaylistFetchTimeUs = ALooper::GetNowUs();
420a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
421a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
422a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    int32_t firstSeqNumberInPlaylist;
423a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (mPlaylist->meta() == NULL || !mPlaylist->meta()->findInt32(
424a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                "media-sequence", &firstSeqNumberInPlaylist)) {
425a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        firstSeqNumberInPlaylist = 0;
426a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
427a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
428a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    bool explicitDiscontinuity = false;
42922fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber    bool bandwidthChanged = false;
430a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
431a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (mSeekTimeUs >= 0) {
432a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        int32_t targetDuration;
433a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (mPlaylist->isComplete() &&
434a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                mPlaylist->meta()->findInt32(
435a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                    "target-duration", &targetDuration)) {
436a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            int64_t seekTimeSecs = (mSeekTimeUs + 500000ll) / 1000000ll;
437a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            int64_t index = seekTimeSecs / targetDuration;
438a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
439a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            if (index >= 0 && index < mPlaylist->size()) {
44043c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber                int32_t newSeqNumber = firstSeqNumberInPlaylist + index;
441a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
44243c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber                if (newSeqNumber != mSeqNumber) {
44343c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber                    LOGI("seeking to seq no %d", newSeqNumber);
44443c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
44543c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber                    mSeqNumber = newSeqNumber;
44643c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
44743c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber                    mDataSource->reset();
44843c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
44922fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber                    // reseting the data source will have had the
45022fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber                    // side effect of discarding any previously queued
45122fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber                    // bandwidth change discontinuity.
45222fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber                    // Therefore we'll need to treat these explicit
45322fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber                    // discontinuities as involving a bandwidth change
45422fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber                    // even if they aren't directly.
45543c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber                    explicitDiscontinuity = true;
45622fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber                    bandwidthChanged = true;
45743c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber                }
458a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            }
459a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
460a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
461a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        mSeekTimeUs = -1;
462a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
463a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        Mutex::Autolock autoLock(mLock);
464a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        mSeekDone = true;
465a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        mCondition.broadcast();
466a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
467a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
468a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (mSeqNumber < 0) {
469a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (mPlaylist->isComplete()) {
470a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            mSeqNumber = firstSeqNumberInPlaylist;
471a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        } else {
472a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            mSeqNumber = firstSeqNumberInPlaylist + mPlaylist->size() / 2;
473a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
474a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
475a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
476a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    int32_t lastSeqNumberInPlaylist =
477a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        firstSeqNumberInPlaylist + (int32_t)mPlaylist->size() - 1;
478a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
479a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (mSeqNumber < firstSeqNumberInPlaylist
480a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            || mSeqNumber > lastSeqNumberInPlaylist) {
48188b7ad413c4b6d08697069b18488641d6ce31fd3Andreas Huber        if (mPrevBandwidthIndex != (ssize_t)bandwidthIndex) {
482aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber            // Go back to the previous bandwidth.
483aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber
484aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber            LOGI("new bandwidth does not have the sequence number "
485aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber                 "we're looking for, switching back to previous bandwidth");
486aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber
487aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber            mLastPlaylistFetchTimeUs = -1;
488aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber            bandwidthIndex = mPrevBandwidthIndex;
489aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber            goto rinse_repeat;
490aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber        }
491aea5aff45a1af14e249ac311f0a128a621a7d13eAndreas Huber
492a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (!mPlaylist->isComplete()
493a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                && mSeqNumber > lastSeqNumberInPlaylist
494a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                && mNumRetries < kMaxNumRetries) {
495a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            ++mNumRetries;
496a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
497a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            mLastPlaylistFetchTimeUs = -1;
4985bc087c573c70c84c6a39946457590b42d392a33Andreas Huber            postMonitorQueue(3000000ll);
499a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            return;
500a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
501a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
502a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        LOGE("Cannot find sequence number %d in playlist "
503a44153c1a57202fb538659eb50706e60454d6273Andreas Huber             "(contains %d - %d)",
504a44153c1a57202fb538659eb50706e60454d6273Andreas Huber             mSeqNumber, firstSeqNumberInPlaylist,
505a44153c1a57202fb538659eb50706e60454d6273Andreas Huber             firstSeqNumberInPlaylist + mPlaylist->size() - 1);
506a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
507a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        mDataSource->queueEOS(ERROR_END_OF_STREAM);
508a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return;
509a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
510a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
511a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    mNumRetries = 0;
512a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
513a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    AString uri;
514a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<AMessage> itemMeta;
515a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    CHECK(mPlaylist->itemAt(
516a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                mSeqNumber - firstSeqNumberInPlaylist,
517a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                &uri,
518a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                &itemMeta));
519a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
520a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    int32_t val;
521a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (itemMeta->findInt32("discontinuity", &val) && val != 0) {
522a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        explicitDiscontinuity = true;
523a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
524a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
525a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<ABuffer> buffer;
526a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    status_t err = fetchFile(uri.c_str(), &buffer);
5276e6b1cae2bac1b78205cefab8e4e9e9538982965Andreas Huber    if (err != OK) {
5286e6b1cae2bac1b78205cefab8e4e9e9538982965Andreas Huber        LOGE("failed to fetch .ts segment at url '%s'", uri.c_str());
5296e6b1cae2bac1b78205cefab8e4e9e9538982965Andreas Huber        mDataSource->queueEOS(err);
5306e6b1cae2bac1b78205cefab8e4e9e9538982965Andreas Huber        return;
5316e6b1cae2bac1b78205cefab8e4e9e9538982965Andreas Huber    }
532a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
53343c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber    CHECK(buffer != NULL);
53443c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
53588b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber    err = decryptBuffer(mSeqNumber - firstSeqNumberInPlaylist, buffer);
53688b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber
53788b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber    if (err != OK) {
53888b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber        LOGE("decryptBuffer failed w/ error %d", err);
53988b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber
54088b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber        mDataSource->queueEOS(err);
54188b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber        return;
54288b348910a607ae399bcd693dd42a231d98da2c9Andreas Huber    }
543a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
544a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (buffer->size() == 0 || buffer->data()[0] != 0x47) {
545a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        // Not a transport stream???
546a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
547a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        LOGE("This doesn't look like a transport stream...");
548a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
549bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber        mBandwidthItems.removeAt(bandwidthIndex);
550bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
551bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber        if (mBandwidthItems.isEmpty()) {
552bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber            mDataSource->queueEOS(ERROR_UNSUPPORTED);
553bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber            return;
554bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber        }
555bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
556bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber        LOGI("Retrying with a different bandwidth stream.");
557bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
558bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber        mLastPlaylistFetchTimeUs = -1;
559bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber        bandwidthIndex = getBandwidthIndex();
560bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber        mPrevBandwidthIndex = bandwidthIndex;
561bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber        mSeqNumber = -1;
562bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
563bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber        goto rinse_repeat;
564a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
565a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
56622fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber    if ((size_t)mPrevBandwidthIndex != bandwidthIndex) {
56722fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber        bandwidthChanged = true;
56822fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber    }
56922fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber
57022fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber    if (mPrevBandwidthIndex < 0) {
57122fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber        // Don't signal a bandwidth change at the very beginning of
57222fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber        // playback.
57322fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber        bandwidthChanged = false;
57422fc52f6f72f39e33c3970d0291de3569118aa5cAndreas Huber    }
5753831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber
5763831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber    if (explicitDiscontinuity || bandwidthChanged) {
577a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        // Signal discontinuity.
578a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
57943c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber        LOGI("queueing discontinuity (explicit=%d, bandwidthChanged=%d)",
58043c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber             explicitDiscontinuity, bandwidthChanged);
58143c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
582a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        sp<ABuffer> tmp = new ABuffer(188);
583a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        memset(tmp->data(), 0, tmp->size());
5843831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber        tmp->data()[1] = bandwidthChanged;
585a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
586a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        mDataSource->queueBuffer(tmp);
587a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
588a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
589a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    mDataSource->queueBuffer(buffer);
590a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
591a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    mPrevBandwidthIndex = bandwidthIndex;
592a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    ++mSeqNumber;
593a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
594a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    postMonitorQueue();
595a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
596a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
597a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onMonitorQueue() {
598a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (mSeekTimeUs >= 0
599a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            || mDataSource->countQueuedBuffers() < kMaxNumQueuedFragments) {
600a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        onDownloadNext();
601a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else {
602a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        postMonitorQueue(1000000ll);
603a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
604a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
605a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
606a44153c1a57202fb538659eb50706e60454d6273Andreas Huberstatus_t LiveSession::decryptBuffer(
607a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        size_t playlistIndex, const sp<ABuffer> &buffer) {
608a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<AMessage> itemMeta;
609a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    bool found = false;
610a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    AString method;
611a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
612a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    for (ssize_t i = playlistIndex; i >= 0; --i) {
613a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        AString uri;
614a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        CHECK(mPlaylist->itemAt(i, &uri, &itemMeta));
615a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
616a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (itemMeta->findString("cipher-method", &method)) {
617a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            found = true;
618a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
619a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
620a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
621a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
622a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (!found) {
623a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        method = "NONE";
624a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
625a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
626a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (method == "NONE") {
627a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return OK;
628a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else if (!(method == "AES-128")) {
629a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        LOGE("Unsupported cipher method '%s'", method.c_str());
630a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return ERROR_UNSUPPORTED;
631a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
632a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
633a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    AString keyURI;
634a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (!itemMeta->findString("cipher-uri", &keyURI)) {
635a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        LOGE("Missing key uri");
636a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return ERROR_MALFORMED;
637a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
638a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
639a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    ssize_t index = mAESKeyForURI.indexOfKey(keyURI);
640a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
641a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<ABuffer> key;
642a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (index >= 0) {
643a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        key = mAESKeyForURI.valueAt(index);
644a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else {
645a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        key = new ABuffer(16);
646a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
6471156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        sp<HTTPBase> keySource =
6481156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber              HTTPBase::Create(
6491156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                  (mFlags & kFlagIncognito)
6501156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                    ? HTTPBase::kFlagIncognito
6511156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                    : 0);
6521156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
653a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        status_t err = keySource->connect(keyURI.c_str());
654a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
655a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (err == OK) {
656a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            size_t offset = 0;
657a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            while (offset < 16) {
658a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                ssize_t n = keySource->readAt(
659a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                        offset, key->data() + offset, 16 - offset);
660a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                if (n <= 0) {
661a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                    err = ERROR_IO;
662a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                    break;
663a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                }
664a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
665a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                offset += n;
666a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            }
667a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
668a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
669a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (err != OK) {
670a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            LOGE("failed to fetch cipher key from '%s'.", keyURI.c_str());
671a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            return ERROR_IO;
672a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
673a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
674a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        mAESKeyForURI.add(keyURI, key);
675a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
676a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
677a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    AES_KEY aes_key;
678a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (AES_set_decrypt_key(key->data(), 128, &aes_key) != 0) {
679a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        LOGE("failed to set AES decryption key.");
680a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return UNKNOWN_ERROR;
681a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
682a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
683a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    unsigned char aes_ivec[16];
684a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
685a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    AString iv;
686a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (itemMeta->findString("cipher-iv", &iv)) {
687a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if ((!iv.startsWith("0x") && !iv.startsWith("0X"))
688a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                || iv.size() != 16 * 2 + 2) {
689a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            LOGE("malformed cipher IV '%s'.", iv.c_str());
690a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            return ERROR_MALFORMED;
691a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
692a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
693a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        memset(aes_ivec, 0, sizeof(aes_ivec));
694a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        for (size_t i = 0; i < 16; ++i) {
695a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            char c1 = tolower(iv.c_str()[2 + 2 * i]);
696a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            char c2 = tolower(iv.c_str()[3 + 2 * i]);
697a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            if (!isxdigit(c1) || !isxdigit(c2)) {
698a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                LOGE("malformed cipher IV '%s'.", iv.c_str());
699a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                return ERROR_MALFORMED;
700a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            }
701a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            uint8_t nibble1 = isdigit(c1) ? c1 - '0' : c1 - 'a' + 10;
702a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            uint8_t nibble2 = isdigit(c2) ? c2 - '0' : c2 - 'a' + 10;
703a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
704a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            aes_ivec[i] = nibble1 << 4 | nibble2;
705a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
706a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else {
707a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        memset(aes_ivec, 0, sizeof(aes_ivec));
708a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        aes_ivec[15] = mSeqNumber & 0xff;
709a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        aes_ivec[14] = (mSeqNumber >> 8) & 0xff;
710a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        aes_ivec[13] = (mSeqNumber >> 16) & 0xff;
711a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        aes_ivec[12] = (mSeqNumber >> 24) & 0xff;
712a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
713a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
714a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    AES_cbc_encrypt(
715a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            buffer->data(), buffer->data(), buffer->size(),
716a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            &aes_key, aes_ivec, AES_DECRYPT);
717a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
718a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    // hexdump(buffer->data(), buffer->size());
719a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
720a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t n = buffer->size();
721a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    CHECK_GT(n, 0u);
722a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
723a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    size_t pad = buffer->data()[n - 1];
724a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
725a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    CHECK_GT(pad, 0u);
726a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    CHECK_LE(pad, 16u);
727a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    CHECK_GE((size_t)n, pad);
728a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    for (size_t i = 0; i < pad; ++i) {
729a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        CHECK_EQ((unsigned)buffer->data()[n - 1 - i], pad);
730a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
731a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
732a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    n -= pad;
733a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
734a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    buffer->setRange(buffer->offset(), n);
735a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
736a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return OK;
737a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
738a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
739a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::postMonitorQueue(int64_t delayUs) {
740a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<AMessage> msg = new AMessage(kWhatMonitorQueue, id());
741a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    msg->setInt32("generation", ++mMonitorQueueGeneration);
742a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    msg->post(delayUs);
743a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
744a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
745a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onSeek(const sp<AMessage> &msg) {
746a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    int64_t timeUs;
747a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    CHECK(msg->findInt64("timeUs", &timeUs));
748a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
749a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    mSeekTimeUs = timeUs;
750a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    postMonitorQueue();
751a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
752a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
753a44153c1a57202fb538659eb50706e60454d6273Andreas Huberstatus_t LiveSession::getDuration(int64_t *durationUs) {
754a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    Mutex::Autolock autoLock(mLock);
755a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    *durationUs = mDurationUs;
756a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
757a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return OK;
758a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
759a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
760a44153c1a57202fb538659eb50706e60454d6273Andreas Huberbool LiveSession::isSeekable() {
761a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    int64_t durationUs;
762a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return getDuration(&durationUs) == OK && durationUs >= 0;
763a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
764a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
765a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}  // namespace android
766a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
767