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