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> &notify,
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> &params) {
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", &params));
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