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