114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber/* 214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber * Copyright (C) 2012 The Android Open Source Project 314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber * 414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber * you may not use this file except in compliance with the License. 614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber * You may obtain a copy of the License at 714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber * 814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber * http://www.apache.org/licenses/LICENSE-2.0 914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber * 1014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber * Unless required by applicable law or agreed to in writing, software 1114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 1214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber * See the License for the specific language governing permissions and 1414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber * limitations under the License. 1514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber */ 1614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 1714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber//#define LOG_NDEBUG 0 1814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#define LOG_TAG "PlaylistFetcher" 1914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include <utils/Log.h> 200852843d304006e3ab333081fddda13b07193de8Robert Shih#include <utils/misc.h> 2114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 2214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include "PlaylistFetcher.h" 235abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang#include "HTTPDownloader.h" 2414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include "LiveSession.h" 2514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include "M3UParser.h" 2614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include "include/avc_utils.h" 2714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include "include/ID3.h" 2814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include "mpeg2ts/AnotherPacketSource.h" 293a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania#include "mpeg2ts/HlsSampleDecryptor.h" 3014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 3114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include <media/stagefright/foundation/ABitReader.h> 3214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include <media/stagefright/foundation/ABuffer.h> 3314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include <media/stagefright/foundation/ADebug.h> 3414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include <media/stagefright/MediaDefs.h> 3514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include <media/stagefright/MetaData.h> 3614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include <media/stagefright/Utils.h> 3714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 3814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include <ctype.h> 39b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross#include <inttypes.h> 4014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 4125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang#define FLOGV(fmt, ...) ALOGV("[fetcher-%d] " fmt, mFetcherID, ##__VA_ARGS__) 4225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang#define FSLOGV(stream, fmt, ...) ALOGV("[fetcher-%d] [%s] " fmt, mFetcherID, \ 4325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang LiveSession::getNameForStream(stream), ##__VA_ARGS__) 4425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 4514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubernamespace android { 4614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 4714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber// static 487c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangconst int64_t PlaylistFetcher::kMinBufferedDurationUs = 30000000ll; 49e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnarconst int64_t PlaylistFetcher::kMaxMonitorDelayUs = 3000000ll; 50a93fd2be99d21629bed504b9b7df035fc2f54562Leena Winterrowd// LCM of 188 (size of a TS packet) & 1k works well 51a93fd2be99d21629bed504b9b7df035fc2f54562Leena Winterrowdconst int32_t PlaylistFetcher::kDownloadBlockSize = 47 * 1024; 5214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 53a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhangstruct PlaylistFetcher::DownloadState : public RefBase { 54a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang DownloadState(); 55a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang void resetState(); 56a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang bool hasSavedState() const; 57a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang void restoreState( 58a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang AString &uri, 59a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang sp<AMessage> &itemMeta, 60a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang sp<ABuffer> &buffer, 61a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang sp<ABuffer> &tsBuffer, 62a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang int32_t &firstSeqNumberInPlaylist, 63a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang int32_t &lastSeqNumberInPlaylist); 64a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang void saveState( 65a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang AString &uri, 66a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang sp<AMessage> &itemMeta, 67a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang sp<ABuffer> &buffer, 68a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang sp<ABuffer> &tsBuffer, 69a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang int32_t &firstSeqNumberInPlaylist, 70a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang int32_t &lastSeqNumberInPlaylist); 71a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 72a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhangprivate: 73a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang bool mHasSavedState; 74a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang AString mUri; 75a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang sp<AMessage> mItemMeta; 76a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang sp<ABuffer> mBuffer; 77a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang sp<ABuffer> mTsBuffer; 78a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang int32_t mFirstSeqNumberInPlaylist; 79a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang int32_t mLastSeqNumberInPlaylist; 80a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang}; 81a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 82a48d372833ccec13c96ece9efcc226e8beac7f59Chong ZhangPlaylistFetcher::DownloadState::DownloadState() { 83a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang resetState(); 84a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang} 85a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 86a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhangbool PlaylistFetcher::DownloadState::hasSavedState() const { 87a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang return mHasSavedState; 88a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang} 89a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 90a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhangvoid PlaylistFetcher::DownloadState::resetState() { 91a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mHasSavedState = false; 92a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 93a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mUri.clear(); 94a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mItemMeta = NULL; 95a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mBuffer = NULL; 96a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mTsBuffer = NULL; 97a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mFirstSeqNumberInPlaylist = 0; 98a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mLastSeqNumberInPlaylist = 0; 99a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang} 100a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 101a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhangvoid PlaylistFetcher::DownloadState::restoreState( 102a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang AString &uri, 103a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang sp<AMessage> &itemMeta, 104a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang sp<ABuffer> &buffer, 105a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang sp<ABuffer> &tsBuffer, 106a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang int32_t &firstSeqNumberInPlaylist, 107a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang int32_t &lastSeqNumberInPlaylist) { 108a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (!mHasSavedState) { 109a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang return; 110a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 111a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 112a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang uri = mUri; 113a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang itemMeta = mItemMeta; 114a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang buffer = mBuffer; 115a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang tsBuffer = mTsBuffer; 116a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang firstSeqNumberInPlaylist = mFirstSeqNumberInPlaylist; 117a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang lastSeqNumberInPlaylist = mLastSeqNumberInPlaylist; 118a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 119a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang resetState(); 120a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang} 121a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 122a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhangvoid PlaylistFetcher::DownloadState::saveState( 123a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang AString &uri, 124a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang sp<AMessage> &itemMeta, 125a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang sp<ABuffer> &buffer, 126a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang sp<ABuffer> &tsBuffer, 127a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang int32_t &firstSeqNumberInPlaylist, 128a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang int32_t &lastSeqNumberInPlaylist) { 129a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mHasSavedState = true; 130a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 131a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mUri = uri; 132a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mItemMeta = itemMeta; 133a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mBuffer = buffer; 134a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mTsBuffer = tsBuffer; 135a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mFirstSeqNumberInPlaylist = firstSeqNumberInPlaylist; 136a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mLastSeqNumberInPlaylist = lastSeqNumberInPlaylist; 137a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang} 138a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 13914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas HuberPlaylistFetcher::PlaylistFetcher( 14014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber const sp<AMessage> ¬ify, 14114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber const sp<LiveSession> &session, 142b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih const char *uri, 14325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang int32_t id, 144b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih int32_t subtitleGeneration) 14514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber : mNotify(notify), 14614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mSession(session), 14714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mURI(uri), 14825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang mFetcherID(id), 14914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mStreamTypeMask(0), 15014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mStartTimeUs(-1ll), 151309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mSegmentStartTimeUs(-1ll), 152309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mDiscontinuitySeq(-1ll), 153309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mStartTimeUsRelative(false), 15414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mLastPlaylistFetchTimeUs(-1ll), 155978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mPlaylistTimeUs(-1ll), 15614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mSeqNumber(-1), 15714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mNumRetries(0), 15814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mStartup(true), 1597c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mIDRFound(false), 160a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mSeekMode(LiveSession::kSeekModeExactPosition), 161c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang mTimeChangeSignaled(false), 16214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mNextPTSTimeUs(-1ll), 16314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mMonitorQueueGeneration(0), 164b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih mSubtitleGeneration(subtitleGeneration), 165c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang mLastDiscontinuitySeq(-1ll), 16614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mRefreshState(INITIAL_MINIMUM_RELOAD_DELAY), 16714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mFirstPTSValid(false), 168a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mFirstTimeUs(-1ll), 169a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mVideoBuffer(new AnotherPacketSource(NULL)), 1703a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania mSampleAesKeyItemChanged(false), 171a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mThresholdRatio(-1.0f), 1720852843d304006e3ab333081fddda13b07193de8Robert Shih mDownloadState(new DownloadState()), 1730852843d304006e3ab333081fddda13b07193de8Robert Shih mHasMetadata(false) { 17414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber memset(mPlaylistHash, 0, sizeof(mPlaylistHash)); 1755abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang mHTTPDownloader = mSession->getHTTPDownloader(); 1763a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 1773a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania memset(mKeyData, 0, sizeof(mKeyData)); 1783a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania memset(mAESInitVec, 0, sizeof(mAESInitVec)); 17914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 18014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 18114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas HuberPlaylistFetcher::~PlaylistFetcher() { 18214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 18314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 18425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhangint32_t PlaylistFetcher::getFetcherID() const { 18525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang return mFetcherID; 18625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang} 18725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 18814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberint64_t PlaylistFetcher::getSegmentStartTimeUs(int32_t seqNumber) const { 18914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(mPlaylist != NULL); 19014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 191978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang int32_t firstSeqNumberInPlaylist, lastSeqNumberInPlaylist; 192978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mPlaylist->getSeqNumberRange( 193978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang &firstSeqNumberInPlaylist, &lastSeqNumberInPlaylist); 19414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 19514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK_GE(seqNumber, firstSeqNumberInPlaylist); 19614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK_LE(seqNumber, lastSeqNumberInPlaylist); 19714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 19814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int64_t segmentStartUs = 0ll; 19914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber for (int32_t index = 0; 20014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber index < seqNumber - firstSeqNumberInPlaylist; ++index) { 20114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AMessage> itemMeta; 20214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(mPlaylist->itemAt( 20314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber index, NULL /* uri */, &itemMeta)); 20414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 20514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int64_t itemDurationUs; 20614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(itemMeta->findInt64("durationUs", &itemDurationUs)); 20714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 20814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber segmentStartUs += itemDurationUs; 20914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 21014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 21114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return segmentStartUs; 21214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 21314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 2147c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangint64_t PlaylistFetcher::getSegmentDurationUs(int32_t seqNumber) const { 2157c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang CHECK(mPlaylist != NULL); 2167c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 217978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang int32_t firstSeqNumberInPlaylist, lastSeqNumberInPlaylist; 218978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mPlaylist->getSeqNumberRange( 219978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang &firstSeqNumberInPlaylist, &lastSeqNumberInPlaylist); 2207c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 2217c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang CHECK_GE(seqNumber, firstSeqNumberInPlaylist); 2227c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang CHECK_LE(seqNumber, lastSeqNumberInPlaylist); 2237c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 2247c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang int32_t index = seqNumber - firstSeqNumberInPlaylist; 2257c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AMessage> itemMeta; 2267c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang CHECK(mPlaylist->itemAt( 2277c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang index, NULL /* uri */, &itemMeta)); 2287c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 2297c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang int64_t itemDurationUs; 2307c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang CHECK(itemMeta->findInt64("durationUs", &itemDurationUs)); 2317c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 2327c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return itemDurationUs; 2337c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang} 2347c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 235e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnarint64_t PlaylistFetcher::delayUsToRefreshPlaylist() const { 236e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar int64_t nowUs = ALooper::GetNowUs(); 237e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar 238e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar if (mPlaylist == NULL || mLastPlaylistFetchTimeUs < 0ll) { 23914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK_EQ((int)mRefreshState, (int)INITIAL_MINIMUM_RELOAD_DELAY); 240e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar return 0ll; 241e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar } 242e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar 243e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar if (mPlaylist->isComplete()) { 244e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar return (~0llu >> 1); 24514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 24614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 247978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang int64_t targetDurationUs = mPlaylist->getTargetDuration(); 24814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 24914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int64_t minPlaylistAgeUs; 25014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 25114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber switch (mRefreshState) { 25214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case INITIAL_MINIMUM_RELOAD_DELAY: 25314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 25414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber size_t n = mPlaylist->size(); 25514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (n > 0) { 25614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AMessage> itemMeta; 25714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(mPlaylist->itemAt(n - 1, NULL /* uri */, &itemMeta)); 25814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 25914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int64_t itemDurationUs; 26014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(itemMeta->findInt64("durationUs", &itemDurationUs)); 26114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 26214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber minPlaylistAgeUs = itemDurationUs; 26314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 26414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 26514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 26614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // fall through 26714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 26814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 26914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case FIRST_UNCHANGED_RELOAD_ATTEMPT: 27014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 27114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber minPlaylistAgeUs = targetDurationUs / 2; 27214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 27314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 27414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 27514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case SECOND_UNCHANGED_RELOAD_ATTEMPT: 27614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 27714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber minPlaylistAgeUs = (targetDurationUs * 3) / 2; 27814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 27914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 28014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 28114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case THIRD_UNCHANGED_RELOAD_ATTEMPT: 28214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 28314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber minPlaylistAgeUs = targetDurationUs * 3; 28414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 28514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 28614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 28714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber default: 28814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber TRESPASS(); 28914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 29014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 29114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 292e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar int64_t delayUs = mLastPlaylistFetchTimeUs + minPlaylistAgeUs - nowUs; 293e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar return delayUs > 0ll ? delayUs : 0ll; 29414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 29514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 29614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t PlaylistFetcher::decryptBuffer( 297ebe130923fb1a5b8dda4b3ee215593edcd804f0dRobert Shih size_t playlistIndex, const sp<ABuffer> &buffer, 298ebe130923fb1a5b8dda4b3ee215593edcd804f0dRobert Shih bool first) { 29914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AMessage> itemMeta; 30014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber bool found = false; 30114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber AString method; 30214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 30314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber for (ssize_t i = playlistIndex; i >= 0; --i) { 30414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber AString uri; 30514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(mPlaylist->itemAt(i, &uri, &itemMeta)); 30614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 30714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (itemMeta->findString("cipher-method", &method)) { 30814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber found = true; 30914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 31014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 31114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 31214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 3133a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania // TODO: Revise this when we add support for KEYFORMAT 3143a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania // If method has changed (e.g., -> NONE); sufficient to check at the segment boundary 3153a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania if (mSampleAesKeyItem != NULL && first && found && method != "SAMPLE-AES") { 3163a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania ALOGI("decryptBuffer: resetting mSampleAesKeyItem(%p) with method %s", 3173a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania mSampleAesKeyItem.get(), method.c_str()); 3183a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania mSampleAesKeyItem = NULL; 3193a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania mSampleAesKeyItemChanged = true; 3203a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania } 3213a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 32214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (!found) { 32314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber method = "NONE"; 32414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 325ebe130923fb1a5b8dda4b3ee215593edcd804f0dRobert Shih buffer->meta()->setString("cipher-method", method.c_str()); 32614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 32714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (method == "NONE") { 32814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return OK; 3293a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania } else if (method == "SAMPLE-AES") { 3303a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania ALOGV("decryptBuffer: Non-Widevine SAMPLE-AES is supported now."); 33114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else if (!(method == "AES-128")) { 33214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGE("Unsupported cipher method '%s'", method.c_str()); 33314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return ERROR_UNSUPPORTED; 33414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 33514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 33614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber AString keyURI; 33714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (!itemMeta->findString("cipher-uri", &keyURI)) { 33814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGE("Missing key uri"); 33914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return ERROR_MALFORMED; 34014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 34114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 34214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ssize_t index = mAESKeyForURI.indexOfKey(keyURI); 34314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 34414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<ABuffer> key; 34514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (index >= 0) { 34614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber key = mAESKeyForURI.valueAt(index); 34714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else { 3485abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang ssize_t err = mHTTPDownloader->fetchFile(keyURI.c_str(), &key); 34914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 3505abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang if (err == ERROR_NOT_CONNECTED) { 3515abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang return ERROR_NOT_CONNECTED; 3525abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } else if (err < 0) { 35314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGE("failed to fetch cipher key from '%s'.", keyURI.c_str()); 35414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return ERROR_IO; 35514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else if (key->size() != 16) { 35614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGE("key file '%s' wasn't 16 bytes in size.", keyURI.c_str()); 35714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return ERROR_MALFORMED; 35814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 35914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 36014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mAESKeyForURI.add(keyURI, key); 36114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 36214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 363ebe130923fb1a5b8dda4b3ee215593edcd804f0dRobert Shih if (first) { 364ebe130923fb1a5b8dda4b3ee215593edcd804f0dRobert Shih // If decrypting the first block in a file, read the iv from the manifest 365ebe130923fb1a5b8dda4b3ee215593edcd804f0dRobert Shih // or derive the iv from the file's sequence number. 36614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 3673a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania unsigned char AESInitVec[AES_BLOCK_SIZE]; 368ebe130923fb1a5b8dda4b3ee215593edcd804f0dRobert Shih AString iv; 369ebe130923fb1a5b8dda4b3ee215593edcd804f0dRobert Shih if (itemMeta->findString("cipher-iv", &iv)) { 370ebe130923fb1a5b8dda4b3ee215593edcd804f0dRobert Shih if ((!iv.startsWith("0x") && !iv.startsWith("0X")) 3714a3108a4464490a57bbe2854d1b47df8336bd471Robert Shih || iv.size() > 16 * 2 + 2) { 37214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGE("malformed cipher IV '%s'.", iv.c_str()); 37314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return ERROR_MALFORMED; 37414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 37514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 3764a3108a4464490a57bbe2854d1b47df8336bd471Robert Shih while (iv.size() < 16 * 2 + 2) { 3774a3108a4464490a57bbe2854d1b47df8336bd471Robert Shih iv.insert("0", 1, 2); 3784a3108a4464490a57bbe2854d1b47df8336bd471Robert Shih } 3794a3108a4464490a57bbe2854d1b47df8336bd471Robert Shih 3803a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania memset(AESInitVec, 0, sizeof(AESInitVec)); 381ebe130923fb1a5b8dda4b3ee215593edcd804f0dRobert Shih for (size_t i = 0; i < 16; ++i) { 382ebe130923fb1a5b8dda4b3ee215593edcd804f0dRobert Shih char c1 = tolower(iv.c_str()[2 + 2 * i]); 383ebe130923fb1a5b8dda4b3ee215593edcd804f0dRobert Shih char c2 = tolower(iv.c_str()[3 + 2 * i]); 384ebe130923fb1a5b8dda4b3ee215593edcd804f0dRobert Shih if (!isxdigit(c1) || !isxdigit(c2)) { 385ebe130923fb1a5b8dda4b3ee215593edcd804f0dRobert Shih ALOGE("malformed cipher IV '%s'.", iv.c_str()); 386ebe130923fb1a5b8dda4b3ee215593edcd804f0dRobert Shih return ERROR_MALFORMED; 387ebe130923fb1a5b8dda4b3ee215593edcd804f0dRobert Shih } 388ebe130923fb1a5b8dda4b3ee215593edcd804f0dRobert Shih uint8_t nibble1 = isdigit(c1) ? c1 - '0' : c1 - 'a' + 10; 389ebe130923fb1a5b8dda4b3ee215593edcd804f0dRobert Shih uint8_t nibble2 = isdigit(c2) ? c2 - '0' : c2 - 'a' + 10; 390ebe130923fb1a5b8dda4b3ee215593edcd804f0dRobert Shih 3913a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania AESInitVec[i] = nibble1 << 4 | nibble2; 392ebe130923fb1a5b8dda4b3ee215593edcd804f0dRobert Shih } 393ebe130923fb1a5b8dda4b3ee215593edcd804f0dRobert Shih } else { 3943a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania memset(AESInitVec, 0, sizeof(AESInitVec)); 3953a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania AESInitVec[15] = mSeqNumber & 0xff; 3963a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania AESInitVec[14] = (mSeqNumber >> 8) & 0xff; 3973a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania AESInitVec[13] = (mSeqNumber >> 16) & 0xff; 3983a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania AESInitVec[12] = (mSeqNumber >> 24) & 0xff; 3993a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania } 4003a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 4013a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania bool newKey = memcmp(mKeyData, key->data(), AES_BLOCK_SIZE) != 0; 4023a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania bool newInitVec = memcmp(mAESInitVec, AESInitVec, AES_BLOCK_SIZE) != 0; 4033a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania bool newSampleAesKeyItem = newKey || newInitVec; 4043a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania ALOGV("decryptBuffer: SAMPLE-AES newKeyItem %d/%d (Key %d initVec %d)", 4053a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania mSampleAesKeyItemChanged, newSampleAesKeyItem, newKey, newInitVec); 4063a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 4073a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania if (newSampleAesKeyItem) { 4083a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania memcpy(mKeyData, key->data(), AES_BLOCK_SIZE); 4093a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania memcpy(mAESInitVec, AESInitVec, AES_BLOCK_SIZE); 4103a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 4113a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania if (method == "SAMPLE-AES") { 4123a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania mSampleAesKeyItemChanged = true; 4133a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 4143a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania sp<ABuffer> keyDataBuffer = ABuffer::CreateAsCopy(mKeyData, sizeof(mKeyData)); 4153a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania sp<ABuffer> initVecBuffer = ABuffer::CreateAsCopy(mAESInitVec, sizeof(mAESInitVec)); 4163a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 4173a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania // always allocating a new one rather than updating the old message 4183a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania // lower layer might still have a reference to the old message 4193a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania mSampleAesKeyItem = new AMessage(); 4203a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania mSampleAesKeyItem->setBuffer("keyData", keyDataBuffer); 4213a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania mSampleAesKeyItem->setBuffer("initVec", initVecBuffer); 4223a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 4233a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania ALOGV("decryptBuffer: New SampleAesKeyItem: Key: %s IV: %s", 4243a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania HlsSampleDecryptor::aesBlockToStr(mKeyData).c_str(), 4253a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania HlsSampleDecryptor::aesBlockToStr(mAESInitVec).c_str()); 4263a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania } // SAMPLE-AES 4273a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania } // newSampleAesKeyItem 4283a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania } // first 4293a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 4303a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania if (method == "SAMPLE-AES") { 4313a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania ALOGV("decryptBuffer: skipping full-seg decrypt for SAMPLE-AES"); 4323a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania return OK; 4333a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania } 4343a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 4353a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 4363a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania AES_KEY aes_key; 4373a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania if (AES_set_decrypt_key(key->data(), 128, &aes_key) != 0) { 4383a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania ALOGE("failed to set AES decryption key."); 4393a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania return UNKNOWN_ERROR; 4403a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania } 4413a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 4423a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania size_t n = buffer->size(); 4433a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania if (!n) { 4443a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania return OK; 4453a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania } 4463a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 4473a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania if (n < 16 || n % 16) { 4483a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania ALOGE("not enough or trailing bytes (%zu) in encrypted buffer", n); 4493a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania return ERROR_MALFORMED; 45014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 45114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 45214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber AES_cbc_encrypt( 45314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber buffer->data(), buffer->data(), buffer->size(), 454ebe130923fb1a5b8dda4b3ee215593edcd804f0dRobert Shih &aes_key, mAESInitVec, AES_DECRYPT); 45514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 456ebe130923fb1a5b8dda4b3ee215593edcd804f0dRobert Shih return OK; 457ebe130923fb1a5b8dda4b3ee215593edcd804f0dRobert Shih} 45814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 459ebe130923fb1a5b8dda4b3ee215593edcd804f0dRobert Shihstatus_t PlaylistFetcher::checkDecryptPadding(const sp<ABuffer> &buffer) { 460ebe130923fb1a5b8dda4b3ee215593edcd804f0dRobert Shih AString method; 461ebe130923fb1a5b8dda4b3ee215593edcd804f0dRobert Shih CHECK(buffer->meta()->findString("cipher-method", &method)); 4623a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania if (method == "NONE" || method == "SAMPLE-AES") { 463ebe130923fb1a5b8dda4b3ee215593edcd804f0dRobert Shih return OK; 464ebe130923fb1a5b8dda4b3ee215593edcd804f0dRobert Shih } 46514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 466ebe130923fb1a5b8dda4b3ee215593edcd804f0dRobert Shih uint8_t padding = 0; 467ebe130923fb1a5b8dda4b3ee215593edcd804f0dRobert Shih if (buffer->size() > 0) { 468ebe130923fb1a5b8dda4b3ee215593edcd804f0dRobert Shih padding = buffer->data()[buffer->size() - 1]; 46914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 47014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 471ebe130923fb1a5b8dda4b3ee215593edcd804f0dRobert Shih if (padding > 16) { 472ebe130923fb1a5b8dda4b3ee215593edcd804f0dRobert Shih return ERROR_MALFORMED; 473ebe130923fb1a5b8dda4b3ee215593edcd804f0dRobert Shih } 47414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 475ebe130923fb1a5b8dda4b3ee215593edcd804f0dRobert Shih for (size_t i = buffer->size() - padding; i < padding; i++) { 476ebe130923fb1a5b8dda4b3ee215593edcd804f0dRobert Shih if (buffer->data()[i] != padding) { 477ebe130923fb1a5b8dda4b3ee215593edcd804f0dRobert Shih return ERROR_MALFORMED; 478ebe130923fb1a5b8dda4b3ee215593edcd804f0dRobert Shih } 479ebe130923fb1a5b8dda4b3ee215593edcd804f0dRobert Shih } 48014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 481ebe130923fb1a5b8dda4b3ee215593edcd804f0dRobert Shih buffer->setRange(buffer->offset(), buffer->size() - padding); 48214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return OK; 48314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 48414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 485e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnarvoid PlaylistFetcher::postMonitorQueue(int64_t delayUs, int64_t minDelayUs) { 486e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar int64_t maxDelayUs = delayUsToRefreshPlaylist(); 487e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar if (maxDelayUs < minDelayUs) { 488e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar maxDelayUs = minDelayUs; 489e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar } 490e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar if (delayUs > maxDelayUs) { 49125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang FLOGV("Need to refresh playlist in %lld", (long long)maxDelayUs); 492e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar delayUs = maxDelayUs; 493e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar } 4941d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> msg = new AMessage(kWhatMonitorQueue, this); 49514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber msg->setInt32("generation", mMonitorQueueGeneration); 49614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber msg->post(delayUs); 49714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 49814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 49914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid PlaylistFetcher::cancelMonitorQueue() { 50014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ++mMonitorQueueGeneration; 50114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 50214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 5035abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhangvoid PlaylistFetcher::setStoppingThreshold(float thresholdRatio, bool disconnect) { 5045abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang { 5055abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang AutoMutex _l(mThresholdLock); 5065abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang mThresholdRatio = thresholdRatio; 5075abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } 5085abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang if (disconnect) { 5095abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang mHTTPDownloader->disconnect(); 5105abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } 5115abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang} 5125abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 5135abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhangvoid PlaylistFetcher::resetStoppingThreshold(bool disconnect) { 5145abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang { 5155abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang AutoMutex _l(mThresholdLock); 5165abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang mThresholdRatio = -1.0f; 5175abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } 5185abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang if (disconnect) { 5195abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang mHTTPDownloader->disconnect(); 5205abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } else { 5215abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // allow reconnect 5225abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang mHTTPDownloader->reconnect(); 523a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 5245abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang} 5255abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 5265abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhangfloat PlaylistFetcher::getStoppingThreshold() { 5275abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang AutoMutex _l(mThresholdLock); 5285abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang return mThresholdRatio; 529c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang} 530c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang 53114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid PlaylistFetcher::startAsync( 53214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber const sp<AnotherPacketSource> &audioSource, 53314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber const sp<AnotherPacketSource> &videoSource, 53414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber const sp<AnotherPacketSource> &subtitleSource, 5350852843d304006e3ab333081fddda13b07193de8Robert Shih const sp<AnotherPacketSource> &metadataSource, 5361543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih int64_t startTimeUs, 537309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih int64_t segmentStartTimeUs, 538309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih int32_t startDiscontinuitySeq, 539a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang LiveSession::SeekMode seekMode) { 5401d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> msg = new AMessage(kWhatStart, this); 54114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 54214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber uint32_t streamTypeMask = 0ul; 54314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 54414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (audioSource != NULL) { 54514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber msg->setPointer("audioSource", audioSource.get()); 54614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber streamTypeMask |= LiveSession::STREAMTYPE_AUDIO; 54714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 54814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 54914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (videoSource != NULL) { 55014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber msg->setPointer("videoSource", videoSource.get()); 55114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber streamTypeMask |= LiveSession::STREAMTYPE_VIDEO; 55214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 55314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 55414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (subtitleSource != NULL) { 55514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber msg->setPointer("subtitleSource", subtitleSource.get()); 55614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber streamTypeMask |= LiveSession::STREAMTYPE_SUBTITLES; 55714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 55814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 5590852843d304006e3ab333081fddda13b07193de8Robert Shih if (metadataSource != NULL) { 5600852843d304006e3ab333081fddda13b07193de8Robert Shih msg->setPointer("metadataSource", metadataSource.get()); 5610852843d304006e3ab333081fddda13b07193de8Robert Shih // metadataSource does not affect streamTypeMask. 5620852843d304006e3ab333081fddda13b07193de8Robert Shih } 5630852843d304006e3ab333081fddda13b07193de8Robert Shih 56414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber msg->setInt32("streamTypeMask", streamTypeMask); 56514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber msg->setInt64("startTimeUs", startTimeUs); 566309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih msg->setInt64("segmentStartTimeUs", segmentStartTimeUs); 567309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih msg->setInt32("startDiscontinuitySeq", startDiscontinuitySeq); 568a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang msg->setInt32("seekMode", seekMode); 56914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber msg->post(); 57014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 57114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 5725ef659e010e90175eb5282d9642a02f6105189bfChong Zhang/* 5735ef659e010e90175eb5282d9642a02f6105189bfChong Zhang * pauseAsync 5745ef659e010e90175eb5282d9642a02f6105189bfChong Zhang * 5755ef659e010e90175eb5282d9642a02f6105189bfChong Zhang * threshold: 0.0f - pause after current fetch block (default 47Kbytes) 5765ef659e010e90175eb5282d9642a02f6105189bfChong Zhang * -1.0f - pause after finishing current segment 5775ef659e010e90175eb5282d9642a02f6105189bfChong Zhang * 0.0~1.0f - pause if remaining of current segment exceeds threshold 5785ef659e010e90175eb5282d9642a02f6105189bfChong Zhang */ 5795abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhangvoid PlaylistFetcher::pauseAsync( 5805abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang float thresholdRatio, bool disconnect) { 5815abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang setStoppingThreshold(thresholdRatio, disconnect); 5825abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 5831d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar (new AMessage(kWhatPause, this))->post(); 58414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 58514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 586309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shihvoid PlaylistFetcher::stopAsync(bool clear) { 5875abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang setStoppingThreshold(0.0f, true /* disconncect */); 588c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang 5891d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> msg = new AMessage(kWhatStop, this); 590309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih msg->setInt32("clear", clear); 5915ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih msg->post(); 59214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 59314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 5941543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shihvoid PlaylistFetcher::resumeUntilAsync(const sp<AMessage> ¶ms) { 59525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang FLOGV("resumeUntilAsync: params=%s", params->debugString().c_str()); 59625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 5971d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar AMessage* msg = new AMessage(kWhatResumeUntil, this); 5981543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih msg->setMessage("params", params); 5991543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih msg->post(); 6001543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih} 6011543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 6025abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhangvoid PlaylistFetcher::fetchPlaylistAsync() { 6035abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang (new AMessage(kWhatFetchPlaylist, this))->post(); 6045abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang} 6055abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 60614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid PlaylistFetcher::onMessageReceived(const sp<AMessage> &msg) { 60714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber switch (msg->what()) { 60814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case kWhatStart: 60914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 61014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber status_t err = onStart(msg); 61114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 61214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AMessage> notify = mNotify->dup(); 61314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->setInt32("what", kWhatStarted); 61414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->setInt32("err", err); 61514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->post(); 61614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 61714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 61814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 61914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case kWhatPause: 62014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 62114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber onPause(); 62214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 62314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AMessage> notify = mNotify->dup(); 62414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->setInt32("what", kWhatPaused); 625a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang notify->setInt32("seekMode", 626a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mDownloadState->hasSavedState() 627a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang ? LiveSession::kSeekModeNextSample 628a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang : LiveSession::kSeekModeNextSegment); 62914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->post(); 63014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 63114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 63214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 63314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case kWhatStop: 63414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 6355ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih onStop(msg); 63614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 63714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AMessage> notify = mNotify->dup(); 63814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->setInt32("what", kWhatStopped); 63914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->post(); 64014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 64114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 64214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 6435abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang case kWhatFetchPlaylist: 6445abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang { 6455abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang bool unchanged; 6465abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang sp<M3UParser> playlist = mHTTPDownloader->fetchPlaylist( 6475abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang mURI.c_str(), NULL /* curPlaylistHash */, &unchanged); 6485abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 6495abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang sp<AMessage> notify = mNotify->dup(); 6505abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang notify->setInt32("what", kWhatPlaylistFetched); 6515abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang notify->setObject("playlist", playlist); 6525abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang notify->post(); 6535abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang break; 6545abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } 6555abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 65614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case kWhatMonitorQueue: 6571543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih case kWhatDownloadNext: 65814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 65914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int32_t generation; 66014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->findInt32("generation", &generation)); 66114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 66214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (generation != mMonitorQueueGeneration) { 66314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // Stale event 66414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 66514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 66614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 6671543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih if (msg->what() == kWhatMonitorQueue) { 6681543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih onMonitorQueue(); 6691543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } else { 6701543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih onDownloadNext(); 6711543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 6721543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih break; 6731543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 6741543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 6751543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih case kWhatResumeUntil: 6761543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih { 6771543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih onResumeUntil(msg); 67814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 67914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 68014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 68114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber default: 68214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber TRESPASS(); 68314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 68414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 68514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 68614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t PlaylistFetcher::onStart(const sp<AMessage> &msg) { 68714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mPacketSources.clear(); 688c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang mStopParams.clear(); 689c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang mStartTimeUsNotify = mNotify->dup(); 690c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang mStartTimeUsNotify->setInt32("what", kWhatStartedAt); 691a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mStartTimeUsNotify->setString("uri", mURI); 69214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 69314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber uint32_t streamTypeMask; 69414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->findInt32("streamTypeMask", (int32_t *)&streamTypeMask)); 69514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 69614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int64_t startTimeUs; 697309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih int64_t segmentStartTimeUs; 698309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih int32_t startDiscontinuitySeq; 699a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang int32_t seekMode; 70014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->findInt64("startTimeUs", &startTimeUs)); 701309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih CHECK(msg->findInt64("segmentStartTimeUs", &segmentStartTimeUs)); 702309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih CHECK(msg->findInt32("startDiscontinuitySeq", &startDiscontinuitySeq)); 703a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang CHECK(msg->findInt32("seekMode", &seekMode)); 70414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 70514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (streamTypeMask & LiveSession::STREAMTYPE_AUDIO) { 70614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber void *ptr; 70714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->findPointer("audioSource", &ptr)); 70814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 70914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mPacketSources.add( 71014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber LiveSession::STREAMTYPE_AUDIO, 71114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber static_cast<AnotherPacketSource *>(ptr)); 71214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 71314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 71414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (streamTypeMask & LiveSession::STREAMTYPE_VIDEO) { 71514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber void *ptr; 71614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->findPointer("videoSource", &ptr)); 71714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 71814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mPacketSources.add( 71914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber LiveSession::STREAMTYPE_VIDEO, 72014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber static_cast<AnotherPacketSource *>(ptr)); 72114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 72214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 72314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (streamTypeMask & LiveSession::STREAMTYPE_SUBTITLES) { 72414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber void *ptr; 72514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(msg->findPointer("subtitleSource", &ptr)); 72614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 72714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mPacketSources.add( 72814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber LiveSession::STREAMTYPE_SUBTITLES, 72914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber static_cast<AnotherPacketSource *>(ptr)); 73014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 73114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 7320852843d304006e3ab333081fddda13b07193de8Robert Shih void *ptr; 7330852843d304006e3ab333081fddda13b07193de8Robert Shih // metadataSource is not part of streamTypeMask 7340852843d304006e3ab333081fddda13b07193de8Robert Shih if ((streamTypeMask & (LiveSession::STREAMTYPE_AUDIO | LiveSession::STREAMTYPE_VIDEO)) 7350852843d304006e3ab333081fddda13b07193de8Robert Shih && msg->findPointer("metadataSource", &ptr)) { 7360852843d304006e3ab333081fddda13b07193de8Robert Shih mPacketSources.add( 7370852843d304006e3ab333081fddda13b07193de8Robert Shih LiveSession::STREAMTYPE_METADATA, 7380852843d304006e3ab333081fddda13b07193de8Robert Shih static_cast<AnotherPacketSource *>(ptr)); 7390852843d304006e3ab333081fddda13b07193de8Robert Shih } 7400852843d304006e3ab333081fddda13b07193de8Robert Shih 74114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mStreamTypeMask = streamTypeMask; 742309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 743309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mSegmentStartTimeUs = segmentStartTimeUs; 7447c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 7457c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (startDiscontinuitySeq >= 0) { 7467c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mDiscontinuitySeq = startDiscontinuitySeq; 7477c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 74814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 749c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang mRefreshState = INITIAL_MINIMUM_RELOAD_DELAY; 750a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mSeekMode = (LiveSession::SeekMode) seekMode; 751c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang 7527c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (startTimeUs >= 0 || mSeekMode == LiveSession::kSeekModeNextSample) { 7537c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mStartup = true; 7547c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mIDRFound = false; 7557c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mVideoBuffer->clear(); 7567c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 7577c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 7580f9a3cf9962b6859cfee9d4bf4676b5aafca79cbRobert Shih if (startTimeUs >= 0) { 7590f9a3cf9962b6859cfee9d4bf4676b5aafca79cbRobert Shih mStartTimeUs = startTimeUs; 760c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang mFirstPTSValid = false; 76114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mSeqNumber = -1; 762c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang mTimeChangeSignaled = false; 763a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mDownloadState->resetState(); 7641543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 7651543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 76614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber postMonitorQueue(); 76714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 76814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return OK; 76914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 77014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 77114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid PlaylistFetcher::onPause() { 77214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber cancelMonitorQueue(); 773c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang mLastDiscontinuitySeq = mDiscontinuitySeq; 774c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang 7755abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang resetStoppingThreshold(false /* disconnect */); 7761543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih} 7771543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 7785ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shihvoid PlaylistFetcher::onStop(const sp<AMessage> &msg) { 7791543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih cancelMonitorQueue(); 78014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 781309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih int32_t clear; 782309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih CHECK(msg->findInt32("clear", &clear)); 783309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (clear) { 7845ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih for (size_t i = 0; i < mPacketSources.size(); i++) { 7855ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih sp<AnotherPacketSource> packetSource = mPacketSources.valueAt(i); 7865ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih packetSource->clear(); 7875ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih } 7885ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih } 7895ce50c1931e1e3d8f113394bbe2c9f99354f4c5fRobert Shih 790a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mDownloadState->resetState(); 79114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mPacketSources.clear(); 79214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mStreamTypeMask = 0; 793c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang 7945abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang resetStoppingThreshold(true /* disconnect */); 79514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 79614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 7971543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih// Resume until we have reached the boundary timestamps listed in `msg`; when 7981543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih// the remaining time is too short (within a resume threshold) stop immediately 7991543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih// instead. 8001543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shihstatus_t PlaylistFetcher::onResumeUntil(const sp<AMessage> &msg) { 8011543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih sp<AMessage> params; 8021543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih CHECK(msg->findMessage("params", ¶ms)); 8031543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 8041543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih mStopParams = params; 805964adb17885185808398507d2de88665fe193ee2Chong Zhang onDownloadNext(); 8061543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 8071543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih return OK; 80814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 80914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 8107c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid PlaylistFetcher::notifyStopReached() { 8117c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AMessage> notify = mNotify->dup(); 8127c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->setInt32("what", kWhatStopReached); 8137c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notify->post(); 8147c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang} 8157c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 81614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid PlaylistFetcher::notifyError(status_t err) { 81714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AMessage> notify = mNotify->dup(); 81814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->setInt32("what", kWhatError); 81914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->setInt32("err", err); 82014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber notify->post(); 82114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 82214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 82314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid PlaylistFetcher::queueDiscontinuity( 82414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ATSParser::DiscontinuityType type, const sp<AMessage> &extra) { 82514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber for (size_t i = 0; i < mPacketSources.size(); ++i) { 826632740c58119a132ce19f6d498e39c5c3773971aChong Zhang // do not discard buffer upon #EXT-X-DISCONTINUITY tag 827632740c58119a132ce19f6d498e39c5c3773971aChong Zhang // (seek will discard buffer by abandoning old fetchers) 828632740c58119a132ce19f6d498e39c5c3773971aChong Zhang mPacketSources.valueAt(i)->queueDiscontinuity( 829632740c58119a132ce19f6d498e39c5c3773971aChong Zhang type, extra, false /* discard */); 83014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 83114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 83214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 83314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid PlaylistFetcher::onMonitorQueue() { 8347c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // in the middle of an unfinished download, delay 8357c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // playlist refresh as it'll change seq numbers 8367c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (!mDownloadState->hasSavedState()) { 8377c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang refreshPlaylist(); 8387c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 839e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar 840e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar int64_t targetDurationUs = kMinBufferedDurationUs; 841e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar if (mPlaylist != NULL) { 842978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang targetDurationUs = mPlaylist->getTargetDuration(); 843e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar } 844e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar 845e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar int64_t bufferedDurationUs = 0ll; 846538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang status_t finalResult = OK; 84714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (mStreamTypeMask == LiveSession::STREAMTYPE_SUBTITLES) { 84814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AnotherPacketSource> packetSource = 84914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mPacketSources.valueFor(LiveSession::STREAMTYPE_SUBTITLES); 85014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 851e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar bufferedDurationUs = 852dcb89b3b505522efde173c105a851c412f947178Chong Zhang packetSource->getBufferedDurationUs(&finalResult); 85314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else { 854538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang // Use min stream duration, but ignore streams that never have any packet 855538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang // enqueued to prevent us from waiting on a non-existent stream; 856538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang // when we cannot make out from the manifest what streams are included in 857538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang // a playlist we might assume extra streams. 858538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang bufferedDurationUs = -1ll; 85914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber for (size_t i = 0; i < mPacketSources.size(); ++i) { 860538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang if ((mStreamTypeMask & mPacketSources.keyAt(i)) == 0 861538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang || mPacketSources[i]->getLatestEnqueuedMeta() == NULL) { 86214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber continue; 86314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 86414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 865e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar int64_t bufferedStreamDurationUs = 86614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mPacketSources.valueAt(i)->getBufferedDurationUs(&finalResult); 86725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 86825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang FSLOGV(mPacketSources.keyAt(i), "buffered %lld", (long long)bufferedStreamDurationUs); 86925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 870538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang if (bufferedDurationUs == -1ll 871538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang || bufferedStreamDurationUs < bufferedDurationUs) { 872e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar bufferedDurationUs = bufferedStreamDurationUs; 87314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 87414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 875538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang if (bufferedDurationUs == -1ll) { 876538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang bufferedDurationUs = 0ll; 877538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang } 87814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 87914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 880538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang if (finalResult == OK && bufferedDurationUs < kMinBufferedDurationUs) { 88125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang FLOGV("monitoring, buffered=%lld < %lld", 88225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang (long long)bufferedDurationUs, (long long)kMinBufferedDurationUs); 88325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 8841543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih // delay the next download slightly; hopefully this gives other concurrent fetchers 8851543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih // a better chance to run. 8861543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih // onDownloadNext(); 8871d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> msg = new AMessage(kWhatDownloadNext, this); 8881543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih msg->setInt32("generation", mMonitorQueueGeneration); 8891543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih msg->post(1000l); 89014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else { 891538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang // We'd like to maintain buffering above durationToBufferUs, so try 892538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang // again when buffer just about to go below durationToBufferUs 893538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang // (or after targetDurationUs / 2, whichever is smaller). 894538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang int64_t delayUs = bufferedDurationUs - kMinBufferedDurationUs + 1000000ll; 895538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang if (delayUs > targetDurationUs / 2) { 896538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang delayUs = targetDurationUs / 2; 897538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang } 89825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 89925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang FLOGV("pausing for %lld, buffered=%lld > %lld", 90025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang (long long)delayUs, 90125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang (long long)bufferedDurationUs, 90225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang (long long)kMinBufferedDurationUs); 90325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 904538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang postMonitorQueue(delayUs); 90514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 90614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 90714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 908e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnarstatus_t PlaylistFetcher::refreshPlaylist() { 909e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar if (delayUsToRefreshPlaylist() <= 0) { 91014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber bool unchanged; 9115abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang sp<M3UParser> playlist = mHTTPDownloader->fetchPlaylist( 91214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mURI.c_str(), mPlaylistHash, &unchanged); 91314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 91414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (playlist == NULL) { 91514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (unchanged) { 91614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // We succeeded in fetching the playlist, but it was 91714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // unchanged from the last time we tried. 91814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 91914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (mRefreshState != THIRD_UNCHANGED_RELOAD_ATTEMPT) { 92014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mRefreshState = (RefreshState)(mRefreshState + 1); 92114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 92214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else { 923daad5b2f4a6bb46a7911661e398278d6a80d7093Robert Shih ALOGE("failed to load playlist at url '%s'", uriDebugString(mURI).c_str()); 924e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar return ERROR_IO; 92514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 92614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else { 92714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mRefreshState = INITIAL_MINIMUM_RELOAD_DELAY; 92814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mPlaylist = playlist; 92914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 93014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (mPlaylist->isComplete() || mPlaylist->isEvent()) { 93114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber updateDuration(); 93214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 9337c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // Notify LiveSession to use target-duration based buffering level 9347c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // for up/down switch. Default LiveSession::kUpSwitchMark may not 9357c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // be reachable for live streams, as our max buffering amount is 9367c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // limited to 3 segments. 9377c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (!mPlaylist->isComplete()) { 9387c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang updateTargetDuration(); 9397c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 940978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mPlaylistTimeUs = ALooper::GetNowUs(); 94114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 94214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 94314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mLastPlaylistFetchTimeUs = ALooper::GetNowUs(); 94414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 945e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar return OK; 946e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar} 947e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar 94843ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih// static 94943ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shihbool PlaylistFetcher::bufferStartsWithTsSyncByte(const sp<ABuffer>& buffer) { 95043ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih return buffer->size() > 0 && buffer->data()[0] == 0x47; 95143ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih} 95243ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih 9537c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangbool PlaylistFetcher::shouldPauseDownload() { 954a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (mStreamTypeMask == LiveSession::STREAMTYPE_SUBTITLES) { 955a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // doesn't apply to subtitles 956a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang return false; 957a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 958a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 959a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // Calculate threshold to abort current download 9605abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang float thresholdRatio = getStoppingThreshold(); 961a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 9625abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang if (thresholdRatio < 0.0f) { 963a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // never abort 964a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang return false; 9655abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } else if (thresholdRatio == 0.0f) { 966a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // immediately abort 967a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang return true; 968a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 969a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 970a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // now we have a positive thresholdUs, abort if remaining 971a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // portion to download is over that threshold. 972a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (mSegmentFirstPTS < 0) { 973a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // this means we haven't even find the first access unit, 974a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // abort now as we must be very far away from the end. 975a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang return true; 976a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 977a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang int64_t lastEnqueueUs = mSegmentFirstPTS; 978a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang for (size_t i = 0; i < mPacketSources.size(); ++i) { 979a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if ((mStreamTypeMask & mPacketSources.keyAt(i)) == 0) { 980a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang continue; 981a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 982a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang sp<AMessage> meta = mPacketSources[i]->getLatestEnqueuedMeta(); 983a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang int32_t type; 984a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (meta == NULL || meta->findInt32("discontinuity", &type)) { 985a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang continue; 986a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 987a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang int64_t tmpUs; 988a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang CHECK(meta->findInt64("timeUs", &tmpUs)); 989a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (tmpUs > lastEnqueueUs) { 990a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang lastEnqueueUs = tmpUs; 991a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 992a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 993a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang lastEnqueueUs -= mSegmentFirstPTS; 99425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 9955abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang int64_t targetDurationUs = mPlaylist->getTargetDuration(); 9965abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang int64_t thresholdUs = thresholdRatio * targetDurationUs; 9975abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 99825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang FLOGV("%spausing now, thresholdUs %lld, remaining %lld", 99925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang targetDurationUs - lastEnqueueUs > thresholdUs ? "" : "not ", 100025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang (long long)thresholdUs, 100125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang (long long)(targetDurationUs - lastEnqueueUs)); 100225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang 1003a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (targetDurationUs - lastEnqueueUs > thresholdUs) { 1004a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang return true; 1005a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 1006a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang return false; 1007a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang} 1008a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 100972433b083ccfa3ab55374305b1c2960982ac3e09Oscar Rydhévoid PlaylistFetcher::initSeqNumberForLiveStream( 101072433b083ccfa3ab55374305b1c2960982ac3e09Oscar Rydhé int32_t &firstSeqNumberInPlaylist, 101172433b083ccfa3ab55374305b1c2960982ac3e09Oscar Rydhé int32_t &lastSeqNumberInPlaylist) { 101272433b083ccfa3ab55374305b1c2960982ac3e09Oscar Rydhé // start at least 3 target durations from the end. 101372433b083ccfa3ab55374305b1c2960982ac3e09Oscar Rydhé int64_t timeFromEnd = 0; 101472433b083ccfa3ab55374305b1c2960982ac3e09Oscar Rydhé size_t index = mPlaylist->size(); 101572433b083ccfa3ab55374305b1c2960982ac3e09Oscar Rydhé sp<AMessage> itemMeta; 101672433b083ccfa3ab55374305b1c2960982ac3e09Oscar Rydhé int64_t itemDurationUs; 101772433b083ccfa3ab55374305b1c2960982ac3e09Oscar Rydhé int32_t targetDuration; 101872433b083ccfa3ab55374305b1c2960982ac3e09Oscar Rydhé if (mPlaylist->meta()->findInt32("target-duration", &targetDuration)) { 101972433b083ccfa3ab55374305b1c2960982ac3e09Oscar Rydhé do { 102072433b083ccfa3ab55374305b1c2960982ac3e09Oscar Rydhé --index; 102172433b083ccfa3ab55374305b1c2960982ac3e09Oscar Rydhé if (!mPlaylist->itemAt(index, NULL /* uri */, &itemMeta) 102272433b083ccfa3ab55374305b1c2960982ac3e09Oscar Rydhé || !itemMeta->findInt64("durationUs", &itemDurationUs)) { 102372433b083ccfa3ab55374305b1c2960982ac3e09Oscar Rydhé ALOGW("item or itemDurationUs missing"); 102472433b083ccfa3ab55374305b1c2960982ac3e09Oscar Rydhé mSeqNumber = lastSeqNumberInPlaylist - 3; 102572433b083ccfa3ab55374305b1c2960982ac3e09Oscar Rydhé break; 102672433b083ccfa3ab55374305b1c2960982ac3e09Oscar Rydhé } 102772433b083ccfa3ab55374305b1c2960982ac3e09Oscar Rydhé 102872433b083ccfa3ab55374305b1c2960982ac3e09Oscar Rydhé timeFromEnd += itemDurationUs; 102972433b083ccfa3ab55374305b1c2960982ac3e09Oscar Rydhé mSeqNumber = firstSeqNumberInPlaylist + index; 103072433b083ccfa3ab55374305b1c2960982ac3e09Oscar Rydhé } while (timeFromEnd < targetDuration * 3E6 && index > 0); 103172433b083ccfa3ab55374305b1c2960982ac3e09Oscar Rydhé } else { 103272433b083ccfa3ab55374305b1c2960982ac3e09Oscar Rydhé ALOGW("target-duration missing"); 103372433b083ccfa3ab55374305b1c2960982ac3e09Oscar Rydhé mSeqNumber = lastSeqNumberInPlaylist - 3; 103472433b083ccfa3ab55374305b1c2960982ac3e09Oscar Rydhé } 103572433b083ccfa3ab55374305b1c2960982ac3e09Oscar Rydhé 103672433b083ccfa3ab55374305b1c2960982ac3e09Oscar Rydhé if (mSeqNumber < firstSeqNumberInPlaylist) { 103772433b083ccfa3ab55374305b1c2960982ac3e09Oscar Rydhé mSeqNumber = firstSeqNumberInPlaylist; 103872433b083ccfa3ab55374305b1c2960982ac3e09Oscar Rydhé } 103972433b083ccfa3ab55374305b1c2960982ac3e09Oscar Rydhé} 104072433b083ccfa3ab55374305b1c2960982ac3e09Oscar Rydhé 1041a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhangbool PlaylistFetcher::initDownloadState( 1042a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang AString &uri, 1043a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang sp<AMessage> &itemMeta, 1044a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang int32_t &firstSeqNumberInPlaylist, 1045a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang int32_t &lastSeqNumberInPlaylist) { 1046daad5b2f4a6bb46a7911661e398278d6a80d7093Robert Shih status_t err = refreshPlaylist(); 1047a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang firstSeqNumberInPlaylist = 0; 1048a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang lastSeqNumberInPlaylist = 0; 1049632740c58119a132ce19f6d498e39c5c3773971aChong Zhang bool discontinuity = false; 105014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 1051daad5b2f4a6bb46a7911661e398278d6a80d7093Robert Shih if (mPlaylist != NULL) { 1052978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mPlaylist->getSeqNumberRange( 1053978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang &firstSeqNumberInPlaylist, &lastSeqNumberInPlaylist); 105414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 1055daad5b2f4a6bb46a7911661e398278d6a80d7093Robert Shih if (mDiscontinuitySeq < 0) { 1056daad5b2f4a6bb46a7911661e398278d6a80d7093Robert Shih mDiscontinuitySeq = mPlaylist->getDiscontinuitySeq(); 1057daad5b2f4a6bb46a7911661e398278d6a80d7093Robert Shih } 1058309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 1059309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 1060a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mSegmentFirstPTS = -1ll; 1061a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1062daad5b2f4a6bb46a7911661e398278d6a80d7093Robert Shih if (mPlaylist != NULL && mSeqNumber < 0) { 106314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK_GE(mStartTimeUs, 0ll); 106414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 1065309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (mSegmentStartTimeUs < 0) { 1066309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (!mPlaylist->isComplete() && !mPlaylist->isEvent()) { 106772433b083ccfa3ab55374305b1c2960982ac3e09Oscar Rydhé // this is a live session 106872433b083ccfa3ab55374305b1c2960982ac3e09Oscar Rydhé initSeqNumberForLiveStream(firstSeqNumberInPlaylist, lastSeqNumberInPlaylist); 1069309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } else { 1070afcc4fcbb3a094ec2221d6e523772e76894d1f00Robert Shih // When seeking mSegmentStartTimeUs is unavailable (< 0), we 1071afcc4fcbb3a094ec2221d6e523772e76894d1f00Robert Shih // use mStartTimeUs (client supplied timestamp) to determine both start segment 1072afcc4fcbb3a094ec2221d6e523772e76894d1f00Robert Shih // and relative position inside a segment 1073309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mSeqNumber = getSeqNumberForTime(mStartTimeUs); 1074309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mStartTimeUs -= getSegmentStartTimeUs(mSeqNumber); 1075309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 1076309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mStartTimeUsRelative = true; 107725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang FLOGV("Initial sequence number for time %lld is %d from (%d .. %d)", 107825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang (long long)mStartTimeUs, mSeqNumber, firstSeqNumberInPlaylist, 1079e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar lastSeqNumberInPlaylist); 108014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else { 1081afcc4fcbb3a094ec2221d6e523772e76894d1f00Robert Shih // When adapting or track switching, mSegmentStartTimeUs (relative 1082afcc4fcbb3a094ec2221d6e523772e76894d1f00Robert Shih // to media time 0) is used to determine the start segment; mStartTimeUs (absolute 1083afcc4fcbb3a094ec2221d6e523772e76894d1f00Robert Shih // timestamps coming from the media container) is used to determine the position 1084afcc4fcbb3a094ec2221d6e523772e76894d1f00Robert Shih // inside a segments. 1085d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (mStreamTypeMask != LiveSession::STREAMTYPE_SUBTITLES 1086d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang && mSeekMode != LiveSession::kSeekModeNextSample) { 1087309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih // avoid double fetch/decode 1088978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang // Use (mSegmentStartTimeUs + 1/2 * targetDurationUs) to search 1089978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang // for the starting segment in new variant. 1090978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang // If the two variants' segments are aligned, this gives the 1091978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang // next segment. If they're not aligned, this gives the segment 1092978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang // that overlaps no more than 1/2 * targetDurationUs. 1093978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mSeqNumber = getSeqNumberForTime(mSegmentStartTimeUs 1094978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang + mPlaylist->getTargetDuration() / 2); 1095978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } else { 1096978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mSeqNumber = getSeqNumberForTime(mSegmentStartTimeUs); 1097309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 1098309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih ssize_t minSeq = getSeqNumberForDiscontinuity(mDiscontinuitySeq); 1099309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (mSeqNumber < minSeq) { 1100309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mSeqNumber = minSeq; 1101309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 1102309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 110314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (mSeqNumber < firstSeqNumberInPlaylist) { 110414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mSeqNumber = firstSeqNumberInPlaylist; 110514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 1106309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 1107309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (mSeqNumber > lastSeqNumberInPlaylist) { 1108309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mSeqNumber = lastSeqNumberInPlaylist; 1109309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 111025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang FLOGV("Initial sequence number is %d from (%d .. %d)", 1111e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar mSeqNumber, firstSeqNumberInPlaylist, 1112e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar lastSeqNumberInPlaylist); 111314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 111414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 111514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 1116daad5b2f4a6bb46a7911661e398278d6a80d7093Robert Shih // if mPlaylist is NULL then err must be non-OK; but the other way around might not be true 111714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (mSeqNumber < firstSeqNumberInPlaylist 1118daad5b2f4a6bb46a7911661e398278d6a80d7093Robert Shih || mSeqNumber > lastSeqNumberInPlaylist 1119daad5b2f4a6bb46a7911661e398278d6a80d7093Robert Shih || err != OK) { 1120daad5b2f4a6bb46a7911661e398278d6a80d7093Robert Shih if ((err != OK || !mPlaylist->isComplete()) && mNumRetries < kMaxNumRetries) { 112114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ++mNumRetries; 112214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 1123daad5b2f4a6bb46a7911661e398278d6a80d7093Robert Shih if (mSeqNumber > lastSeqNumberInPlaylist || err != OK) { 1124daad5b2f4a6bb46a7911661e398278d6a80d7093Robert Shih // make sure we reach this retry logic on refresh failures 1125daad5b2f4a6bb46a7911661e398278d6a80d7093Robert Shih // by adding an err != OK clause to all enclosing if's. 1126daad5b2f4a6bb46a7911661e398278d6a80d7093Robert Shih 1127e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar // refresh in increasing fraction (1/2, 1/3, ...) of the 1128e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar // playlist's target duration or 3 seconds, whichever is less 1129daad5b2f4a6bb46a7911661e398278d6a80d7093Robert Shih int64_t delayUs = kMaxMonitorDelayUs; 1130978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (mPlaylist != NULL) { 1131978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang delayUs = mPlaylist->size() * mPlaylist->getTargetDuration() 1132978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang / (1 + mNumRetries); 1133daad5b2f4a6bb46a7911661e398278d6a80d7093Robert Shih } 1134e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar if (delayUs > kMaxMonitorDelayUs) { 1135e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar delayUs = kMaxMonitorDelayUs; 1136e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar } 113725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang FLOGV("sequence number high: %d from (%d .. %d), " 113825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang "monitor in %lld (retry=%d)", 1139e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar mSeqNumber, firstSeqNumberInPlaylist, 114025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang lastSeqNumberInPlaylist, (long long)delayUs, mNumRetries); 1141e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar postMonitorQueue(delayUs); 1142a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang return false; 114314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 114414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 1145daad5b2f4a6bb46a7911661e398278d6a80d7093Robert Shih if (err != OK) { 1146daad5b2f4a6bb46a7911661e398278d6a80d7093Robert Shih notifyError(err); 1147a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang return false; 1148daad5b2f4a6bb46a7911661e398278d6a80d7093Robert Shih } 1149daad5b2f4a6bb46a7911661e398278d6a80d7093Robert Shih 1150daad5b2f4a6bb46a7911661e398278d6a80d7093Robert Shih // we've missed the boat, let's start 3 segments prior to the latest sequence 115114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // number available and signal a discontinuity. 115214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 1153e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar ALOGI("We've missed the boat, restarting playback." 1154e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar " mStartup=%d, was looking for %d in %d-%d", 1155e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar mStartup, mSeqNumber, firstSeqNumberInPlaylist, 1156e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar lastSeqNumberInPlaylist); 115795697aecd644ffcfbe7fe828e9e42bfab71b75a5Robert Shih if (mStopParams != NULL) { 115895697aecd644ffcfbe7fe828e9e42bfab71b75a5Robert Shih // we should have kept on fetching until we hit the boundaries in mStopParams, 115995697aecd644ffcfbe7fe828e9e42bfab71b75a5Robert Shih // but since the segments we are supposed to fetch have already rolled off 116095697aecd644ffcfbe7fe828e9e42bfab71b75a5Robert Shih // the playlist, i.e. we have already missed the boat, we inevitably have to 116195697aecd644ffcfbe7fe828e9e42bfab71b75a5Robert Shih // skip. 11627c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notifyStopReached(); 1163a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang return false; 116495697aecd644ffcfbe7fe828e9e42bfab71b75a5Robert Shih } 1165e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar mSeqNumber = lastSeqNumberInPlaylist - 3; 1166e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar if (mSeqNumber < firstSeqNumberInPlaylist) { 1167e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar mSeqNumber = firstSeqNumberInPlaylist; 1168e175e5ec1636fc638465187f3d5c6166d92388edLajos Molnar } 1169632740c58119a132ce19f6d498e39c5c3773971aChong Zhang discontinuity = true; 117014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 117114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // fall through 117214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else { 11737c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (mPlaylist != NULL) { 11744f601e8c9a9203aab38e0c6ac61b9fa65effcd33Robert Shih if (mSeqNumber >= firstSeqNumberInPlaylist + (int32_t)mPlaylist->size() 11754f601e8c9a9203aab38e0c6ac61b9fa65effcd33Robert Shih && !mPlaylist->isComplete()) { 11764f601e8c9a9203aab38e0c6ac61b9fa65effcd33Robert Shih // Live playlists 11774f601e8c9a9203aab38e0c6ac61b9fa65effcd33Robert Shih ALOGW("sequence number %d not yet available", mSeqNumber); 11784f601e8c9a9203aab38e0c6ac61b9fa65effcd33Robert Shih postMonitorQueue(delayUsToRefreshPlaylist()); 11794f601e8c9a9203aab38e0c6ac61b9fa65effcd33Robert Shih return false; 11804f601e8c9a9203aab38e0c6ac61b9fa65effcd33Robert Shih } 11817c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGE("Cannot find sequence number %d in playlist " 11827c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang "(contains %d - %d)", 11837c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mSeqNumber, firstSeqNumberInPlaylist, 11847c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang firstSeqNumberInPlaylist + (int32_t)mPlaylist->size() - 1); 11857c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 1186aabbdc7401ae24a4199f12a283985deb648673c0Robert Shih if (mTSParser != NULL) { 1187aabbdc7401ae24a4199f12a283985deb648673c0Robert Shih mTSParser->signalEOS(ERROR_END_OF_STREAM); 1188aabbdc7401ae24a4199f12a283985deb648673c0Robert Shih // Use an empty buffer; we don't have any new data, just want to extract 1189aabbdc7401ae24a4199f12a283985deb648673c0Robert Shih // potential new access units after flush. Reset mSeqNumber to 1190aabbdc7401ae24a4199f12a283985deb648673c0Robert Shih // lastSeqNumberInPlaylist such that we set the correct access unit 1191aabbdc7401ae24a4199f12a283985deb648673c0Robert Shih // properties in extractAndQueueAccessUnitsFromTs. 1192aabbdc7401ae24a4199f12a283985deb648673c0Robert Shih sp<ABuffer> buffer = new ABuffer(0); 1193aabbdc7401ae24a4199f12a283985deb648673c0Robert Shih mSeqNumber = lastSeqNumberInPlaylist; 1194aabbdc7401ae24a4199f12a283985deb648673c0Robert Shih extractAndQueueAccessUnitsFromTs(buffer); 1195aabbdc7401ae24a4199f12a283985deb648673c0Robert Shih } 11967c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notifyError(ERROR_END_OF_STREAM); 11977c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } else { 11987c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // It's possible that we were never able to download the playlist. 11997c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // In this case we should notify error, instead of EOS, as EOS during 12007c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // prepare means we succeeded in downloading everything. 12017c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGE("Failed to download playlist!"); 12027c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notifyError(ERROR_IO); 12037c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 120414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 1205a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang return false; 120614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 120714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 120814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 120914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mNumRetries = 0; 121014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 121114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(mPlaylist->itemAt( 121214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mSeqNumber - firstSeqNumberInPlaylist, 121314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber &uri, 121414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber &itemMeta)); 121514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 1216c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang CHECK(itemMeta->findInt32("discontinuity-sequence", &mDiscontinuitySeq)); 1217c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang 121814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int32_t val; 121914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (itemMeta->findInt32("discontinuity", &val) && val != 0) { 1220c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang discontinuity = true; 1221c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang } else if (mLastDiscontinuitySeq >= 0 1222c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang && mDiscontinuitySeq != mLastDiscontinuitySeq) { 1223c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // Seek jumped to a new discontinuity sequence. We need to signal 1224c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // a format change to decoder. Decoder needs to shutdown and be 1225c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // created again if seamless format change is unsupported. 122625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang FLOGV("saw discontinuity: mStartup %d, mLastDiscontinuitySeq %d, " 1227c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang "mDiscontinuitySeq %d, mStartTimeUs %lld", 122825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang mStartup, mLastDiscontinuitySeq, mDiscontinuitySeq, (long long)mStartTimeUs); 1229632740c58119a132ce19f6d498e39c5c3773971aChong Zhang discontinuity = true; 123014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 1231c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang mLastDiscontinuitySeq = -1; 123214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 123343ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih // decrypt a junk buffer to prefetch key; since a session uses only one http connection, 123443ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih // this avoids interleaved connections to the key and segment file. 123543ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih { 123643ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih sp<ABuffer> junk = new ABuffer(16); 123743ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih junk->setRange(0, 16); 123843ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih status_t err = decryptBuffer(mSeqNumber - firstSeqNumberInPlaylist, junk, 123943ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih true /* first */); 12405abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang if (err == ERROR_NOT_CONNECTED) { 12415abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang return false; 12425abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } else if (err != OK) { 124343ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih notifyError(err); 1244a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang return false; 124543ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih } 124614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 124714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 1248c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang if ((mStartup && !mTimeChangeSignaled) || discontinuity) { 1249c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // We need to signal a time discontinuity to ATSParser on the 1250c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // first segment after start, or on a discontinuity segment. 1251c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // Setting mNextPTSTimeUs informs extractAndQueueAccessUnitsXX() 1252c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // to send the time discontinuity. 1253c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang if (mPlaylist->isComplete() || mPlaylist->isEvent()) { 1254c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // If this was a live event this made no sense since 1255c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // we don't have access to all the segment before the current 1256c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // one. 1257c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang mNextPTSTimeUs = getSegmentStartTimeUs(mSeqNumber); 1258c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang } 1259c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang 1260c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // Setting mTimeChangeSignaled to true, so that if start time 1261c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // searching goes into 2nd segment (without a discontinuity), 1262c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // we don't reset time again. It causes corruption when pending 1263c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // data in ATSParser is cleared. 1264c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang mTimeChangeSignaled = true; 1265c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang } 1266c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang 1267c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang if (discontinuity) { 1268c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang ALOGI("queueing discontinuity (explicit=%d)", discontinuity); 1269c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang 1270c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // Signal a format discontinuity to ATSParser to clear partial data 1271c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // from previous streams. Not doing this causes bitstream corruption. 12727c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (mTSParser != NULL) { 1273a722375a32e9a0febc3770513647dc32bf88ccc0Robert Shih mTSParser.clear(); 12747c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 1275c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang 1276c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang queueDiscontinuity( 1277978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang ATSParser::DISCONTINUITY_FORMAT_ONLY, 1278c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang NULL /* extra */); 1279c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang 1280c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang if (mStartup && mStartTimeUsRelative && mFirstPTSValid) { 1281c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // This means we guessed mStartTimeUs to be in the previous 1282c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // segment (likely very close to the end), but either video or 1283c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // audio has not found start by the end of that segment. 1284c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // 1285c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // If this new segment is not a discontinuity, keep searching. 1286c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // 1287c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // If this new segment even got a discontinuity marker, just 1288c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang // set mStartTimeUs=0, and take all samples from now on. 1289c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang mStartTimeUs = 0; 1290c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang mFirstPTSValid = false; 1291978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mIDRFound = false; 1292978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mVideoBuffer->clear(); 1293c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang } 1294c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang } 1295c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang 129625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang FLOGV("fetching segment %d from (%d .. %d)", 1297a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mSeqNumber, firstSeqNumberInPlaylist, lastSeqNumberInPlaylist); 1298a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang return true; 1299a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang} 1300a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1301a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhangvoid PlaylistFetcher::onDownloadNext() { 1302a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang AString uri; 1303a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang sp<AMessage> itemMeta; 1304a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang sp<ABuffer> buffer; 1305a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang sp<ABuffer> tsBuffer; 1306a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang int32_t firstSeqNumberInPlaylist = 0; 1307a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang int32_t lastSeqNumberInPlaylist = 0; 1308a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang bool connectHTTP = true; 1309a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1310a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (mDownloadState->hasSavedState()) { 1311a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang mDownloadState->restoreState( 1312a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang uri, 1313a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang itemMeta, 1314a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang buffer, 1315a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang tsBuffer, 1316a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang firstSeqNumberInPlaylist, 1317a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang lastSeqNumberInPlaylist); 1318a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang connectHTTP = false; 131925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang FLOGV("resuming: '%s'", uri.c_str()); 1320a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } else { 1321a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (!initDownloadState( 1322a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang uri, 1323a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang itemMeta, 1324a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang firstSeqNumberInPlaylist, 1325a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang lastSeqNumberInPlaylist)) { 1326a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang return; 1327a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 132825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang FLOGV("fetching: '%s'", uri.c_str()); 1329a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 1330a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 1331a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang int64_t range_offset, range_length; 1332a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (!itemMeta->findInt64("range-offset", &range_offset) 1333a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang || !itemMeta->findInt64("range-length", &range_length)) { 1334a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang range_offset = 0; 1335a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang range_length = -1; 1336a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 1337a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 133843ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih // block-wise download 13397c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang bool shouldPause = false; 134043ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih ssize_t bytesRead; 134143ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih do { 1342a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang int64_t startUs = ALooper::GetNowUs(); 13435abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang bytesRead = mHTTPDownloader->fetchBlock( 1344a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang uri.c_str(), &buffer, range_offset, range_length, kDownloadBlockSize, 13455abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang NULL /* actualURL */, connectHTTP); 13465abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang int64_t delayUs = ALooper::GetNowUs() - startUs; 13475abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 13485abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang if (bytesRead == ERROR_NOT_CONNECTED) { 13495abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang return; 13505abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } 13515abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang if (bytesRead < 0) { 13525abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang status_t err = bytesRead; 13535abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang ALOGE("failed to fetch .ts segment at url '%s'", uri.c_str()); 13545abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang notifyError(err); 13555abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang return; 13565abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } 135714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 1358d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // add sample for bandwidth estimation, excluding samples from subtitles (as 1359d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // its too small), or during startup/resumeUntil (when we could have more than 1360d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // one connection open which affects bandwidth) 1361d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (!mStartup && mStopParams == NULL && bytesRead > 0 1362538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang && (mStreamTypeMask 1363538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang & (LiveSession::STREAMTYPE_AUDIO 1364538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang | LiveSession::STREAMTYPE_VIDEO))) { 1365538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang mSession->addBandwidthMeasurement(bytesRead, delayUs); 136625f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang if (delayUs > 2000000ll) { 136725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang FLOGV("bytesRead %zd took %.2f seconds - abnormal bandwidth dip", 136825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang bytesRead, (double)delayUs / 1.0e6); 136925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang } 1370538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang } 1371538b6d22a3578c0201d48f8548289aa254d81484Chong Zhang 1372a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang connectHTTP = false; 1373a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 137443ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih CHECK(buffer != NULL); 137514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 137643ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih size_t size = buffer->size(); 137743ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih // Set decryption range. 137843ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih buffer->setRange(size - bytesRead, bytesRead); 137943ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih status_t err = decryptBuffer(mSeqNumber - firstSeqNumberInPlaylist, buffer, 138043ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih buffer->offset() == 0 /* first */); 138143ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih // Unset decryption range. 138243ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih buffer->setRange(0, size); 138314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 138443ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih if (err != OK) { 138543ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih ALOGE("decryptBuffer failed w/ error %d", err); 138614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 138743ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih notifyError(err); 138843ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih return; 138914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 139014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 1391a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang bool startUp = mStartup; // save current start up state 1392a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang 139343ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih err = OK; 139443ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih if (bufferStartsWithTsSyncByte(buffer)) { 139543ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih // Incremental extraction is only supported for MPEG2 transport streams. 139643ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih if (tsBuffer == NULL) { 139743ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih tsBuffer = new ABuffer(buffer->data(), buffer->capacity()); 139843ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih tsBuffer->setRange(0, 0); 139943ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih } else if (tsBuffer->capacity() != buffer->capacity()) { 140043ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih size_t tsOff = tsBuffer->offset(), tsSize = tsBuffer->size(); 140143ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih tsBuffer = new ABuffer(buffer->data(), buffer->capacity()); 140243ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih tsBuffer->setRange(tsOff, tsSize); 140343ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih } 140443ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih tsBuffer->setRange(tsBuffer->offset(), tsBuffer->size() + bytesRead); 140543ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih err = extractAndQueueAccessUnitsFromTs(tsBuffer); 140643ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih } 140743ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih 140843ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih if (err == -EAGAIN) { 1409f78f62bd6b0a99747db53828d281a50b9270a646Robert Shih // starting sequence number too low/high 14105cda1b30b8c3900f8405f9bf2fab2df6e38ea95fRobert Shih mTSParser.clear(); 1411dae1e733f7cd4abaa14791657fa0a1b0e44a27b6Robert Shih for (size_t i = 0; i < mPacketSources.size(); i++) { 1412dae1e733f7cd4abaa14791657fa0a1b0e44a27b6Robert Shih sp<AnotherPacketSource> packetSource = mPacketSources.valueAt(i); 1413dae1e733f7cd4abaa14791657fa0a1b0e44a27b6Robert Shih packetSource->clear(); 1414dae1e733f7cd4abaa14791657fa0a1b0e44a27b6Robert Shih } 141543ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih postMonitorQueue(); 141643ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih return; 1417309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } else if (err == ERROR_OUT_OF_RANGE) { 141843ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih // reached stopping point 14197c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notifyStopReached(); 142043ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih return; 1421309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } else if (err != OK) { 142243ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih notifyError(err); 142343ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih return; 14247c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 14257c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // If we're switching, post start notification 14267c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // this should only be posted when the last chunk is full processed by TSParser 14277c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (mSeekMode != LiveSession::kSeekModeExactPosition && startUp != mStartup) { 14287c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang CHECK(mStartTimeUsNotify != NULL); 14297c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mStartTimeUsNotify->post(); 14307c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mStartTimeUsNotify.clear(); 14317c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang shouldPause = true; 14327c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 14337c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (shouldPause || shouldPauseDownload()) { 14347c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // save state and return if this is not the last chunk, 14357c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // leaving the fetcher in paused state. 14367c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (bytesRead != 0) { 14377c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mDownloadState->saveState( 14387c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang uri, 14397c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang itemMeta, 14407c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang buffer, 14417c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang tsBuffer, 14427c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang firstSeqNumberInPlaylist, 14437c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang lastSeqNumberInPlaylist); 14447c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return; 14457c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 14467c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang shouldPause = true; 144743ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih } 1448a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } while (bytesRead != 0); 144943ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih 145043ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih if (bufferStartsWithTsSyncByte(buffer)) { 1451bf20727f0aaf609bc3b495b07b45822b137d21baRobert Shih // If we don't see a stream in the program table after fetching a full ts segment 1452bf20727f0aaf609bc3b495b07b45822b137d21baRobert Shih // mark it as nonexistent. 14530852843d304006e3ab333081fddda13b07193de8Robert Shih ATSParser::SourceType srcTypes[] = 145443ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih { ATSParser::VIDEO, ATSParser::AUDIO }; 14550852843d304006e3ab333081fddda13b07193de8Robert Shih LiveSession::StreamType streamTypes[] = 145643ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih { LiveSession::STREAMTYPE_VIDEO, LiveSession::STREAMTYPE_AUDIO }; 14570852843d304006e3ab333081fddda13b07193de8Robert Shih const size_t kNumTypes = NELEM(srcTypes); 145843ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih 145943ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih for (size_t i = 0; i < kNumTypes; i++) { 146043ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih ATSParser::SourceType srcType = srcTypes[i]; 146143ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih LiveSession::StreamType streamType = streamTypes[i]; 146243ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih 146343ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih sp<AnotherPacketSource> source = 146443ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih static_cast<AnotherPacketSource *>( 146543ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih mTSParser->getSource(srcType).get()); 146643ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih 1467bf20727f0aaf609bc3b495b07b45822b137d21baRobert Shih if (!mTSParser->hasSource(srcType)) { 146843ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih ALOGW("MPEG2 Transport stream does not contain %s data.", 146943ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih srcType == ATSParser::VIDEO ? "video" : "audio"); 147043ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih 147143ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih mStreamTypeMask &= ~streamType; 147243ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih mPacketSources.removeItem(streamType); 147343ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih } 147443ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih } 147514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 14761543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 14771543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 147843ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih if (checkDecryptPadding(buffer) != OK) { 147943ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih ALOGE("Incorrect padding bytes after decryption."); 148043ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih notifyError(ERROR_MALFORMED); 14811543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih return; 14821543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 14831543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 148443ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih if (tsBuffer != NULL) { 148543ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih AString method; 148643ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih CHECK(buffer->meta()->findString("cipher-method", &method)); 148743ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih if ((tsBuffer->size() > 0 && method == "NONE") 148843ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih || tsBuffer->size() > 16) { 148943ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih ALOGE("MPEG2 transport stream is not an even multiple of 188 " 149043ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih "bytes in length."); 149143ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih notifyError(ERROR_MALFORMED); 149243ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih return; 149343ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih } 149443ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih } 149543ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih 149643ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih // bulk extract non-ts files 14977c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang bool startUp = mStartup; 149843ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih if (tsBuffer == NULL) { 14997c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang status_t err = extractAndQueueAccessUnits(buffer, itemMeta); 150073d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih if (err == -EAGAIN) { 150173d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih // starting sequence number too low/high 150273d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih postMonitorQueue(); 150373d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih return; 150473d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih } else if (err == ERROR_OUT_OF_RANGE) { 150573d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih // reached stopping point 15067c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notifyStopReached(); 15077c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return; 15087c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } else if (err != OK) { 15097c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang notifyError(err); 151073d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih return; 151173d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih } 151243ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih } 151343ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih 15147c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ++mSeqNumber; 15157c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 15167c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang // if adapting, pause after found the next starting point 15177c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (mSeekMode != LiveSession::kSeekModeExactPosition && startUp != mStartup) { 1518d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang CHECK(mStartTimeUsNotify != NULL); 15197c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mStartTimeUsNotify->post(); 15207c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang mStartTimeUsNotify.clear(); 15217c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang shouldPause = true; 152214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 152314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 15247c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (!shouldPause) { 15257c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang postMonitorQueue(); 15267c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang } 152714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 152814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 1529978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang/* 1530978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang * returns true if we need to adjust mSeqNumber 1531978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang */ 1532978449984366946a2e5c9f7cf350746f4306caf8Chong Zhangbool PlaylistFetcher::adjustSeqNumberWithAnchorTime(int64_t anchorTimeUs) { 1533978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang int32_t firstSeqNumberInPlaylist = mPlaylist->getFirstSeqNumber(); 1534978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang 1535978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang int64_t minDiffUs, maxDiffUs; 1536978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (mSeekMode == LiveSession::kSeekModeNextSample) { 15378a048338d9291b2db1b3a325fff58cb1aa69f04dChong Zhang // if the previous fetcher paused in the middle of a segment, we 15388a048338d9291b2db1b3a325fff58cb1aa69f04dChong Zhang // want to start at a segment that overlaps the last sample 1539978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang minDiffUs = -mPlaylist->getTargetDuration(); 1540978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang maxDiffUs = 0ll; 1541978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } else { 15428a048338d9291b2db1b3a325fff58cb1aa69f04dChong Zhang // if the previous fetcher paused at the end of a segment, ideally 15438a048338d9291b2db1b3a325fff58cb1aa69f04dChong Zhang // we want to start at the segment that's roughly aligned with its 15448a048338d9291b2db1b3a325fff58cb1aa69f04dChong Zhang // next segment, but if the two variants are not well aligned we 15458a048338d9291b2db1b3a325fff58cb1aa69f04dChong Zhang // adjust the diff to within (-T/2, T/2) 1546978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang minDiffUs = -mPlaylist->getTargetDuration() / 2; 15478a048338d9291b2db1b3a325fff58cb1aa69f04dChong Zhang maxDiffUs = mPlaylist->getTargetDuration() / 2; 1548f78f62bd6b0a99747db53828d281a50b9270a646Robert Shih } 1549f78f62bd6b0a99747db53828d281a50b9270a646Robert Shih 1550978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang int32_t oldSeqNumber = mSeqNumber; 1551978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang ssize_t index = mSeqNumber - firstSeqNumberInPlaylist; 1552f78f62bd6b0a99747db53828d281a50b9270a646Robert Shih 1553978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang // adjust anchorTimeUs to within (minDiffUs, maxDiffUs) from mStartTimeUs 1554978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang int64_t diffUs = anchorTimeUs - mStartTimeUs; 1555978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (diffUs > maxDiffUs) { 1556978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang while (index > 0 && diffUs > maxDiffUs) { 1557978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang --index; 1558978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang 1559978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang sp<AMessage> itemMeta; 1560978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang CHECK(mPlaylist->itemAt(index, NULL /* uri */, &itemMeta)); 1561978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang 1562978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang int64_t itemDurationUs; 1563978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang CHECK(itemMeta->findInt64("durationUs", &itemDurationUs)); 1564978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang 1565978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang diffUs -= itemDurationUs; 1566978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 1567978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } else if (diffUs < minDiffUs) { 1568978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang while (index + 1 < (ssize_t) mPlaylist->size() 1569978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang && diffUs < minDiffUs) { 1570978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang ++index; 1571978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang 1572978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang sp<AMessage> itemMeta; 1573978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang CHECK(mPlaylist->itemAt(index, NULL /* uri */, &itemMeta)); 1574978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang 1575978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang int64_t itemDurationUs; 1576978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang CHECK(itemMeta->findInt64("durationUs", &itemDurationUs)); 1577f78f62bd6b0a99747db53828d281a50b9270a646Robert Shih 1578978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang diffUs += itemDurationUs; 1579978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 1580f78f62bd6b0a99747db53828d281a50b9270a646Robert Shih } 1581f78f62bd6b0a99747db53828d281a50b9270a646Robert Shih 1582978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mSeqNumber = firstSeqNumberInPlaylist + index; 1583978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang 1584978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (mSeqNumber != oldSeqNumber) { 1585978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang FLOGV("guessed wrong seg number: diff %lld out of [%lld, %lld]", 1586978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang (long long) anchorTimeUs - mStartTimeUs, 1587978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang (long long) minDiffUs, 1588978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang (long long) maxDiffUs); 1589978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang return true; 1590f78f62bd6b0a99747db53828d281a50b9270a646Robert Shih } 1591978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang return false; 1592f78f62bd6b0a99747db53828d281a50b9270a646Robert Shih} 1593f78f62bd6b0a99747db53828d281a50b9270a646Robert Shih 1594309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shihint32_t PlaylistFetcher::getSeqNumberForDiscontinuity(size_t discontinuitySeq) const { 1595978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang int32_t firstSeqNumberInPlaylist = mPlaylist->getFirstSeqNumber(); 1596309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 1597309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih size_t index = 0; 1598309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih while (index < mPlaylist->size()) { 1599309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih sp<AMessage> itemMeta; 1600309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih CHECK(mPlaylist->itemAt( index, NULL /* uri */, &itemMeta)); 1601d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang size_t curDiscontinuitySeq; 1602d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang CHECK(itemMeta->findInt32("discontinuity-sequence", (int32_t *)&curDiscontinuitySeq)); 1603d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang int32_t seqNumber = firstSeqNumberInPlaylist + index; 1604309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (curDiscontinuitySeq == discontinuitySeq) { 1605d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang return seqNumber; 1606d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang } else if (curDiscontinuitySeq > discontinuitySeq) { 1607d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang return seqNumber <= 0 ? 0 : seqNumber - 1; 1608309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 1609309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 1610309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih ++index; 1611309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 1612309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 1613309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih return firstSeqNumberInPlaylist + mPlaylist->size(); 1614309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih} 1615309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 161614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberint32_t PlaylistFetcher::getSeqNumberForTime(int64_t timeUs) const { 161714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber size_t index = 0; 161814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int64_t segmentStartUs = 0; 161914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber while (index < mPlaylist->size()) { 162014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AMessage> itemMeta; 162114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(mPlaylist->itemAt( 162214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber index, NULL /* uri */, &itemMeta)); 162314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 162414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int64_t itemDurationUs; 162514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(itemMeta->findInt64("durationUs", &itemDurationUs)); 162614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 162714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (timeUs < segmentStartUs + itemDurationUs) { 162814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 162914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 163014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 163114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber segmentStartUs += itemDurationUs; 163214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ++index; 163314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 163414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 163514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (index >= mPlaylist->size()) { 163614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber index = mPlaylist->size() - 1; 163714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 163814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 1639978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang return mPlaylist->getFirstSeqNumber() + index; 164014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 164114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 1642309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shihconst sp<ABuffer> &PlaylistFetcher::setAccessUnitProperties( 1643309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih const sp<ABuffer> &accessUnit, const sp<AnotherPacketSource> &source, bool discard) { 1644309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih sp<MetaData> format = source->getFormat(); 1645309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (format != NULL) { 1646309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih // for simplicity, store a reference to the format in each unit 1647309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih accessUnit->meta()->setObject("format", format); 1648309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 1649309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 1650309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (discard) { 1651309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih accessUnit->meta()->setInt32("discard", discard); 1652309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 1653309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 1654309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih accessUnit->meta()->setInt32("discontinuitySeq", mDiscontinuitySeq); 1655309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih accessUnit->meta()->setInt64("segmentStartTimeUs", getSegmentStartTimeUs(mSeqNumber)); 1656978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang accessUnit->meta()->setInt64("segmentFirstTimeUs", mSegmentFirstPTS); 16577c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang accessUnit->meta()->setInt64("segmentDurationUs", getSegmentDurationUs(mSeqNumber)); 1658978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (!mPlaylist->isComplete() && !mPlaylist->isEvent()) { 1659978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang accessUnit->meta()->setInt64("playlistTimeUs", mPlaylistTimeUs); 1660978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 1661309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih return accessUnit; 1662309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih} 1663309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 16640852843d304006e3ab333081fddda13b07193de8Robert Shihbool PlaylistFetcher::isStartTimeReached(int64_t timeUs) { 16650852843d304006e3ab333081fddda13b07193de8Robert Shih if (!mFirstPTSValid) { 16660852843d304006e3ab333081fddda13b07193de8Robert Shih mFirstTimeUs = timeUs; 16670852843d304006e3ab333081fddda13b07193de8Robert Shih mFirstPTSValid = true; 16680852843d304006e3ab333081fddda13b07193de8Robert Shih } 16690852843d304006e3ab333081fddda13b07193de8Robert Shih bool startTimeReached = true; 16700852843d304006e3ab333081fddda13b07193de8Robert Shih if (mStartTimeUsRelative) { 16710852843d304006e3ab333081fddda13b07193de8Robert Shih FLOGV("startTimeUsRelative, timeUs (%lld) - %lld = %lld", 16720852843d304006e3ab333081fddda13b07193de8Robert Shih (long long)timeUs, 16730852843d304006e3ab333081fddda13b07193de8Robert Shih (long long)mFirstTimeUs, 16740852843d304006e3ab333081fddda13b07193de8Robert Shih (long long)(timeUs - mFirstTimeUs)); 16750852843d304006e3ab333081fddda13b07193de8Robert Shih timeUs -= mFirstTimeUs; 16760852843d304006e3ab333081fddda13b07193de8Robert Shih if (timeUs < 0) { 16770852843d304006e3ab333081fddda13b07193de8Robert Shih FLOGV("clamp negative timeUs to 0"); 16780852843d304006e3ab333081fddda13b07193de8Robert Shih timeUs = 0; 16790852843d304006e3ab333081fddda13b07193de8Robert Shih } 16800852843d304006e3ab333081fddda13b07193de8Robert Shih startTimeReached = (timeUs >= mStartTimeUs); 16810852843d304006e3ab333081fddda13b07193de8Robert Shih } 16820852843d304006e3ab333081fddda13b07193de8Robert Shih return startTimeReached; 16830852843d304006e3ab333081fddda13b07193de8Robert Shih} 16840852843d304006e3ab333081fddda13b07193de8Robert Shih 168543ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shihstatus_t PlaylistFetcher::extractAndQueueAccessUnitsFromTs(const sp<ABuffer> &buffer) { 168643ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih if (mTSParser == NULL) { 168743ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih // Use TS_TIMESTAMPS_ARE_ABSOLUTE so pts carry over between fetchers. 168843ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih mTSParser = new ATSParser(ATSParser::TS_TIMESTAMPS_ARE_ABSOLUTE); 168943ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih } 169014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 169143ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih if (mNextPTSTimeUs >= 0ll) { 169243ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih sp<AMessage> extra = new AMessage; 169343ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih // Since we are using absolute timestamps, signal an offset of 0 to prevent 169443ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih // ATSParser from skewing the timestamps of access units. 169543ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih extra->setInt64(IStreamListener::kKeyMediaTimeUs, 0); 169614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 1697d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // When adapting, signal a recent media time to the parser, 1698d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // so that PTS wrap around is handled for the new variant. 1699d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (mStartTimeUs >= 0 && !mStartTimeUsRelative) { 1700d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang extra->setInt64(IStreamListener::kKeyRecentMediaTimeUs, mStartTimeUs); 1701d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang } 1702d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang 170343ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih mTSParser->signalDiscontinuity( 1704fef808d42a9c94b0b5ef3c3d5fb0a090edbc42daWei Jia ATSParser::DISCONTINUITY_TIME, extra); 170514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 170643ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih mNextPTSTimeUs = -1ll; 170743ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih } 170814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 17093a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania if (mSampleAesKeyItemChanged) { 17103a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania mTSParser->signalNewSampleAesKey(mSampleAesKeyItem); 17113a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania mSampleAesKeyItemChanged = false; 17123a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania } 17133a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 171443ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih size_t offset = 0; 171543ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih while (offset + 188 <= buffer->size()) { 171643ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih status_t err = mTSParser->feedTSPacket(buffer->data() + offset, 188); 171714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 171843ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih if (err != OK) { 171943ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih return err; 172014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 172114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 172243ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih offset += 188; 172343ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih } 172443ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih // setRange to indicate consumed bytes. 172543ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih buffer->setRange(buffer->offset() + offset, buffer->size() - offset); 17261543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 1727978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (mSegmentFirstPTS < 0ll) { 1728978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang // get the smallest first PTS from all streams present in this parser 172925f191c5cb2ec532e534be646c32806f9f85e196Vishwath Mohan for (size_t i = mPacketSources.size(); i > 0;) { 173025f191c5cb2ec532e534be646c32806f9f85e196Vishwath Mohan i--; 1731978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang const LiveSession::StreamType stream = mPacketSources.keyAt(i); 1732978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (stream == LiveSession::STREAMTYPE_SUBTITLES) { 1733978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang ALOGE("MPEG2 Transport streams do not contain subtitles."); 1734978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang return ERROR_MALFORMED; 1735978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 17368a048338d9291b2db1b3a325fff58cb1aa69f04dChong Zhang if (stream == LiveSession::STREAMTYPE_METADATA) { 17378a048338d9291b2db1b3a325fff58cb1aa69f04dChong Zhang continue; 17388a048338d9291b2db1b3a325fff58cb1aa69f04dChong Zhang } 1739978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang ATSParser::SourceType type =LiveSession::getSourceTypeForStream(stream); 1740978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang sp<AnotherPacketSource> source = 1741978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang static_cast<AnotherPacketSource *>( 1742978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mTSParser->getSource(type).get()); 1743978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang 1744978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (source == NULL) { 1745978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang continue; 1746978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 1747978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang sp<AMessage> meta = source->getMetaAfterLastDequeued(0); 1748978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (meta != NULL) { 1749978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang int64_t timeUs; 1750978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang CHECK(meta->findInt64("timeUs", &timeUs)); 1751978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (mSegmentFirstPTS < 0ll || timeUs < mSegmentFirstPTS) { 1752978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mSegmentFirstPTS = timeUs; 1753978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 1754978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 1755978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 1756978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (mSegmentFirstPTS < 0ll) { 1757978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang // didn't find any TS packet, can return early 1758978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang return OK; 1759978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 1760978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (!mStartTimeUsRelative) { 1761978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang // mStartup 1762978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang // mStartup is true until we have queued a packet for all the streams 1763978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang // we are fetching. We queue packets whose timestamps are greater than 1764978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang // mStartTimeUs. 1765978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang // mSegmentStartTimeUs >= 0 1766978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang // mSegmentStartTimeUs is non-negative when adapting or switching tracks 1767978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang // adjustSeqNumberWithAnchorTime(timeUs) == true 1768978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang // we guessed a seq number that's either too large or too small. 1769978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang // If this happens, we'll adjust mSeqNumber and restart fetching from new 1770978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang // location. Note that we only want to adjust once, so set mSegmentStartTimeUs 1771978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang // to -1 so that we don't enter this chunk next time. 1772978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (mStartup && mSegmentStartTimeUs >= 0 1773978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang && adjustSeqNumberWithAnchorTime(mSegmentFirstPTS)) { 1774978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mStartTimeUsNotify = mNotify->dup(); 1775978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mStartTimeUsNotify->setInt32("what", kWhatStartedAt); 1776978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mStartTimeUsNotify->setString("uri", mURI); 1777978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mIDRFound = false; 1778978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mSegmentStartTimeUs = -1; 1779978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang return -EAGAIN; 1780978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 1781978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 1782978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 1783978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang 178443ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih status_t err = OK; 178525f191c5cb2ec532e534be646c32806f9f85e196Vishwath Mohan for (size_t i = mPacketSources.size(); i > 0;) { 178625f191c5cb2ec532e534be646c32806f9f85e196Vishwath Mohan i--; 178743ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih sp<AnotherPacketSource> packetSource = mPacketSources.valueAt(i); 178814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 178943ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih const LiveSession::StreamType stream = mPacketSources.keyAt(i); 17907c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang if (stream == LiveSession::STREAMTYPE_SUBTITLES) { 17917c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang ALOGE("MPEG2 Transport streams do not contain subtitles."); 17927c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang return ERROR_MALFORMED; 179343ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih } 17940852843d304006e3ab333081fddda13b07193de8Robert Shih 17957c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang const char *key = LiveSession::getKeyForStream(stream); 17960852843d304006e3ab333081fddda13b07193de8Robert Shih ATSParser::SourceType type =LiveSession::getSourceTypeForStream(stream); 179714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 179843ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih sp<AnotherPacketSource> source = 179943ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih static_cast<AnotherPacketSource *>( 180043ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih mTSParser->getSource(type).get()); 180114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 180243ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih if (source == NULL) { 180343ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih continue; 180443ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih } 180514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 1806c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang const char *mime; 1807c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang sp<MetaData> format = source->getFormat(); 1808c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang bool isAvc = format != NULL && format->findCString(kKeyMIMEType, &mime) 1809c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang && !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); 1810c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang 181143ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih sp<ABuffer> accessUnit; 181243ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih status_t finalResult; 181343ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih while (source->hasBufferAvailable(&finalResult) 181443ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih && source->dequeueAccessUnit(&accessUnit) == OK) { 181543ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih 1816c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang int64_t timeUs; 181743ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs)); 1818309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 1819309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (mStartup) { 18200852843d304006e3ab333081fddda13b07193de8Robert Shih bool startTimeReached = isStartTimeReached(timeUs); 1821f78f62bd6b0a99747db53828d281a50b9270a646Robert Shih 1822a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (!startTimeReached || (isAvc && !mIDRFound)) { 1823a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // buffer up to the closest preceding IDR frame in the next segement, 1824a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang // or the closest succeeding IDR frame after the exact position 1825978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang FSLOGV(stream, "timeUs(%lld)-mStartTimeUs(%lld)=%lld, mIDRFound=%d", 1826978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang (long long)timeUs, 1827978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang (long long)mStartTimeUs, 1828978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang (long long)timeUs - mStartTimeUs, 1829978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mIDRFound); 1830f78f62bd6b0a99747db53828d281a50b9270a646Robert Shih if (isAvc) { 1831d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (IsIDR(accessUnit)) { 1832c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang mVideoBuffer->clear(); 183325f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang FSLOGV(stream, "found IDR, clear mVideoBuffer"); 1834c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang mIDRFound = true; 1835c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang } 1836d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (mIDRFound && mStartTimeUsRelative && !startTimeReached) { 1837c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang mVideoBuffer->queueAccessUnit(accessUnit); 183825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang FSLOGV(stream, "saving AVC video AccessUnit"); 1839c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang } 18401543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 1841a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang if (!startTimeReached || (isAvc && !mIDRFound)) { 1842a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang continue; 1843a48d372833ccec13c96ece9efcc226e8beac7f59Chong Zhang } 18441543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 1845f78f62bd6b0a99747db53828d281a50b9270a646Robert Shih } 1846309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 1847c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang if (mStartTimeUsNotify != NULL) { 1848d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang uint32_t streamMask = 0; 1849d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang mStartTimeUsNotify->findInt32("streamMask", (int32_t *) &streamMask); 18500852843d304006e3ab333081fddda13b07193de8Robert Shih if ((mStreamTypeMask & mPacketSources.keyAt(i)) 18510852843d304006e3ab333081fddda13b07193de8Robert Shih && !(streamMask & mPacketSources.keyAt(i))) { 1852f78f62bd6b0a99747db53828d281a50b9270a646Robert Shih streamMask |= mPacketSources.keyAt(i); 1853f78f62bd6b0a99747db53828d281a50b9270a646Robert Shih mStartTimeUsNotify->setInt32("streamMask", streamMask); 185425f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang FSLOGV(stream, "found start point, timeUs=%lld, streamMask becomes %x", 185525f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang (long long)timeUs, streamMask); 1856f78f62bd6b0a99747db53828d281a50b9270a646Robert Shih 1857f78f62bd6b0a99747db53828d281a50b9270a646Robert Shih if (streamMask == mStreamTypeMask) { 185825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang FLOGV("found start point for all streams"); 1859f78f62bd6b0a99747db53828d281a50b9270a646Robert Shih mStartup = false; 1860309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 1861309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 186243ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih } 18631543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 186443ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih if (mStopParams != NULL) { 1865309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih int32_t discontinuitySeq; 186643ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih int64_t stopTimeUs; 1867309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (!mStopParams->findInt32("discontinuitySeq", &discontinuitySeq) 1868309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih || discontinuitySeq > mDiscontinuitySeq 1869309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih || !mStopParams->findInt64(key, &stopTimeUs) 1870309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih || (discontinuitySeq == mDiscontinuitySeq 1871309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih && timeUs >= stopTimeUs)) { 187225f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang FSLOGV(stream, "reached stop point, timeUs=%lld", (long long)timeUs); 187343ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih mStreamTypeMask &= ~stream; 187443ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih mPacketSources.removeItemsAt(i); 187543ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih break; 18761543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 187743ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih } 18781543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 1879309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (stream == LiveSession::STREAMTYPE_VIDEO) { 1880309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih const bool discard = true; 1881309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih status_t status; 1882309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih while (mVideoBuffer->hasBufferAvailable(&status)) { 1883309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih sp<ABuffer> videoBuffer; 1884309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mVideoBuffer->dequeueAccessUnit(&videoBuffer); 1885309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih setAccessUnitProperties(videoBuffer, source, discard); 1886309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih packetSource->queueAccessUnit(videoBuffer); 188725f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang int64_t bufferTimeUs; 188825f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang CHECK(videoBuffer->meta()->findInt64("timeUs", &bufferTimeUs)); 188925f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang FSLOGV(stream, "queueAccessUnit (saved), timeUs=%lld", 189025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang (long long)bufferTimeUs); 1891309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 18920852843d304006e3ab333081fddda13b07193de8Robert Shih } else if (stream == LiveSession::STREAMTYPE_METADATA && !mHasMetadata) { 18930852843d304006e3ab333081fddda13b07193de8Robert Shih mHasMetadata = true; 18940852843d304006e3ab333081fddda13b07193de8Robert Shih sp<AMessage> notify = mNotify->dup(); 18950852843d304006e3ab333081fddda13b07193de8Robert Shih notify->setInt32("what", kWhatMetadataDetected); 18960852843d304006e3ab333081fddda13b07193de8Robert Shih notify->post(); 189714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 18981543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 1899309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih setAccessUnitProperties(accessUnit, source); 190043ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih packetSource->queueAccessUnit(accessUnit); 190125f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang FSLOGV(stream, "queueAccessUnit, timeUs=%lld", (long long)timeUs); 19021543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 19031543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 19041543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih if (err != OK) { 190543ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih break; 19061543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih } 190743ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih } 19081543d3c735a5ba4ddfcf8ab644575df13c7e30a9Robert Shih 190943ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih if (err != OK) { 191025f191c5cb2ec532e534be646c32806f9f85e196Vishwath Mohan for (size_t i = mPacketSources.size(); i > 0;) { 191125f191c5cb2ec532e534be646c32806f9f85e196Vishwath Mohan i--; 191243ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih sp<AnotherPacketSource> packetSource = mPacketSources.valueAt(i); 191343ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih packetSource->clear(); 191414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 191543ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih return err; 191643ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih } 191714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 191843ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih if (!mStreamTypeMask) { 191943ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih // Signal gap is filled between original and new stream. 192025f82752942b1c78aec8ee303d61afff85cff9d1Chong Zhang FLOGV("reached stop point for all streams"); 192143ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih return ERROR_OUT_OF_RANGE; 192243ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih } 192343ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih 192443ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih return OK; 192543ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih} 192643ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih 19277d8e3ccfbf326b5e190b416590e956c2fc3021f7Lajos Molnar/* static */ 19287d8e3ccfbf326b5e190b416590e956c2fc3021f7Lajos Molnarbool PlaylistFetcher::bufferStartsWithWebVTTMagicSequence( 19297d8e3ccfbf326b5e190b416590e956c2fc3021f7Lajos Molnar const sp<ABuffer> &buffer) { 19307d8e3ccfbf326b5e190b416590e956c2fc3021f7Lajos Molnar size_t pos = 0; 19317d8e3ccfbf326b5e190b416590e956c2fc3021f7Lajos Molnar 19327d8e3ccfbf326b5e190b416590e956c2fc3021f7Lajos Molnar // skip possible BOM 19337d8e3ccfbf326b5e190b416590e956c2fc3021f7Lajos Molnar if (buffer->size() >= pos + 3 && 19347d8e3ccfbf326b5e190b416590e956c2fc3021f7Lajos Molnar !memcmp("\xef\xbb\xbf", buffer->data() + pos, 3)) { 19357d8e3ccfbf326b5e190b416590e956c2fc3021f7Lajos Molnar pos += 3; 19367d8e3ccfbf326b5e190b416590e956c2fc3021f7Lajos Molnar } 19377d8e3ccfbf326b5e190b416590e956c2fc3021f7Lajos Molnar 19387d8e3ccfbf326b5e190b416590e956c2fc3021f7Lajos Molnar // accept WEBVTT followed by SPACE, TAB or (CR) LF 19397d8e3ccfbf326b5e190b416590e956c2fc3021f7Lajos Molnar if (buffer->size() < pos + 6 || 19407d8e3ccfbf326b5e190b416590e956c2fc3021f7Lajos Molnar memcmp("WEBVTT", buffer->data() + pos, 6)) { 19417d8e3ccfbf326b5e190b416590e956c2fc3021f7Lajos Molnar return false; 19427d8e3ccfbf326b5e190b416590e956c2fc3021f7Lajos Molnar } 19437d8e3ccfbf326b5e190b416590e956c2fc3021f7Lajos Molnar pos += 6; 19447d8e3ccfbf326b5e190b416590e956c2fc3021f7Lajos Molnar 19457d8e3ccfbf326b5e190b416590e956c2fc3021f7Lajos Molnar if (buffer->size() == pos) { 19467d8e3ccfbf326b5e190b416590e956c2fc3021f7Lajos Molnar return true; 19477d8e3ccfbf326b5e190b416590e956c2fc3021f7Lajos Molnar } 19487d8e3ccfbf326b5e190b416590e956c2fc3021f7Lajos Molnar 19497d8e3ccfbf326b5e190b416590e956c2fc3021f7Lajos Molnar uint8_t sep = buffer->data()[pos]; 19507d8e3ccfbf326b5e190b416590e956c2fc3021f7Lajos Molnar return sep == ' ' || sep == '\t' || sep == '\n' || sep == '\r'; 19517d8e3ccfbf326b5e190b416590e956c2fc3021f7Lajos Molnar} 19527d8e3ccfbf326b5e190b416590e956c2fc3021f7Lajos Molnar 195343ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shihstatus_t PlaylistFetcher::extractAndQueueAccessUnits( 195443ca783effd99bba0e6e2dd6fe177a8888578ef8Robert Shih const sp<ABuffer> &buffer, const sp<AMessage> &itemMeta) { 19557d8e3ccfbf326b5e190b416590e956c2fc3021f7Lajos Molnar if (bufferStartsWithWebVTTMagicSequence(buffer)) { 195614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (mStreamTypeMask != LiveSession::STREAMTYPE_SUBTITLES) { 195714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGE("This stream only contains subtitles."); 195814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return ERROR_MALFORMED; 195914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 196014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 196114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber const sp<AnotherPacketSource> packetSource = 196214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mPacketSources.valueFor(LiveSession::STREAMTYPE_SUBTITLES); 196314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 1964dcb89b3b505522efde173c105a851c412f947178Chong Zhang int64_t durationUs; 1965dcb89b3b505522efde173c105a851c412f947178Chong Zhang CHECK(itemMeta->findInt64("durationUs", &durationUs)); 1966dcb89b3b505522efde173c105a851c412f947178Chong Zhang buffer->meta()->setInt64("timeUs", getSegmentStartTimeUs(mSeqNumber)); 1967dcb89b3b505522efde173c105a851c412f947178Chong Zhang buffer->meta()->setInt64("durationUs", durationUs); 1968309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih buffer->meta()->setInt64("segmentStartTimeUs", getSegmentStartTimeUs(mSeqNumber)); 1969309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih buffer->meta()->setInt32("discontinuitySeq", mDiscontinuitySeq); 1970b44ce2f84691559672cfaf6bb8fd3a9ac43904f2Robert Shih buffer->meta()->setInt32("subtitleGeneration", mSubtitleGeneration); 197114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber packetSource->queueAccessUnit(buffer); 197214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return OK; 197314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 197414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 197514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (mNextPTSTimeUs >= 0ll) { 197614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mNextPTSTimeUs = -1ll; 197714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 197814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 197914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // This better be an ISO 13818-7 (AAC) or ISO 13818-1 (MPEG) audio 198014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // stream prefixed by an ID3 tag. 198114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 198214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber bool firstID3Tag = true; 198314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber uint64_t PTS = 0; 198414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 198514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber for (;;) { 198614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // Make sure to skip all ID3 tags preceding the audio data. 198714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // At least one must be present to provide the PTS timestamp. 198814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 198914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ID3 id3(buffer->data(), buffer->size(), true /* ignoreV1 */); 199014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (!id3.isValid()) { 199114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (firstID3Tag) { 199214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGE("Unable to parse ID3 tag."); 199314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return ERROR_MALFORMED; 199414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else { 199514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 199614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 199714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 199814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 199914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (firstID3Tag) { 200014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber bool found = false; 200114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 200214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ID3::Iterator it(id3, "PRIV"); 200314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber while (!it.done()) { 200414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber size_t length; 200514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber const uint8_t *data = it.getData(&length); 2006be7b5e253f85132683826f305e5dcdaf83f0b300Joshua J. Drake if (!data) { 2007be7b5e253f85132683826f305e5dcdaf83f0b300Joshua J. Drake return ERROR_MALFORMED; 2008be7b5e253f85132683826f305e5dcdaf83f0b300Joshua J. Drake } 200914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 201014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber static const char *kMatchName = 201114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber "com.apple.streaming.transportStreamTimestamp"; 201214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber static const size_t kMatchNameLen = strlen(kMatchName); 201314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 201414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (length == kMatchNameLen + 1 + 8 201514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber && !strncmp((const char *)data, kMatchName, kMatchNameLen)) { 201614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber found = true; 201714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber PTS = U64_AT(&data[kMatchNameLen + 1]); 201814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 201914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 202014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber it.next(); 202114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 202214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 202314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (!found) { 202414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGE("Unable to extract transportStreamTimestamp from ID3 tag."); 202514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return ERROR_MALFORMED; 202614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 202714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 202814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 202914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // skip the ID3 tag 203014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber buffer->setRange( 203114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber buffer->offset() + id3.rawSize(), buffer->size() - id3.rawSize()); 203214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 203314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber firstID3Tag = false; 203414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 203514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 203614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (mStreamTypeMask != LiveSession::STREAMTYPE_AUDIO) { 203714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGW("This stream only contains audio data!"); 203814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 203914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mStreamTypeMask &= LiveSession::STREAMTYPE_AUDIO; 204014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 204114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (mStreamTypeMask == 0) { 204214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return OK; 204314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 204414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 204514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 204614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AnotherPacketSource> packetSource = 204714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mPacketSources.valueFor(LiveSession::STREAMTYPE_AUDIO); 204814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 204914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (packetSource->getFormat() == NULL && buffer->size() >= 7) { 205014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ABitReader bits(buffer->data(), buffer->size()); 205114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 205214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // adts_fixed_header 205314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 205414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK_EQ(bits.getBits(12), 0xfffu); 205514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber bits.skipBits(3); // ID, layer 2056b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe bool protection_absent __unused = bits.getBits(1) != 0; 205714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 205814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber unsigned profile = bits.getBits(2); 205914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK_NE(profile, 3u); 206014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber unsigned sampling_freq_index = bits.getBits(4); 206114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber bits.getBits(1); // private_bit 206214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber unsigned channel_configuration = bits.getBits(3); 206314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK_NE(channel_configuration, 0u); 206414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber bits.skipBits(2); // original_copy, home 206514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 206614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<MetaData> meta = MakeAACCodecSpecificData( 206714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber profile, sampling_freq_index, channel_configuration); 206814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 206914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber meta->setInt32(kKeyIsADTS, true); 207014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 207114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber packetSource->setFormat(meta); 207214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 207314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 207414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int64_t numSamples = 0ll; 207514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int32_t sampleRate; 207614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(packetSource->getFormat()->findInt32(kKeySampleRate, &sampleRate)); 207714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 2078309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih int64_t timeUs = (PTS * 100ll) / 9ll; 2079c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang if (mStartup && !mFirstPTSValid) { 2080309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mFirstPTSValid = true; 2081309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mFirstTimeUs = timeUs; 2082309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 2083309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 2084978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (mSegmentFirstPTS < 0ll) { 2085978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mSegmentFirstPTS = timeUs; 2086978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (!mStartTimeUsRelative) { 2087978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang // Duplicated logic from how we handle .ts playlists. 2088978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (mStartup && mSegmentStartTimeUs >= 0 2089978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang && adjustSeqNumberWithAnchorTime(timeUs)) { 2090978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mSegmentStartTimeUs = -1; 2091978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang return -EAGAIN; 2092978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 2093978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 2094978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 2095978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang 20963a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania sp<HlsSampleDecryptor> sampleDecryptor = NULL; 20973a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania if (mSampleAesKeyItem != NULL) { 20983a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania ALOGV("extractAndQueueAccessUnits[%d] SampleAesKeyItem: Key: %s IV: %s", 20993a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania mSeqNumber, 21003a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania HlsSampleDecryptor::aesBlockToStr(mKeyData).c_str(), 21013a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania HlsSampleDecryptor::aesBlockToStr(mAESInitVec).c_str()); 21023a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 21033a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania sampleDecryptor = new HlsSampleDecryptor(mSampleAesKeyItem); 21043a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania } 21053a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 21063a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania int frameId = 0; 21073a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 210814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber size_t offset = 0; 210914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber while (offset < buffer->size()) { 211014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber const uint8_t *adtsHeader = buffer->data() + offset; 211114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK_LT(offset + 5, buffer->size()); 21123a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania // non-const pointer for decryption if needed 21133a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania uint8_t *adtsFrame = buffer->data() + offset; 211414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 211514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber unsigned aac_frame_length = 211614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ((adtsHeader[3] & 3) << 11) 211714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber | (adtsHeader[4] << 3) 211814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber | (adtsHeader[5] >> 5); 211914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 2120bdc0609f8133517b8e051938ad66bac750be90b4Robert Shih if (aac_frame_length == 0) { 2121bdc0609f8133517b8e051938ad66bac750be90b4Robert Shih const uint8_t *id3Header = adtsHeader; 2122bdc0609f8133517b8e051938ad66bac750be90b4Robert Shih if (!memcmp(id3Header, "ID3", 3)) { 2123bdc0609f8133517b8e051938ad66bac750be90b4Robert Shih ID3 id3(id3Header, buffer->size() - offset, true); 2124bdc0609f8133517b8e051938ad66bac750be90b4Robert Shih if (id3.isValid()) { 2125bdc0609f8133517b8e051938ad66bac750be90b4Robert Shih offset += id3.rawSize(); 2126bdc0609f8133517b8e051938ad66bac750be90b4Robert Shih continue; 2127bdc0609f8133517b8e051938ad66bac750be90b4Robert Shih }; 2128bdc0609f8133517b8e051938ad66bac750be90b4Robert Shih } 2129bdc0609f8133517b8e051938ad66bac750be90b4Robert Shih return ERROR_MALFORMED; 2130bdc0609f8133517b8e051938ad66bac750be90b4Robert Shih } 2131bdc0609f8133517b8e051938ad66bac750be90b4Robert Shih 213214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK_LE(offset + aac_frame_length, buffer->size()); 213314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 213414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int64_t unitTimeUs = timeUs + numSamples * 1000000ll / sampleRate; 2135309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih offset += aac_frame_length; 213614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 213714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // Each AAC frame encodes 1024 samples. 213814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber numSamples += 1024; 213914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 2140309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (mStartup) { 2141309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih int64_t startTimeUs = unitTimeUs; 2142309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (mStartTimeUsRelative) { 2143309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih startTimeUs -= mFirstTimeUs; 2144309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (startTimeUs < 0) { 2145309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih startTimeUs = 0; 2146309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 2147309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 2148309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (startTimeUs < mStartTimeUs) { 2149309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih continue; 2150309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 215173d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih 215273d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih if (mStartTimeUsNotify != NULL) { 215373d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih mStartTimeUsNotify->setInt32("streamMask", LiveSession::STREAMTYPE_AUDIO); 2154f5b7c3b3c9a6da29f3bbd02e4031ad19bc7ad0f7Robert Shih mStartup = false; 215573d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih } 215673d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih } 215773d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih 215873d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih if (mStopParams != NULL) { 215973d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih int32_t discontinuitySeq; 216073d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih int64_t stopTimeUs; 216173d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih if (!mStopParams->findInt32("discontinuitySeq", &discontinuitySeq) 216273d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih || discontinuitySeq > mDiscontinuitySeq 216373d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih || !mStopParams->findInt64("timeUsAudio", &stopTimeUs) 216473d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih || (discontinuitySeq == mDiscontinuitySeq && unitTimeUs >= stopTimeUs)) { 216573d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih mStreamTypeMask = 0; 216673d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih mPacketSources.clear(); 216773d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih return ERROR_OUT_OF_RANGE; 216873d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih } 2169309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 217014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 21713a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania if (sampleDecryptor != NULL) { 21723a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania bool protection_absent = (adtsHeader[1] & 0x1); 21733a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania size_t headerSize = protection_absent ? 7 : 9; 21743a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania if (frameId == 0) { 21753a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania ALOGV("extractAndQueueAAC[%d] protection_absent %d (%02x) headerSize %zu", 21763a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania mSeqNumber, protection_absent, adtsHeader[1], headerSize); 21773a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania } 21783a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 21793a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania sampleDecryptor->processAAC(headerSize, adtsFrame, aac_frame_length); 21803a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania } 21813a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania frameId++; 21823a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 2183309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih sp<ABuffer> unit = new ABuffer(aac_frame_length); 2184309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih memcpy(unit->data(), adtsHeader, aac_frame_length); 2185309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 2186309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih unit->meta()->setInt64("timeUs", unitTimeUs); 218773d2847af14cdd5fdf8bd1ac80fb7ddf9ae7d9a7Robert Shih setAccessUnitProperties(unit, packetSource); 2188309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih packetSource->queueAccessUnit(unit); 218914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 219014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 219114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return OK; 219214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 219314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 219414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid PlaylistFetcher::updateDuration() { 219514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int64_t durationUs = 0ll; 219614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber for (size_t index = 0; index < mPlaylist->size(); ++index) { 219714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AMessage> itemMeta; 219814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(mPlaylist->itemAt( 219914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber index, NULL /* uri */, &itemMeta)); 220014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 220114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber int64_t itemDurationUs; 220214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(itemMeta->findInt64("durationUs", &itemDurationUs)); 220314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 220414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber durationUs += itemDurationUs; 220514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 220614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 220714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AMessage> msg = mNotify->dup(); 220814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber msg->setInt32("what", kWhatDurationUpdate); 220914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber msg->setInt64("durationUs", durationUs); 221014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber msg->post(); 221114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 221214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 22137c8708046117e03c0d38006bdd9685139df3ac6bChong Zhangvoid PlaylistFetcher::updateTargetDuration() { 22147c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang sp<AMessage> msg = mNotify->dup(); 22157c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang msg->setInt32("what", kWhatTargetDurationUpdate); 2216978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang msg->setInt64("targetDurationUs", mPlaylist->getTargetDuration()); 22177c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang msg->post(); 22187c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang} 22197c8708046117e03c0d38006bdd9685139df3ac6bChong Zhang 222014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} // namespace android 2221