PlaylistFetcher.cpp revision 25f82752942b1c78aec8ee303d61afff85cff9d1
1/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "PlaylistFetcher"
19#include <utils/Log.h>
20
21#include "PlaylistFetcher.h"
22
23#include "LiveDataSource.h"
24#include "LiveSession.h"
25#include "M3UParser.h"
26
27#include "include/avc_utils.h"
28#include "include/HTTPBase.h"
29#include "include/ID3.h"
30#include "mpeg2ts/AnotherPacketSource.h"
31
32#include <media/IStreamSource.h>
33#include <media/stagefright/foundation/ABitReader.h>
34#include <media/stagefright/foundation/ABuffer.h>
35#include <media/stagefright/foundation/ADebug.h>
36#include <media/stagefright/foundation/AUtils.h>
37#include <media/stagefright/foundation/hexdump.h>
38#include <media/stagefright/FileSource.h>
39#include <media/stagefright/MediaDefs.h>
40#include <media/stagefright/MetaData.h>
41#include <media/stagefright/Utils.h>
42
43#include <ctype.h>
44#include <inttypes.h>
45#include <openssl/aes.h>
46#include <openssl/md5.h>
47
48#define FLOGV(fmt, ...) ALOGV("[fetcher-%d] " fmt, mFetcherID, ##__VA_ARGS__)
49#define FSLOGV(stream, fmt, ...) ALOGV("[fetcher-%d] [%s] " fmt, mFetcherID, \
50         LiveSession::getNameForStream(stream), ##__VA_ARGS__)
51
52namespace android {
53
54// static
55const int64_t PlaylistFetcher::kMinBufferedDurationUs = 30000000ll;
56const int64_t PlaylistFetcher::kMaxMonitorDelayUs = 3000000ll;
57// LCM of 188 (size of a TS packet) & 1k works well
58const int32_t PlaylistFetcher::kDownloadBlockSize = 47 * 1024;
59
60struct PlaylistFetcher::DownloadState : public RefBase {
61    DownloadState();
62    void resetState();
63    bool hasSavedState() const;
64    void restoreState(
65            AString &uri,
66            sp<AMessage> &itemMeta,
67            sp<ABuffer> &buffer,
68            sp<ABuffer> &tsBuffer,
69            int32_t &firstSeqNumberInPlaylist,
70            int32_t &lastSeqNumberInPlaylist);
71    void saveState(
72            AString &uri,
73            sp<AMessage> &itemMeta,
74            sp<ABuffer> &buffer,
75            sp<ABuffer> &tsBuffer,
76            int32_t &firstSeqNumberInPlaylist,
77            int32_t &lastSeqNumberInPlaylist);
78
79private:
80    bool mHasSavedState;
81    AString mUri;
82    sp<AMessage> mItemMeta;
83    sp<ABuffer> mBuffer;
84    sp<ABuffer> mTsBuffer;
85    int32_t mFirstSeqNumberInPlaylist;
86    int32_t mLastSeqNumberInPlaylist;
87};
88
89PlaylistFetcher::DownloadState::DownloadState() {
90    resetState();
91}
92
93bool PlaylistFetcher::DownloadState::hasSavedState() const {
94    return mHasSavedState;
95}
96
97void PlaylistFetcher::DownloadState::resetState() {
98    mHasSavedState = false;
99
100    mUri.clear();
101    mItemMeta = NULL;
102    mBuffer = NULL;
103    mTsBuffer = NULL;
104    mFirstSeqNumberInPlaylist = 0;
105    mLastSeqNumberInPlaylist = 0;
106}
107
108void PlaylistFetcher::DownloadState::restoreState(
109        AString &uri,
110        sp<AMessage> &itemMeta,
111        sp<ABuffer> &buffer,
112        sp<ABuffer> &tsBuffer,
113        int32_t &firstSeqNumberInPlaylist,
114        int32_t &lastSeqNumberInPlaylist) {
115    if (!mHasSavedState) {
116        return;
117    }
118
119    uri = mUri;
120    itemMeta = mItemMeta;
121    buffer = mBuffer;
122    tsBuffer = mTsBuffer;
123    firstSeqNumberInPlaylist = mFirstSeqNumberInPlaylist;
124    lastSeqNumberInPlaylist = mLastSeqNumberInPlaylist;
125
126    resetState();
127}
128
129void PlaylistFetcher::DownloadState::saveState(
130        AString &uri,
131        sp<AMessage> &itemMeta,
132        sp<ABuffer> &buffer,
133        sp<ABuffer> &tsBuffer,
134        int32_t &firstSeqNumberInPlaylist,
135        int32_t &lastSeqNumberInPlaylist) {
136    mHasSavedState = true;
137
138    mUri = uri;
139    mItemMeta = itemMeta;
140    mBuffer = buffer;
141    mTsBuffer = tsBuffer;
142    mFirstSeqNumberInPlaylist = firstSeqNumberInPlaylist;
143    mLastSeqNumberInPlaylist = lastSeqNumberInPlaylist;
144}
145
146PlaylistFetcher::PlaylistFetcher(
147        const sp<AMessage> &notify,
148        const sp<LiveSession> &session,
149        const char *uri,
150        int32_t id,
151        int32_t subtitleGeneration)
152    : mNotify(notify),
153      mSession(session),
154      mURI(uri),
155      mFetcherID(id),
156      mStreamTypeMask(0),
157      mStartTimeUs(-1ll),
158      mSegmentStartTimeUs(-1ll),
159      mDiscontinuitySeq(-1ll),
160      mStartTimeUsRelative(false),
161      mLastPlaylistFetchTimeUs(-1ll),
162      mSeqNumber(-1),
163      mNumRetries(0),
164      mStartup(true),
165      mIDRFound(false),
166      mSeekMode(LiveSession::kSeekModeExactPosition),
167      mTimeChangeSignaled(false),
168      mNextPTSTimeUs(-1ll),
169      mMonitorQueueGeneration(0),
170      mSubtitleGeneration(subtitleGeneration),
171      mLastDiscontinuitySeq(-1ll),
172      mRefreshState(INITIAL_MINIMUM_RELOAD_DELAY),
173      mFirstPTSValid(false),
174      mFirstTimeUs(-1ll),
175      mVideoBuffer(new AnotherPacketSource(NULL)),
176      mThresholdRatio(-1.0f),
177      mDownloadState(new DownloadState()) {
178    memset(mPlaylistHash, 0, sizeof(mPlaylistHash));
179    mHTTPDataSource = mSession->getHTTPDataSource();
180}
181
182PlaylistFetcher::~PlaylistFetcher() {
183}
184
185int32_t PlaylistFetcher::getFetcherID() const {
186    return mFetcherID;
187}
188
189int64_t PlaylistFetcher::getSegmentStartTimeUs(int32_t seqNumber) const {
190    CHECK(mPlaylist != NULL);
191
192    int32_t firstSeqNumberInPlaylist;
193    if (mPlaylist->meta() == NULL || !mPlaylist->meta()->findInt32(
194                "media-sequence", &firstSeqNumberInPlaylist)) {
195        firstSeqNumberInPlaylist = 0;
196    }
197
198    int32_t lastSeqNumberInPlaylist =
199        firstSeqNumberInPlaylist + (int32_t)mPlaylist->size() - 1;
200
201    CHECK_GE(seqNumber, firstSeqNumberInPlaylist);
202    CHECK_LE(seqNumber, lastSeqNumberInPlaylist);
203
204    int64_t segmentStartUs = 0ll;
205    for (int32_t index = 0;
206            index < seqNumber - firstSeqNumberInPlaylist; ++index) {
207        sp<AMessage> itemMeta;
208        CHECK(mPlaylist->itemAt(
209                    index, NULL /* uri */, &itemMeta));
210
211        int64_t itemDurationUs;
212        CHECK(itemMeta->findInt64("durationUs", &itemDurationUs));
213
214        segmentStartUs += itemDurationUs;
215    }
216
217    return segmentStartUs;
218}
219
220int64_t PlaylistFetcher::getSegmentDurationUs(int32_t seqNumber) const {
221    CHECK(mPlaylist != NULL);
222
223    int32_t firstSeqNumberInPlaylist;
224    if (mPlaylist->meta() == NULL || !mPlaylist->meta()->findInt32(
225                "media-sequence", &firstSeqNumberInPlaylist)) {
226        firstSeqNumberInPlaylist = 0;
227    }
228
229    int32_t lastSeqNumberInPlaylist =
230        firstSeqNumberInPlaylist + (int32_t)mPlaylist->size() - 1;
231
232    CHECK_GE(seqNumber, firstSeqNumberInPlaylist);
233    CHECK_LE(seqNumber, lastSeqNumberInPlaylist);
234
235    int32_t index = seqNumber - firstSeqNumberInPlaylist;
236    sp<AMessage> itemMeta;
237    CHECK(mPlaylist->itemAt(
238                index, NULL /* uri */, &itemMeta));
239
240    int64_t itemDurationUs;
241    CHECK(itemMeta->findInt64("durationUs", &itemDurationUs));
242
243    return itemDurationUs;
244}
245
246int64_t PlaylistFetcher::delayUsToRefreshPlaylist() const {
247    int64_t nowUs = ALooper::GetNowUs();
248
249    if (mPlaylist == NULL || mLastPlaylistFetchTimeUs < 0ll) {
250        CHECK_EQ((int)mRefreshState, (int)INITIAL_MINIMUM_RELOAD_DELAY);
251        return 0ll;
252    }
253
254    if (mPlaylist->isComplete()) {
255        return (~0llu >> 1);
256    }
257
258    int32_t targetDurationSecs;
259    CHECK(mPlaylist->meta()->findInt32("target-duration", &targetDurationSecs));
260
261    int64_t targetDurationUs = targetDurationSecs * 1000000ll;
262
263    int64_t minPlaylistAgeUs;
264
265    switch (mRefreshState) {
266        case INITIAL_MINIMUM_RELOAD_DELAY:
267        {
268            size_t n = mPlaylist->size();
269            if (n > 0) {
270                sp<AMessage> itemMeta;
271                CHECK(mPlaylist->itemAt(n - 1, NULL /* uri */, &itemMeta));
272
273                int64_t itemDurationUs;
274                CHECK(itemMeta->findInt64("durationUs", &itemDurationUs));
275
276                minPlaylistAgeUs = itemDurationUs;
277                break;
278            }
279
280            // fall through
281        }
282
283        case FIRST_UNCHANGED_RELOAD_ATTEMPT:
284        {
285            minPlaylistAgeUs = targetDurationUs / 2;
286            break;
287        }
288
289        case SECOND_UNCHANGED_RELOAD_ATTEMPT:
290        {
291            minPlaylistAgeUs = (targetDurationUs * 3) / 2;
292            break;
293        }
294
295        case THIRD_UNCHANGED_RELOAD_ATTEMPT:
296        {
297            minPlaylistAgeUs = targetDurationUs * 3;
298            break;
299        }
300
301        default:
302            TRESPASS();
303            break;
304    }
305
306    int64_t delayUs = mLastPlaylistFetchTimeUs + minPlaylistAgeUs - nowUs;
307    return delayUs > 0ll ? delayUs : 0ll;
308}
309
310status_t PlaylistFetcher::decryptBuffer(
311        size_t playlistIndex, const sp<ABuffer> &buffer,
312        bool first) {
313    sp<AMessage> itemMeta;
314    bool found = false;
315    AString method;
316
317    for (ssize_t i = playlistIndex; i >= 0; --i) {
318        AString uri;
319        CHECK(mPlaylist->itemAt(i, &uri, &itemMeta));
320
321        if (itemMeta->findString("cipher-method", &method)) {
322            found = true;
323            break;
324        }
325    }
326
327    if (!found) {
328        method = "NONE";
329    }
330    buffer->meta()->setString("cipher-method", method.c_str());
331
332    if (method == "NONE") {
333        return OK;
334    } else if (!(method == "AES-128")) {
335        ALOGE("Unsupported cipher method '%s'", method.c_str());
336        return ERROR_UNSUPPORTED;
337    }
338
339    AString keyURI;
340    if (!itemMeta->findString("cipher-uri", &keyURI)) {
341        ALOGE("Missing key uri");
342        return ERROR_MALFORMED;
343    }
344
345    ssize_t index = mAESKeyForURI.indexOfKey(keyURI);
346
347    sp<ABuffer> key;
348    if (index >= 0) {
349        key = mAESKeyForURI.valueAt(index);
350    } else {
351        ssize_t err = mSession->fetchFile(keyURI.c_str(), &key);
352
353        if (err < 0) {
354            ALOGE("failed to fetch cipher key from '%s'.", keyURI.c_str());
355            return ERROR_IO;
356        } else if (key->size() != 16) {
357            ALOGE("key file '%s' wasn't 16 bytes in size.", keyURI.c_str());
358            return ERROR_MALFORMED;
359        }
360
361        mAESKeyForURI.add(keyURI, key);
362    }
363
364    AES_KEY aes_key;
365    if (AES_set_decrypt_key(key->data(), 128, &aes_key) != 0) {
366        ALOGE("failed to set AES decryption key.");
367        return UNKNOWN_ERROR;
368    }
369
370    size_t n = buffer->size();
371    if (!n) {
372        return OK;
373    }
374    CHECK(n % 16 == 0);
375
376    if (first) {
377        // If decrypting the first block in a file, read the iv from the manifest
378        // or derive the iv from the file's sequence number.
379
380        AString iv;
381        if (itemMeta->findString("cipher-iv", &iv)) {
382            if ((!iv.startsWith("0x") && !iv.startsWith("0X"))
383                    || iv.size() != 16 * 2 + 2) {
384                ALOGE("malformed cipher IV '%s'.", iv.c_str());
385                return ERROR_MALFORMED;
386            }
387
388            memset(mAESInitVec, 0, sizeof(mAESInitVec));
389            for (size_t i = 0; i < 16; ++i) {
390                char c1 = tolower(iv.c_str()[2 + 2 * i]);
391                char c2 = tolower(iv.c_str()[3 + 2 * i]);
392                if (!isxdigit(c1) || !isxdigit(c2)) {
393                    ALOGE("malformed cipher IV '%s'.", iv.c_str());
394                    return ERROR_MALFORMED;
395                }
396                uint8_t nibble1 = isdigit(c1) ? c1 - '0' : c1 - 'a' + 10;
397                uint8_t nibble2 = isdigit(c2) ? c2 - '0' : c2 - 'a' + 10;
398
399                mAESInitVec[i] = nibble1 << 4 | nibble2;
400            }
401        } else {
402            memset(mAESInitVec, 0, sizeof(mAESInitVec));
403            mAESInitVec[15] = mSeqNumber & 0xff;
404            mAESInitVec[14] = (mSeqNumber >> 8) & 0xff;
405            mAESInitVec[13] = (mSeqNumber >> 16) & 0xff;
406            mAESInitVec[12] = (mSeqNumber >> 24) & 0xff;
407        }
408    }
409
410    AES_cbc_encrypt(
411            buffer->data(), buffer->data(), buffer->size(),
412            &aes_key, mAESInitVec, AES_DECRYPT);
413
414    return OK;
415}
416
417status_t PlaylistFetcher::checkDecryptPadding(const sp<ABuffer> &buffer) {
418    AString method;
419    CHECK(buffer->meta()->findString("cipher-method", &method));
420    if (method == "NONE") {
421        return OK;
422    }
423
424    uint8_t padding = 0;
425    if (buffer->size() > 0) {
426        padding = buffer->data()[buffer->size() - 1];
427    }
428
429    if (padding > 16) {
430        return ERROR_MALFORMED;
431    }
432
433    for (size_t i = buffer->size() - padding; i < padding; i++) {
434        if (buffer->data()[i] != padding) {
435            return ERROR_MALFORMED;
436        }
437    }
438
439    buffer->setRange(buffer->offset(), buffer->size() - padding);
440    return OK;
441}
442
443void PlaylistFetcher::postMonitorQueue(int64_t delayUs, int64_t minDelayUs) {
444    int64_t maxDelayUs = delayUsToRefreshPlaylist();
445    if (maxDelayUs < minDelayUs) {
446        maxDelayUs = minDelayUs;
447    }
448    if (delayUs > maxDelayUs) {
449        FLOGV("Need to refresh playlist in %lld", (long long)maxDelayUs);
450        delayUs = maxDelayUs;
451    }
452    sp<AMessage> msg = new AMessage(kWhatMonitorQueue, this);
453    msg->setInt32("generation", mMonitorQueueGeneration);
454    msg->post(delayUs);
455}
456
457void PlaylistFetcher::cancelMonitorQueue() {
458    ++mMonitorQueueGeneration;
459}
460
461void PlaylistFetcher::setStoppingThreshold(float thresholdRatio) {
462    AutoMutex _l(mThresholdLock);
463    if (mStreamTypeMask == LiveSession::STREAMTYPE_SUBTITLES) {
464        return;
465    }
466    mThresholdRatio = thresholdRatio;
467}
468
469void PlaylistFetcher::startAsync(
470        const sp<AnotherPacketSource> &audioSource,
471        const sp<AnotherPacketSource> &videoSource,
472        const sp<AnotherPacketSource> &subtitleSource,
473        int64_t startTimeUs,
474        int64_t segmentStartTimeUs,
475        int32_t startDiscontinuitySeq,
476        LiveSession::SeekMode seekMode) {
477    sp<AMessage> msg = new AMessage(kWhatStart, this);
478
479    uint32_t streamTypeMask = 0ul;
480
481    if (audioSource != NULL) {
482        msg->setPointer("audioSource", audioSource.get());
483        streamTypeMask |= LiveSession::STREAMTYPE_AUDIO;
484    }
485
486    if (videoSource != NULL) {
487        msg->setPointer("videoSource", videoSource.get());
488        streamTypeMask |= LiveSession::STREAMTYPE_VIDEO;
489    }
490
491    if (subtitleSource != NULL) {
492        msg->setPointer("subtitleSource", subtitleSource.get());
493        streamTypeMask |= LiveSession::STREAMTYPE_SUBTITLES;
494    }
495
496    msg->setInt32("streamTypeMask", streamTypeMask);
497    msg->setInt64("startTimeUs", startTimeUs);
498    msg->setInt64("segmentStartTimeUs", segmentStartTimeUs);
499    msg->setInt32("startDiscontinuitySeq", startDiscontinuitySeq);
500    msg->setInt32("seekMode", seekMode);
501    msg->post();
502}
503
504void PlaylistFetcher::pauseAsync(float thresholdRatio) {
505    if (thresholdRatio >= 0.0f) {
506        setStoppingThreshold(thresholdRatio);
507    }
508    (new AMessage(kWhatPause, this))->post();
509}
510
511void PlaylistFetcher::stopAsync(bool clear) {
512    setStoppingThreshold(0.0f);
513
514    sp<AMessage> msg = new AMessage(kWhatStop, this);
515    msg->setInt32("clear", clear);
516    msg->post();
517}
518
519void PlaylistFetcher::resumeUntilAsync(const sp<AMessage> &params) {
520    FLOGV("resumeUntilAsync: params=%s", params->debugString().c_str());
521
522    AMessage* msg = new AMessage(kWhatResumeUntil, this);
523    msg->setMessage("params", params);
524    msg->post();
525}
526
527void PlaylistFetcher::onMessageReceived(const sp<AMessage> &msg) {
528    switch (msg->what()) {
529        case kWhatStart:
530        {
531            status_t err = onStart(msg);
532
533            sp<AMessage> notify = mNotify->dup();
534            notify->setInt32("what", kWhatStarted);
535            notify->setInt32("err", err);
536            notify->post();
537            break;
538        }
539
540        case kWhatPause:
541        {
542            onPause();
543
544            sp<AMessage> notify = mNotify->dup();
545            notify->setInt32("what", kWhatPaused);
546            notify->setInt32("seekMode",
547                    mDownloadState->hasSavedState()
548                    ? LiveSession::kSeekModeNextSample
549                    : LiveSession::kSeekModeNextSegment);
550            notify->post();
551            break;
552        }
553
554        case kWhatStop:
555        {
556            onStop(msg);
557
558            sp<AMessage> notify = mNotify->dup();
559            notify->setInt32("what", kWhatStopped);
560            notify->post();
561            break;
562        }
563
564        case kWhatMonitorQueue:
565        case kWhatDownloadNext:
566        {
567            int32_t generation;
568            CHECK(msg->findInt32("generation", &generation));
569
570            if (generation != mMonitorQueueGeneration) {
571                // Stale event
572                break;
573            }
574
575            if (msg->what() == kWhatMonitorQueue) {
576                onMonitorQueue();
577            } else {
578                onDownloadNext();
579            }
580            break;
581        }
582
583        case kWhatResumeUntil:
584        {
585            onResumeUntil(msg);
586            break;
587        }
588
589        default:
590            TRESPASS();
591    }
592}
593
594status_t PlaylistFetcher::onStart(const sp<AMessage> &msg) {
595    mPacketSources.clear();
596    mStopParams.clear();
597    mStartTimeUsNotify = mNotify->dup();
598    mStartTimeUsNotify->setInt32("what", kWhatStartedAt);
599    mStartTimeUsNotify->setString("uri", mURI);
600
601    uint32_t streamTypeMask;
602    CHECK(msg->findInt32("streamTypeMask", (int32_t *)&streamTypeMask));
603
604    int64_t startTimeUs;
605    int64_t segmentStartTimeUs;
606    int32_t startDiscontinuitySeq;
607    int32_t seekMode;
608    CHECK(msg->findInt64("startTimeUs", &startTimeUs));
609    CHECK(msg->findInt64("segmentStartTimeUs", &segmentStartTimeUs));
610    CHECK(msg->findInt32("startDiscontinuitySeq", &startDiscontinuitySeq));
611    CHECK(msg->findInt32("seekMode", &seekMode));
612
613    if (streamTypeMask & LiveSession::STREAMTYPE_AUDIO) {
614        void *ptr;
615        CHECK(msg->findPointer("audioSource", &ptr));
616
617        mPacketSources.add(
618                LiveSession::STREAMTYPE_AUDIO,
619                static_cast<AnotherPacketSource *>(ptr));
620    }
621
622    if (streamTypeMask & LiveSession::STREAMTYPE_VIDEO) {
623        void *ptr;
624        CHECK(msg->findPointer("videoSource", &ptr));
625
626        mPacketSources.add(
627                LiveSession::STREAMTYPE_VIDEO,
628                static_cast<AnotherPacketSource *>(ptr));
629    }
630
631    if (streamTypeMask & LiveSession::STREAMTYPE_SUBTITLES) {
632        void *ptr;
633        CHECK(msg->findPointer("subtitleSource", &ptr));
634
635        mPacketSources.add(
636                LiveSession::STREAMTYPE_SUBTITLES,
637                static_cast<AnotherPacketSource *>(ptr));
638    }
639
640    mStreamTypeMask = streamTypeMask;
641
642    mSegmentStartTimeUs = segmentStartTimeUs;
643
644    if (startDiscontinuitySeq >= 0) {
645        mDiscontinuitySeq = startDiscontinuitySeq;
646    }
647
648    mRefreshState = INITIAL_MINIMUM_RELOAD_DELAY;
649    mSeekMode = (LiveSession::SeekMode) seekMode;
650
651    if (startTimeUs >= 0 || mSeekMode == LiveSession::kSeekModeNextSample) {
652        mStartup = true;
653        mIDRFound = false;
654        mVideoBuffer->clear();
655    }
656
657    if (startTimeUs >= 0) {
658        mStartTimeUs = startTimeUs;
659        mFirstPTSValid = false;
660        mSeqNumber = -1;
661        mTimeChangeSignaled = false;
662        mDownloadState->resetState();
663    }
664
665    postMonitorQueue();
666
667    return OK;
668}
669
670void PlaylistFetcher::onPause() {
671    cancelMonitorQueue();
672    mLastDiscontinuitySeq = mDiscontinuitySeq;
673
674    setStoppingThreshold(-1.0f);
675}
676
677void PlaylistFetcher::onStop(const sp<AMessage> &msg) {
678    cancelMonitorQueue();
679
680    int32_t clear;
681    CHECK(msg->findInt32("clear", &clear));
682    if (clear) {
683        for (size_t i = 0; i < mPacketSources.size(); i++) {
684            sp<AnotherPacketSource> packetSource = mPacketSources.valueAt(i);
685            packetSource->clear();
686        }
687    }
688
689    // close off the connection after use
690    mHTTPDataSource->disconnect();
691
692    mDownloadState->resetState();
693    mPacketSources.clear();
694    mStreamTypeMask = 0;
695
696    setStoppingThreshold(-1.0f);
697}
698
699// Resume until we have reached the boundary timestamps listed in `msg`; when
700// the remaining time is too short (within a resume threshold) stop immediately
701// instead.
702status_t PlaylistFetcher::onResumeUntil(const sp<AMessage> &msg) {
703    sp<AMessage> params;
704    CHECK(msg->findMessage("params", &params));
705
706    mStopParams = params;
707    onDownloadNext();
708
709    return OK;
710}
711
712void PlaylistFetcher::notifyStopReached() {
713    sp<AMessage> notify = mNotify->dup();
714    notify->setInt32("what", kWhatStopReached);
715    notify->post();
716}
717
718void PlaylistFetcher::notifyError(status_t err) {
719    sp<AMessage> notify = mNotify->dup();
720    notify->setInt32("what", kWhatError);
721    notify->setInt32("err", err);
722    notify->post();
723}
724
725void PlaylistFetcher::queueDiscontinuity(
726        ATSParser::DiscontinuityType type, const sp<AMessage> &extra) {
727    for (size_t i = 0; i < mPacketSources.size(); ++i) {
728        // do not discard buffer upon #EXT-X-DISCONTINUITY tag
729        // (seek will discard buffer by abandoning old fetchers)
730        mPacketSources.valueAt(i)->queueDiscontinuity(
731                type, extra, false /* discard */);
732    }
733}
734
735void PlaylistFetcher::onMonitorQueue() {
736    bool downloadMore = false;
737
738    // in the middle of an unfinished download, delay
739    // playlist refresh as it'll change seq numbers
740    if (!mDownloadState->hasSavedState()) {
741        refreshPlaylist();
742    }
743
744    int32_t targetDurationSecs;
745    int64_t targetDurationUs = kMinBufferedDurationUs;
746    if (mPlaylist != NULL) {
747        if (mPlaylist->meta() == NULL || !mPlaylist->meta()->findInt32(
748                "target-duration", &targetDurationSecs)) {
749            ALOGE("Playlist is missing required EXT-X-TARGETDURATION tag");
750            notifyError(ERROR_MALFORMED);
751            return;
752        }
753        targetDurationUs = targetDurationSecs * 1000000ll;
754    }
755
756    int64_t bufferedDurationUs = 0ll;
757    status_t finalResult = OK;
758    if (mStreamTypeMask == LiveSession::STREAMTYPE_SUBTITLES) {
759        sp<AnotherPacketSource> packetSource =
760            mPacketSources.valueFor(LiveSession::STREAMTYPE_SUBTITLES);
761
762        bufferedDurationUs =
763                packetSource->getBufferedDurationUs(&finalResult);
764    } else {
765        // Use min stream duration, but ignore streams that never have any packet
766        // enqueued to prevent us from waiting on a non-existent stream;
767        // when we cannot make out from the manifest what streams are included in
768        // a playlist we might assume extra streams.
769        bufferedDurationUs = -1ll;
770        for (size_t i = 0; i < mPacketSources.size(); ++i) {
771            if ((mStreamTypeMask & mPacketSources.keyAt(i)) == 0
772                    || mPacketSources[i]->getLatestEnqueuedMeta() == NULL) {
773                continue;
774            }
775
776            int64_t bufferedStreamDurationUs =
777                mPacketSources.valueAt(i)->getBufferedDurationUs(&finalResult);
778
779            FSLOGV(mPacketSources.keyAt(i), "buffered %lld", (long long)bufferedStreamDurationUs);
780
781            if (bufferedDurationUs == -1ll
782                 || bufferedStreamDurationUs < bufferedDurationUs) {
783                bufferedDurationUs = bufferedStreamDurationUs;
784            }
785        }
786        if (bufferedDurationUs == -1ll) {
787            bufferedDurationUs = 0ll;
788        }
789    }
790
791    if (finalResult == OK && bufferedDurationUs < kMinBufferedDurationUs) {
792        FLOGV("monitoring, buffered=%lld < %lld",
793                (long long)bufferedDurationUs, (long long)kMinBufferedDurationUs);
794
795        // delay the next download slightly; hopefully this gives other concurrent fetchers
796        // a better chance to run.
797        // onDownloadNext();
798        sp<AMessage> msg = new AMessage(kWhatDownloadNext, this);
799        msg->setInt32("generation", mMonitorQueueGeneration);
800        msg->post(1000l);
801    } else {
802        // We'd like to maintain buffering above durationToBufferUs, so try
803        // again when buffer just about to go below durationToBufferUs
804        // (or after targetDurationUs / 2, whichever is smaller).
805        int64_t delayUs = bufferedDurationUs - kMinBufferedDurationUs + 1000000ll;
806        if (delayUs > targetDurationUs / 2) {
807            delayUs = targetDurationUs / 2;
808        }
809
810        FLOGV("pausing for %lld, buffered=%lld > %lld",
811                (long long)delayUs,
812                (long long)bufferedDurationUs,
813                (long long)kMinBufferedDurationUs);
814
815        postMonitorQueue(delayUs);
816    }
817}
818
819status_t PlaylistFetcher::refreshPlaylist() {
820    if (delayUsToRefreshPlaylist() <= 0) {
821        bool unchanged;
822        sp<M3UParser> playlist = mSession->fetchPlaylist(
823                mURI.c_str(), mPlaylistHash, &unchanged);
824
825        if (playlist == NULL) {
826            if (unchanged) {
827                // We succeeded in fetching the playlist, but it was
828                // unchanged from the last time we tried.
829
830                if (mRefreshState != THIRD_UNCHANGED_RELOAD_ATTEMPT) {
831                    mRefreshState = (RefreshState)(mRefreshState + 1);
832                }
833            } else {
834                ALOGE("failed to load playlist at url '%s'", uriDebugString(mURI).c_str());
835                return ERROR_IO;
836            }
837        } else {
838            mRefreshState = INITIAL_MINIMUM_RELOAD_DELAY;
839            mPlaylist = playlist;
840
841            if (mPlaylist->isComplete() || mPlaylist->isEvent()) {
842                updateDuration();
843            }
844            // Notify LiveSession to use target-duration based buffering level
845            // for up/down switch. Default LiveSession::kUpSwitchMark may not
846            // be reachable for live streams, as our max buffering amount is
847            // limited to 3 segments.
848            if (!mPlaylist->isComplete()) {
849                updateTargetDuration();
850            }
851        }
852
853        mLastPlaylistFetchTimeUs = ALooper::GetNowUs();
854    }
855    return OK;
856}
857
858// static
859bool PlaylistFetcher::bufferStartsWithTsSyncByte(const sp<ABuffer>& buffer) {
860    return buffer->size() > 0 && buffer->data()[0] == 0x47;
861}
862
863bool PlaylistFetcher::shouldPauseDownload() {
864    if (mStreamTypeMask == LiveSession::STREAMTYPE_SUBTITLES) {
865        // doesn't apply to subtitles
866        return false;
867    }
868
869    // Calculate threshold to abort current download
870    int32_t targetDurationSecs;
871    CHECK(mPlaylist->meta()->findInt32("target-duration", &targetDurationSecs));
872    int64_t targetDurationUs = targetDurationSecs * 1000000ll;
873    int64_t thresholdUs = -1;
874    {
875        AutoMutex _l(mThresholdLock);
876        thresholdUs = (mThresholdRatio < 0.0f) ?
877                -1ll : mThresholdRatio * targetDurationUs;
878    }
879
880    if (thresholdUs < 0) {
881        // never abort
882        return false;
883    } else if (thresholdUs == 0) {
884        // immediately abort
885        return true;
886    }
887
888    // now we have a positive thresholdUs, abort if remaining
889    // portion to download is over that threshold.
890    if (mSegmentFirstPTS < 0) {
891        // this means we haven't even find the first access unit,
892        // abort now as we must be very far away from the end.
893        return true;
894    }
895    int64_t lastEnqueueUs = mSegmentFirstPTS;
896    for (size_t i = 0; i < mPacketSources.size(); ++i) {
897        if ((mStreamTypeMask & mPacketSources.keyAt(i)) == 0) {
898            continue;
899        }
900        sp<AMessage> meta = mPacketSources[i]->getLatestEnqueuedMeta();
901        int32_t type;
902        if (meta == NULL || meta->findInt32("discontinuity", &type)) {
903            continue;
904        }
905        int64_t tmpUs;
906        CHECK(meta->findInt64("timeUs", &tmpUs));
907        if (tmpUs > lastEnqueueUs) {
908            lastEnqueueUs = tmpUs;
909        }
910    }
911    lastEnqueueUs -= mSegmentFirstPTS;
912
913    FLOGV("%spausing now, thresholdUs %lld, remaining %lld",
914            targetDurationUs - lastEnqueueUs > thresholdUs ? "" : "not ",
915            (long long)thresholdUs,
916            (long long)(targetDurationUs - lastEnqueueUs));
917
918    if (targetDurationUs - lastEnqueueUs > thresholdUs) {
919        return true;
920    }
921    return false;
922}
923
924bool PlaylistFetcher::initDownloadState(
925        AString &uri,
926        sp<AMessage> &itemMeta,
927        int32_t &firstSeqNumberInPlaylist,
928        int32_t &lastSeqNumberInPlaylist) {
929    status_t err = refreshPlaylist();
930    firstSeqNumberInPlaylist = 0;
931    lastSeqNumberInPlaylist = 0;
932    bool discontinuity = false;
933
934    if (mPlaylist != NULL) {
935        if (mPlaylist->meta() != NULL) {
936            mPlaylist->meta()->findInt32("media-sequence", &firstSeqNumberInPlaylist);
937        }
938
939        lastSeqNumberInPlaylist =
940                firstSeqNumberInPlaylist + (int32_t)mPlaylist->size() - 1;
941
942        if (mDiscontinuitySeq < 0) {
943            mDiscontinuitySeq = mPlaylist->getDiscontinuitySeq();
944        }
945    }
946
947    mSegmentFirstPTS = -1ll;
948
949    if (mPlaylist != NULL && mSeqNumber < 0) {
950        CHECK_GE(mStartTimeUs, 0ll);
951
952        if (mSegmentStartTimeUs < 0) {
953            if (!mPlaylist->isComplete() && !mPlaylist->isEvent()) {
954                // If this is a live session, start 3 segments from the end on connect
955                mSeqNumber = lastSeqNumberInPlaylist - 3;
956                if (mSeqNumber < firstSeqNumberInPlaylist) {
957                    mSeqNumber = firstSeqNumberInPlaylist;
958                }
959            } else {
960                // When seeking mSegmentStartTimeUs is unavailable (< 0), we
961                // use mStartTimeUs (client supplied timestamp) to determine both start segment
962                // and relative position inside a segment
963                mSeqNumber = getSeqNumberForTime(mStartTimeUs);
964                mStartTimeUs -= getSegmentStartTimeUs(mSeqNumber);
965            }
966            mStartTimeUsRelative = true;
967            FLOGV("Initial sequence number for time %lld is %d from (%d .. %d)",
968                    (long long)mStartTimeUs, mSeqNumber, firstSeqNumberInPlaylist,
969                    lastSeqNumberInPlaylist);
970        } else {
971            // When adapting or track switching, mSegmentStartTimeUs (relative
972            // to media time 0) is used to determine the start segment; mStartTimeUs (absolute
973            // timestamps coming from the media container) is used to determine the position
974            // inside a segments.
975            mSeqNumber = getSeqNumberForTime(mSegmentStartTimeUs);
976            if (mStreamTypeMask != LiveSession::STREAMTYPE_SUBTITLES
977                    && mSeekMode != LiveSession::kSeekModeNextSample) {
978                // avoid double fetch/decode
979                mSeqNumber += 1;
980            }
981            ssize_t minSeq = getSeqNumberForDiscontinuity(mDiscontinuitySeq);
982            if (mSeqNumber < minSeq) {
983                mSeqNumber = minSeq;
984            }
985
986            if (mSeqNumber < firstSeqNumberInPlaylist) {
987                mSeqNumber = firstSeqNumberInPlaylist;
988            }
989
990            if (mSeqNumber > lastSeqNumberInPlaylist) {
991                mSeqNumber = lastSeqNumberInPlaylist;
992            }
993            FLOGV("Initial sequence number is %d from (%d .. %d)",
994                    mSeqNumber, firstSeqNumberInPlaylist,
995                    lastSeqNumberInPlaylist);
996        }
997    }
998
999    // if mPlaylist is NULL then err must be non-OK; but the other way around might not be true
1000    if (mSeqNumber < firstSeqNumberInPlaylist
1001            || mSeqNumber > lastSeqNumberInPlaylist
1002            || err != OK) {
1003        if ((err != OK || !mPlaylist->isComplete()) && mNumRetries < kMaxNumRetries) {
1004            ++mNumRetries;
1005
1006            if (mSeqNumber > lastSeqNumberInPlaylist || err != OK) {
1007                // make sure we reach this retry logic on refresh failures
1008                // by adding an err != OK clause to all enclosing if's.
1009
1010                // refresh in increasing fraction (1/2, 1/3, ...) of the
1011                // playlist's target duration or 3 seconds, whichever is less
1012                int64_t delayUs = kMaxMonitorDelayUs;
1013                if (mPlaylist != NULL && mPlaylist->meta() != NULL) {
1014                    int32_t targetDurationSecs;
1015                    CHECK(mPlaylist->meta()->findInt32("target-duration", &targetDurationSecs));
1016                    delayUs = mPlaylist->size() * targetDurationSecs *
1017                            1000000ll / (1 + mNumRetries);
1018                }
1019                if (delayUs > kMaxMonitorDelayUs) {
1020                    delayUs = kMaxMonitorDelayUs;
1021                }
1022                FLOGV("sequence number high: %d from (%d .. %d), "
1023                      "monitor in %lld (retry=%d)",
1024                        mSeqNumber, firstSeqNumberInPlaylist,
1025                        lastSeqNumberInPlaylist, (long long)delayUs, mNumRetries);
1026                postMonitorQueue(delayUs);
1027                return false;
1028            }
1029
1030            if (err != OK) {
1031                notifyError(err);
1032                return false;
1033            }
1034
1035            // we've missed the boat, let's start 3 segments prior to the latest sequence
1036            // number available and signal a discontinuity.
1037
1038            ALOGI("We've missed the boat, restarting playback."
1039                  "  mStartup=%d, was  looking for %d in %d-%d",
1040                    mStartup, mSeqNumber, firstSeqNumberInPlaylist,
1041                    lastSeqNumberInPlaylist);
1042            if (mStopParams != NULL) {
1043                // we should have kept on fetching until we hit the boundaries in mStopParams,
1044                // but since the segments we are supposed to fetch have already rolled off
1045                // the playlist, i.e. we have already missed the boat, we inevitably have to
1046                // skip.
1047                notifyStopReached();
1048                return false;
1049            }
1050            mSeqNumber = lastSeqNumberInPlaylist - 3;
1051            if (mSeqNumber < firstSeqNumberInPlaylist) {
1052                mSeqNumber = firstSeqNumberInPlaylist;
1053            }
1054            discontinuity = true;
1055
1056            // fall through
1057        } else {
1058            if (mPlaylist != NULL) {
1059                ALOGE("Cannot find sequence number %d in playlist "
1060                     "(contains %d - %d)",
1061                     mSeqNumber, firstSeqNumberInPlaylist,
1062                      firstSeqNumberInPlaylist + (int32_t)mPlaylist->size() - 1);
1063
1064                notifyError(ERROR_END_OF_STREAM);
1065            } else {
1066                // It's possible that we were never able to download the playlist.
1067                // In this case we should notify error, instead of EOS, as EOS during
1068                // prepare means we succeeded in downloading everything.
1069                ALOGE("Failed to download playlist!");
1070                notifyError(ERROR_IO);
1071            }
1072
1073            return false;
1074        }
1075    }
1076
1077    mNumRetries = 0;
1078
1079    CHECK(mPlaylist->itemAt(
1080                mSeqNumber - firstSeqNumberInPlaylist,
1081                &uri,
1082                &itemMeta));
1083
1084    CHECK(itemMeta->findInt32("discontinuity-sequence", &mDiscontinuitySeq));
1085
1086    int32_t val;
1087    if (itemMeta->findInt32("discontinuity", &val) && val != 0) {
1088        discontinuity = true;
1089    } else if (mLastDiscontinuitySeq >= 0
1090            && mDiscontinuitySeq != mLastDiscontinuitySeq) {
1091        // Seek jumped to a new discontinuity sequence. We need to signal
1092        // a format change to decoder. Decoder needs to shutdown and be
1093        // created again if seamless format change is unsupported.
1094        FLOGV("saw discontinuity: mStartup %d, mLastDiscontinuitySeq %d, "
1095                "mDiscontinuitySeq %d, mStartTimeUs %lld",
1096                mStartup, mLastDiscontinuitySeq, mDiscontinuitySeq, (long long)mStartTimeUs);
1097        discontinuity = true;
1098    }
1099    mLastDiscontinuitySeq = -1;
1100
1101    // decrypt a junk buffer to prefetch key; since a session uses only one http connection,
1102    // this avoids interleaved connections to the key and segment file.
1103    {
1104        sp<ABuffer> junk = new ABuffer(16);
1105        junk->setRange(0, 16);
1106        status_t err = decryptBuffer(mSeqNumber - firstSeqNumberInPlaylist, junk,
1107                true /* first */);
1108        if (err != OK) {
1109            notifyError(err);
1110            return false;
1111        }
1112    }
1113
1114    if ((mStartup && !mTimeChangeSignaled) || discontinuity) {
1115        // We need to signal a time discontinuity to ATSParser on the
1116        // first segment after start, or on a discontinuity segment.
1117        // Setting mNextPTSTimeUs informs extractAndQueueAccessUnitsXX()
1118        // to send the time discontinuity.
1119        if (mPlaylist->isComplete() || mPlaylist->isEvent()) {
1120            // If this was a live event this made no sense since
1121            // we don't have access to all the segment before the current
1122            // one.
1123            mNextPTSTimeUs = getSegmentStartTimeUs(mSeqNumber);
1124        }
1125
1126        // Setting mTimeChangeSignaled to true, so that if start time
1127        // searching goes into 2nd segment (without a discontinuity),
1128        // we don't reset time again. It causes corruption when pending
1129        // data in ATSParser is cleared.
1130        mTimeChangeSignaled = true;
1131    }
1132
1133    if (discontinuity) {
1134        ALOGI("queueing discontinuity (explicit=%d)", discontinuity);
1135
1136        // Signal a format discontinuity to ATSParser to clear partial data
1137        // from previous streams. Not doing this causes bitstream corruption.
1138        if (mTSParser != NULL) {
1139            mTSParser->signalDiscontinuity(
1140                    ATSParser::DISCONTINUITY_FORMATCHANGE, NULL /* extra */);
1141        }
1142
1143        queueDiscontinuity(
1144                ATSParser::DISCONTINUITY_FORMATCHANGE,
1145                NULL /* extra */);
1146
1147        if (mStartup && mStartTimeUsRelative && mFirstPTSValid) {
1148            // This means we guessed mStartTimeUs to be in the previous
1149            // segment (likely very close to the end), but either video or
1150            // audio has not found start by the end of that segment.
1151            //
1152            // If this new segment is not a discontinuity, keep searching.
1153            //
1154            // If this new segment even got a discontinuity marker, just
1155            // set mStartTimeUs=0, and take all samples from now on.
1156            mStartTimeUs = 0;
1157            mFirstPTSValid = false;
1158        }
1159    }
1160
1161    FLOGV("fetching segment %d from (%d .. %d)",
1162            mSeqNumber, firstSeqNumberInPlaylist, lastSeqNumberInPlaylist);
1163    return true;
1164}
1165
1166void PlaylistFetcher::onDownloadNext() {
1167    AString uri;
1168    sp<AMessage> itemMeta;
1169    sp<ABuffer> buffer;
1170    sp<ABuffer> tsBuffer;
1171    int32_t firstSeqNumberInPlaylist = 0;
1172    int32_t lastSeqNumberInPlaylist = 0;
1173    bool connectHTTP = true;
1174
1175    if (mDownloadState->hasSavedState()) {
1176        mDownloadState->restoreState(
1177                uri,
1178                itemMeta,
1179                buffer,
1180                tsBuffer,
1181                firstSeqNumberInPlaylist,
1182                lastSeqNumberInPlaylist);
1183        connectHTTP = false;
1184        FLOGV("resuming: '%s'", uri.c_str());
1185    } else {
1186        if (!initDownloadState(
1187                uri,
1188                itemMeta,
1189                firstSeqNumberInPlaylist,
1190                lastSeqNumberInPlaylist)) {
1191            return;
1192        }
1193        FLOGV("fetching: '%s'", uri.c_str());
1194    }
1195
1196    int64_t range_offset, range_length;
1197    if (!itemMeta->findInt64("range-offset", &range_offset)
1198            || !itemMeta->findInt64("range-length", &range_length)) {
1199        range_offset = 0;
1200        range_length = -1;
1201    }
1202
1203    // block-wise download
1204    bool shouldPause = false;
1205    ssize_t bytesRead;
1206    do {
1207        sp<DataSource> source = mHTTPDataSource;
1208
1209        int64_t startUs = ALooper::GetNowUs();
1210        bytesRead = mSession->fetchFile(
1211                uri.c_str(), &buffer, range_offset, range_length, kDownloadBlockSize,
1212                &source, NULL, connectHTTP);
1213
1214        // add sample for bandwidth estimation, excluding samples from subtitles (as
1215        // its too small), or during startup/resumeUntil (when we could have more than
1216        // one connection open which affects bandwidth)
1217        if (!mStartup && mStopParams == NULL && bytesRead > 0
1218                && (mStreamTypeMask
1219                        & (LiveSession::STREAMTYPE_AUDIO
1220                        | LiveSession::STREAMTYPE_VIDEO))) {
1221            int64_t delayUs = ALooper::GetNowUs() - startUs;
1222            mSession->addBandwidthMeasurement(bytesRead, delayUs);
1223
1224            if (delayUs > 2000000ll) {
1225                FLOGV("bytesRead %zd took %.2f seconds - abnormal bandwidth dip",
1226                        bytesRead, (double)delayUs / 1.0e6);
1227            }
1228        }
1229
1230        connectHTTP = false;
1231
1232        if (bytesRead < 0) {
1233            status_t err = bytesRead;
1234            ALOGE("failed to fetch .ts segment at url '%s'", uri.c_str());
1235            notifyError(err);
1236            return;
1237        }
1238
1239        CHECK(buffer != NULL);
1240
1241        size_t size = buffer->size();
1242        // Set decryption range.
1243        buffer->setRange(size - bytesRead, bytesRead);
1244        status_t err = decryptBuffer(mSeqNumber - firstSeqNumberInPlaylist, buffer,
1245                buffer->offset() == 0 /* first */);
1246        // Unset decryption range.
1247        buffer->setRange(0, size);
1248
1249        if (err != OK) {
1250            ALOGE("decryptBuffer failed w/ error %d", err);
1251
1252            notifyError(err);
1253            return;
1254        }
1255
1256        bool startUp = mStartup; // save current start up state
1257
1258        err = OK;
1259        if (bufferStartsWithTsSyncByte(buffer)) {
1260            // Incremental extraction is only supported for MPEG2 transport streams.
1261            if (tsBuffer == NULL) {
1262                tsBuffer = new ABuffer(buffer->data(), buffer->capacity());
1263                tsBuffer->setRange(0, 0);
1264            } else if (tsBuffer->capacity() != buffer->capacity()) {
1265                size_t tsOff = tsBuffer->offset(), tsSize = tsBuffer->size();
1266                tsBuffer = new ABuffer(buffer->data(), buffer->capacity());
1267                tsBuffer->setRange(tsOff, tsSize);
1268            }
1269            tsBuffer->setRange(tsBuffer->offset(), tsBuffer->size() + bytesRead);
1270            err = extractAndQueueAccessUnitsFromTs(tsBuffer);
1271        }
1272
1273        if (err == -EAGAIN) {
1274            // starting sequence number too low/high
1275            mTSParser.clear();
1276            for (size_t i = 0; i < mPacketSources.size(); i++) {
1277                sp<AnotherPacketSource> packetSource = mPacketSources.valueAt(i);
1278                packetSource->clear();
1279            }
1280            postMonitorQueue();
1281            return;
1282        } else if (err == ERROR_OUT_OF_RANGE) {
1283            // reached stopping point
1284            notifyStopReached();
1285            return;
1286        } else if (err != OK) {
1287            notifyError(err);
1288            return;
1289        }
1290        // If we're switching, post start notification
1291        // this should only be posted when the last chunk is full processed by TSParser
1292        if (mSeekMode != LiveSession::kSeekModeExactPosition && startUp != mStartup) {
1293            CHECK(mStartTimeUsNotify != NULL);
1294            mStartTimeUsNotify->post();
1295            mStartTimeUsNotify.clear();
1296            shouldPause = true;
1297        }
1298        if (shouldPause || shouldPauseDownload()) {
1299            // save state and return if this is not the last chunk,
1300            // leaving the fetcher in paused state.
1301            if (bytesRead != 0) {
1302                mDownloadState->saveState(
1303                        uri,
1304                        itemMeta,
1305                        buffer,
1306                        tsBuffer,
1307                        firstSeqNumberInPlaylist,
1308                        lastSeqNumberInPlaylist);
1309                return;
1310            }
1311            shouldPause = true;
1312        }
1313    } while (bytesRead != 0);
1314
1315    if (bufferStartsWithTsSyncByte(buffer)) {
1316        // If we don't see a stream in the program table after fetching a full ts segment
1317        // mark it as nonexistent.
1318        const size_t kNumTypes = ATSParser::NUM_SOURCE_TYPES;
1319        ATSParser::SourceType srcTypes[kNumTypes] =
1320                { ATSParser::VIDEO, ATSParser::AUDIO };
1321        LiveSession::StreamType streamTypes[kNumTypes] =
1322                { LiveSession::STREAMTYPE_VIDEO, LiveSession::STREAMTYPE_AUDIO };
1323
1324        for (size_t i = 0; i < kNumTypes; i++) {
1325            ATSParser::SourceType srcType = srcTypes[i];
1326            LiveSession::StreamType streamType = streamTypes[i];
1327
1328            sp<AnotherPacketSource> source =
1329                static_cast<AnotherPacketSource *>(
1330                    mTSParser->getSource(srcType).get());
1331
1332            if (!mTSParser->hasSource(srcType)) {
1333                ALOGW("MPEG2 Transport stream does not contain %s data.",
1334                      srcType == ATSParser::VIDEO ? "video" : "audio");
1335
1336                mStreamTypeMask &= ~streamType;
1337                mPacketSources.removeItem(streamType);
1338            }
1339        }
1340
1341    }
1342
1343    if (checkDecryptPadding(buffer) != OK) {
1344        ALOGE("Incorrect padding bytes after decryption.");
1345        notifyError(ERROR_MALFORMED);
1346        return;
1347    }
1348
1349    if (tsBuffer != NULL) {
1350        AString method;
1351        CHECK(buffer->meta()->findString("cipher-method", &method));
1352        if ((tsBuffer->size() > 0 && method == "NONE")
1353                || tsBuffer->size() > 16) {
1354            ALOGE("MPEG2 transport stream is not an even multiple of 188 "
1355                    "bytes in length.");
1356            notifyError(ERROR_MALFORMED);
1357            return;
1358        }
1359    }
1360
1361    // bulk extract non-ts files
1362    bool startUp = mStartup;
1363    if (tsBuffer == NULL) {
1364        status_t err = extractAndQueueAccessUnits(buffer, itemMeta);
1365        if (err == -EAGAIN) {
1366            // starting sequence number too low/high
1367            postMonitorQueue();
1368            return;
1369        } else if (err == ERROR_OUT_OF_RANGE) {
1370            // reached stopping point
1371            notifyStopReached();
1372            return;
1373        } else if (err != OK) {
1374            notifyError(err);
1375            return;
1376        }
1377    }
1378
1379    ++mSeqNumber;
1380
1381    // if adapting, pause after found the next starting point
1382    if (mSeekMode != LiveSession::kSeekModeExactPosition && startUp != mStartup) {
1383        CHECK(mStartTimeUsNotify != NULL);
1384        mStartTimeUsNotify->post();
1385        mStartTimeUsNotify.clear();
1386        shouldPause = true;
1387    }
1388
1389    if (!shouldPause) {
1390        postMonitorQueue();
1391    }
1392}
1393
1394int32_t PlaylistFetcher::getSeqNumberWithAnchorTime(
1395        int64_t anchorTimeUs, int64_t targetDiffUs) const {
1396    int32_t firstSeqNumberInPlaylist, lastSeqNumberInPlaylist;
1397    if (mPlaylist->meta() == NULL
1398            || !mPlaylist->meta()->findInt32("media-sequence", &firstSeqNumberInPlaylist)) {
1399        firstSeqNumberInPlaylist = 0;
1400    }
1401    lastSeqNumberInPlaylist = firstSeqNumberInPlaylist + mPlaylist->size() - 1;
1402
1403    int32_t index = mSeqNumber - firstSeqNumberInPlaylist - 1;
1404    // adjust anchorTimeUs to within targetDiffUs from mStartTimeUs
1405    while (index >= 0 && anchorTimeUs - mStartTimeUs > targetDiffUs) {
1406        sp<AMessage> itemMeta;
1407        CHECK(mPlaylist->itemAt(index, NULL /* uri */, &itemMeta));
1408
1409        int64_t itemDurationUs;
1410        CHECK(itemMeta->findInt64("durationUs", &itemDurationUs));
1411
1412        anchorTimeUs -= itemDurationUs;
1413        --index;
1414    }
1415
1416    int32_t newSeqNumber = firstSeqNumberInPlaylist + index + 1;
1417    if (newSeqNumber <= lastSeqNumberInPlaylist) {
1418        return newSeqNumber;
1419    } else {
1420        return lastSeqNumberInPlaylist;
1421    }
1422}
1423
1424int32_t PlaylistFetcher::getSeqNumberForDiscontinuity(size_t discontinuitySeq) const {
1425    int32_t firstSeqNumberInPlaylist;
1426    if (mPlaylist->meta() == NULL || !mPlaylist->meta()->findInt32(
1427                "media-sequence", &firstSeqNumberInPlaylist)) {
1428        firstSeqNumberInPlaylist = 0;
1429    }
1430
1431    size_t index = 0;
1432    while (index < mPlaylist->size()) {
1433        sp<AMessage> itemMeta;
1434        CHECK(mPlaylist->itemAt( index, NULL /* uri */, &itemMeta));
1435        size_t curDiscontinuitySeq;
1436        CHECK(itemMeta->findInt32("discontinuity-sequence", (int32_t *)&curDiscontinuitySeq));
1437        int32_t seqNumber = firstSeqNumberInPlaylist + index;
1438        if (curDiscontinuitySeq == discontinuitySeq) {
1439            return seqNumber;
1440        } else if (curDiscontinuitySeq > discontinuitySeq) {
1441            return seqNumber <= 0 ? 0 : seqNumber - 1;
1442        }
1443
1444        ++index;
1445    }
1446
1447    return firstSeqNumberInPlaylist + mPlaylist->size();
1448}
1449
1450int32_t PlaylistFetcher::getSeqNumberForTime(int64_t timeUs) const {
1451    int32_t firstSeqNumberInPlaylist;
1452    if (mPlaylist->meta() == NULL || !mPlaylist->meta()->findInt32(
1453                "media-sequence", &firstSeqNumberInPlaylist)) {
1454        firstSeqNumberInPlaylist = 0;
1455    }
1456
1457    size_t index = 0;
1458    int64_t segmentStartUs = 0;
1459    while (index < mPlaylist->size()) {
1460        sp<AMessage> itemMeta;
1461        CHECK(mPlaylist->itemAt(
1462                    index, NULL /* uri */, &itemMeta));
1463
1464        int64_t itemDurationUs;
1465        CHECK(itemMeta->findInt64("durationUs", &itemDurationUs));
1466
1467        if (timeUs < segmentStartUs + itemDurationUs) {
1468            break;
1469        }
1470
1471        segmentStartUs += itemDurationUs;
1472        ++index;
1473    }
1474
1475    if (index >= mPlaylist->size()) {
1476        index = mPlaylist->size() - 1;
1477    }
1478
1479    return firstSeqNumberInPlaylist + index;
1480}
1481
1482const sp<ABuffer> &PlaylistFetcher::setAccessUnitProperties(
1483        const sp<ABuffer> &accessUnit, const sp<AnotherPacketSource> &source, bool discard) {
1484    sp<MetaData> format = source->getFormat();
1485    if (format != NULL) {
1486        // for simplicity, store a reference to the format in each unit
1487        accessUnit->meta()->setObject("format", format);
1488    }
1489
1490    if (discard) {
1491        accessUnit->meta()->setInt32("discard", discard);
1492    }
1493
1494    int32_t targetDurationSecs;
1495    if (mPlaylist->meta()->findInt32("target-duration", &targetDurationSecs)) {
1496        accessUnit->meta()->setInt32("targetDuration", targetDurationSecs);
1497    }
1498
1499    accessUnit->meta()->setInt32("discontinuitySeq", mDiscontinuitySeq);
1500    accessUnit->meta()->setInt64("segmentStartTimeUs", getSegmentStartTimeUs(mSeqNumber));
1501    accessUnit->meta()->setInt64("segmentDurationUs", getSegmentDurationUs(mSeqNumber));
1502    return accessUnit;
1503}
1504
1505status_t PlaylistFetcher::extractAndQueueAccessUnitsFromTs(const sp<ABuffer> &buffer) {
1506    if (mTSParser == NULL) {
1507        // Use TS_TIMESTAMPS_ARE_ABSOLUTE so pts carry over between fetchers.
1508        mTSParser = new ATSParser(ATSParser::TS_TIMESTAMPS_ARE_ABSOLUTE);
1509    }
1510
1511    if (mNextPTSTimeUs >= 0ll) {
1512        sp<AMessage> extra = new AMessage;
1513        // Since we are using absolute timestamps, signal an offset of 0 to prevent
1514        // ATSParser from skewing the timestamps of access units.
1515        extra->setInt64(IStreamListener::kKeyMediaTimeUs, 0);
1516
1517        // When adapting, signal a recent media time to the parser,
1518        // so that PTS wrap around is handled for the new variant.
1519        if (mStartTimeUs >= 0 && !mStartTimeUsRelative) {
1520            extra->setInt64(IStreamListener::kKeyRecentMediaTimeUs, mStartTimeUs);
1521        }
1522
1523        mTSParser->signalDiscontinuity(
1524                ATSParser::DISCONTINUITY_TIME, extra);
1525
1526        mNextPTSTimeUs = -1ll;
1527    }
1528
1529    size_t offset = 0;
1530    while (offset + 188 <= buffer->size()) {
1531        status_t err = mTSParser->feedTSPacket(buffer->data() + offset, 188);
1532
1533        if (err != OK) {
1534            return err;
1535        }
1536
1537        offset += 188;
1538    }
1539    // setRange to indicate consumed bytes.
1540    buffer->setRange(buffer->offset() + offset, buffer->size() - offset);
1541
1542    status_t err = OK;
1543    for (size_t i = mPacketSources.size(); i-- > 0;) {
1544        sp<AnotherPacketSource> packetSource = mPacketSources.valueAt(i);
1545
1546        const LiveSession::StreamType stream = mPacketSources.keyAt(i);
1547        if (stream == LiveSession::STREAMTYPE_SUBTITLES) {
1548            ALOGE("MPEG2 Transport streams do not contain subtitles.");
1549            return ERROR_MALFORMED;
1550        }
1551        const char *key = LiveSession::getKeyForStream(stream);
1552        ATSParser::SourceType type =
1553                (stream == LiveSession::STREAMTYPE_AUDIO) ?
1554                        ATSParser::AUDIO : ATSParser::VIDEO;
1555
1556        sp<AnotherPacketSource> source =
1557            static_cast<AnotherPacketSource *>(
1558                    mTSParser->getSource(type).get());
1559
1560        if (source == NULL) {
1561            continue;
1562        }
1563
1564        const char *mime;
1565        sp<MetaData> format  = source->getFormat();
1566        bool isAvc = format != NULL && format->findCString(kKeyMIMEType, &mime)
1567                && !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
1568
1569        sp<ABuffer> accessUnit;
1570        status_t finalResult;
1571        while (source->hasBufferAvailable(&finalResult)
1572                && source->dequeueAccessUnit(&accessUnit) == OK) {
1573
1574            int64_t timeUs;
1575            CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs));
1576
1577            if (mSegmentFirstPTS < 0ll) {
1578                mSegmentFirstPTS = timeUs;
1579                if (!mStartTimeUsRelative) {
1580                    int32_t firstSeqNumberInPlaylist;
1581                    if (mPlaylist->meta() == NULL || !mPlaylist->meta()->findInt32(
1582                                "media-sequence", &firstSeqNumberInPlaylist)) {
1583                        firstSeqNumberInPlaylist = 0;
1584                    }
1585
1586                    int32_t targetDurationSecs;
1587                    CHECK(mPlaylist->meta()->findInt32("target-duration", &targetDurationSecs));
1588                    int64_t targetDurationUs = targetDurationSecs * 1000000ll;
1589                    // mStartup
1590                    //   mStartup is true until we have queued a packet for all the streams
1591                    //   we are fetching. We queue packets whose timestamps are greater than
1592                    //   mStartTimeUs.
1593                    // mSegmentStartTimeUs >= 0
1594                    //   mSegmentStartTimeUs is non-negative when adapting or switching tracks
1595                    // mSeqNumber > firstSeqNumberInPlaylist
1596                    //   don't decrement mSeqNumber if it already points to the 1st segment
1597                    // timeUs - mStartTimeUs > targetDurationUs:
1598                    //   This and the 2 above conditions should only happen when adapting in a live
1599                    //   stream; the old fetcher has already fetched to mStartTimeUs; the new fetcher
1600                    //   would start fetching after timeUs, which should be greater than mStartTimeUs;
1601                    //   the old fetcher would then continue fetching data until timeUs. We don't want
1602                    //   timeUs to be too far ahead of mStartTimeUs because we want the old fetcher to
1603                    //   stop as early as possible. The definition of being "too far ahead" is
1604                    //   arbitrary; here we use targetDurationUs as threshold.
1605                    int64_t targetDiffUs = (mSeekMode == LiveSession::kSeekModeNextSample
1606                            ? 0 : targetDurationUs);
1607                    if (mStartup && mSegmentStartTimeUs >= 0
1608                            && mSeqNumber > firstSeqNumberInPlaylist
1609                            && timeUs - mStartTimeUs > targetDiffUs) {
1610                        // we just guessed a starting timestamp that is too high when adapting in a
1611                        // live stream; re-adjust based on the actual timestamp extracted from the
1612                        // media segment; if we didn't move backward after the re-adjustment
1613                        // (newSeqNumber), start at least 1 segment prior.
1614                        int32_t newSeqNumber = getSeqNumberWithAnchorTime(
1615                                timeUs, targetDiffUs);
1616
1617                        FLOGV("guessed wrong seq number: timeUs=%lld, mStartTimeUs=%lld, "
1618                                "targetDurationUs=%lld, mSeqNumber=%d, newSeq=%d, firstSeq=%d",
1619                                (long long)timeUs,
1620                                (long long)mStartTimeUs,
1621                                (long long)targetDurationUs,
1622                                mSeqNumber,
1623                                newSeqNumber,
1624                                firstSeqNumberInPlaylist);
1625
1626                        if (newSeqNumber >= mSeqNumber) {
1627                            --mSeqNumber;
1628                        } else {
1629                            mSeqNumber = newSeqNumber;
1630                        }
1631                        mStartTimeUsNotify = mNotify->dup();
1632                        mStartTimeUsNotify->setInt32("what", kWhatStartedAt);
1633                        mStartTimeUsNotify->setString("uri", mURI);
1634                        mIDRFound = false;
1635                        return -EAGAIN;
1636                    }
1637                }
1638            }
1639            if (mStartup) {
1640                if (!mFirstPTSValid) {
1641                    mFirstTimeUs = timeUs;
1642                    mFirstPTSValid = true;
1643                }
1644                bool startTimeReached = true;
1645                if (mStartTimeUsRelative) {
1646                    FLOGV("startTimeUsRelative, timeUs (%lld) - %lld = %lld",
1647                            (long long)timeUs,
1648                            (long long)mFirstTimeUs,
1649                            (long long)(timeUs - mFirstTimeUs));
1650                    timeUs -= mFirstTimeUs;
1651                    if (timeUs < 0) {
1652                        FLOGV("clamp negative timeUs to 0");
1653                        timeUs = 0;
1654                    }
1655                    startTimeReached = (timeUs >= mStartTimeUs);
1656                }
1657
1658                if (!startTimeReached || (isAvc && !mIDRFound)) {
1659                    // buffer up to the closest preceding IDR frame in the next segement,
1660                    // or the closest succeeding IDR frame after the exact position
1661                    FSLOGV(stream, "timeUs=%lld, mStartTimeUs=%lld, mIDRFound=%d",
1662                            (long long)timeUs, (long long)mStartTimeUs, mIDRFound);
1663                    if (isAvc) {
1664                        if (IsIDR(accessUnit)) {
1665                            mVideoBuffer->clear();
1666                            FSLOGV(stream, "found IDR, clear mVideoBuffer");
1667                            mIDRFound = true;
1668                        }
1669                        if (mIDRFound && mStartTimeUsRelative && !startTimeReached) {
1670                            mVideoBuffer->queueAccessUnit(accessUnit);
1671                            FSLOGV(stream, "saving AVC video AccessUnit");
1672                        }
1673                    }
1674                    if (!startTimeReached || (isAvc && !mIDRFound)) {
1675                        continue;
1676                    }
1677                }
1678            }
1679
1680            if (mStartTimeUsNotify != NULL) {
1681                uint32_t streamMask = 0;
1682                mStartTimeUsNotify->findInt32("streamMask", (int32_t *) &streamMask);
1683                if (!(streamMask & mPacketSources.keyAt(i))) {
1684                    streamMask |= mPacketSources.keyAt(i);
1685                    mStartTimeUsNotify->setInt32("streamMask", streamMask);
1686                    FSLOGV(stream, "found start point, timeUs=%lld, streamMask becomes %x",
1687                            (long long)timeUs, streamMask);
1688
1689                    if (streamMask == mStreamTypeMask) {
1690                        FLOGV("found start point for all streams");
1691                        mStartup = false;
1692                    }
1693                }
1694            }
1695
1696            if (mStopParams != NULL) {
1697                int32_t discontinuitySeq;
1698                int64_t stopTimeUs;
1699                if (!mStopParams->findInt32("discontinuitySeq", &discontinuitySeq)
1700                        || discontinuitySeq > mDiscontinuitySeq
1701                        || !mStopParams->findInt64(key, &stopTimeUs)
1702                        || (discontinuitySeq == mDiscontinuitySeq
1703                                && timeUs >= stopTimeUs)) {
1704                    FSLOGV(stream, "reached stop point, timeUs=%lld", (long long)timeUs);
1705                    mStreamTypeMask &= ~stream;
1706                    mPacketSources.removeItemsAt(i);
1707                    break;
1708                }
1709            }
1710
1711            if (stream == LiveSession::STREAMTYPE_VIDEO) {
1712                const bool discard = true;
1713                status_t status;
1714                while (mVideoBuffer->hasBufferAvailable(&status)) {
1715                    sp<ABuffer> videoBuffer;
1716                    mVideoBuffer->dequeueAccessUnit(&videoBuffer);
1717                    setAccessUnitProperties(videoBuffer, source, discard);
1718                    packetSource->queueAccessUnit(videoBuffer);
1719                    int64_t bufferTimeUs;
1720                    CHECK(videoBuffer->meta()->findInt64("timeUs", &bufferTimeUs));
1721                    FSLOGV(stream, "queueAccessUnit (saved), timeUs=%lld",
1722                            (long long)bufferTimeUs);
1723                }
1724            }
1725
1726            setAccessUnitProperties(accessUnit, source);
1727            packetSource->queueAccessUnit(accessUnit);
1728            FSLOGV(stream, "queueAccessUnit, timeUs=%lld", (long long)timeUs);
1729        }
1730
1731        if (err != OK) {
1732            break;
1733        }
1734    }
1735
1736    if (err != OK) {
1737        for (size_t i = mPacketSources.size(); i-- > 0;) {
1738            sp<AnotherPacketSource> packetSource = mPacketSources.valueAt(i);
1739            packetSource->clear();
1740        }
1741        return err;
1742    }
1743
1744    if (!mStreamTypeMask) {
1745        // Signal gap is filled between original and new stream.
1746        FLOGV("reached stop point for all streams");
1747        return ERROR_OUT_OF_RANGE;
1748    }
1749
1750    return OK;
1751}
1752
1753/* static */
1754bool PlaylistFetcher::bufferStartsWithWebVTTMagicSequence(
1755        const sp<ABuffer> &buffer) {
1756    size_t pos = 0;
1757
1758    // skip possible BOM
1759    if (buffer->size() >= pos + 3 &&
1760            !memcmp("\xef\xbb\xbf", buffer->data() + pos, 3)) {
1761        pos += 3;
1762    }
1763
1764    // accept WEBVTT followed by SPACE, TAB or (CR) LF
1765    if (buffer->size() < pos + 6 ||
1766            memcmp("WEBVTT", buffer->data() + pos, 6)) {
1767        return false;
1768    }
1769    pos += 6;
1770
1771    if (buffer->size() == pos) {
1772        return true;
1773    }
1774
1775    uint8_t sep = buffer->data()[pos];
1776    return sep == ' ' || sep == '\t' || sep == '\n' || sep == '\r';
1777}
1778
1779status_t PlaylistFetcher::extractAndQueueAccessUnits(
1780        const sp<ABuffer> &buffer, const sp<AMessage> &itemMeta) {
1781    if (bufferStartsWithWebVTTMagicSequence(buffer)) {
1782        if (mStreamTypeMask != LiveSession::STREAMTYPE_SUBTITLES) {
1783            ALOGE("This stream only contains subtitles.");
1784            return ERROR_MALFORMED;
1785        }
1786
1787        const sp<AnotherPacketSource> packetSource =
1788            mPacketSources.valueFor(LiveSession::STREAMTYPE_SUBTITLES);
1789
1790        int64_t durationUs;
1791        CHECK(itemMeta->findInt64("durationUs", &durationUs));
1792        buffer->meta()->setInt64("timeUs", getSegmentStartTimeUs(mSeqNumber));
1793        buffer->meta()->setInt64("durationUs", durationUs);
1794        buffer->meta()->setInt64("segmentStartTimeUs", getSegmentStartTimeUs(mSeqNumber));
1795        buffer->meta()->setInt32("discontinuitySeq", mDiscontinuitySeq);
1796        buffer->meta()->setInt32("subtitleGeneration", mSubtitleGeneration);
1797
1798        packetSource->queueAccessUnit(buffer);
1799        return OK;
1800    }
1801
1802    if (mNextPTSTimeUs >= 0ll) {
1803        mNextPTSTimeUs = -1ll;
1804    }
1805
1806    // This better be an ISO 13818-7 (AAC) or ISO 13818-1 (MPEG) audio
1807    // stream prefixed by an ID3 tag.
1808
1809    bool firstID3Tag = true;
1810    uint64_t PTS = 0;
1811
1812    for (;;) {
1813        // Make sure to skip all ID3 tags preceding the audio data.
1814        // At least one must be present to provide the PTS timestamp.
1815
1816        ID3 id3(buffer->data(), buffer->size(), true /* ignoreV1 */);
1817        if (!id3.isValid()) {
1818            if (firstID3Tag) {
1819                ALOGE("Unable to parse ID3 tag.");
1820                return ERROR_MALFORMED;
1821            } else {
1822                break;
1823            }
1824        }
1825
1826        if (firstID3Tag) {
1827            bool found = false;
1828
1829            ID3::Iterator it(id3, "PRIV");
1830            while (!it.done()) {
1831                size_t length;
1832                const uint8_t *data = it.getData(&length);
1833
1834                static const char *kMatchName =
1835                    "com.apple.streaming.transportStreamTimestamp";
1836                static const size_t kMatchNameLen = strlen(kMatchName);
1837
1838                if (length == kMatchNameLen + 1 + 8
1839                        && !strncmp((const char *)data, kMatchName, kMatchNameLen)) {
1840                    found = true;
1841                    PTS = U64_AT(&data[kMatchNameLen + 1]);
1842                }
1843
1844                it.next();
1845            }
1846
1847            if (!found) {
1848                ALOGE("Unable to extract transportStreamTimestamp from ID3 tag.");
1849                return ERROR_MALFORMED;
1850            }
1851        }
1852
1853        // skip the ID3 tag
1854        buffer->setRange(
1855                buffer->offset() + id3.rawSize(), buffer->size() - id3.rawSize());
1856
1857        firstID3Tag = false;
1858    }
1859
1860    if (mStreamTypeMask != LiveSession::STREAMTYPE_AUDIO) {
1861        ALOGW("This stream only contains audio data!");
1862
1863        mStreamTypeMask &= LiveSession::STREAMTYPE_AUDIO;
1864
1865        if (mStreamTypeMask == 0) {
1866            return OK;
1867        }
1868    }
1869
1870    sp<AnotherPacketSource> packetSource =
1871        mPacketSources.valueFor(LiveSession::STREAMTYPE_AUDIO);
1872
1873    if (packetSource->getFormat() == NULL && buffer->size() >= 7) {
1874        ABitReader bits(buffer->data(), buffer->size());
1875
1876        // adts_fixed_header
1877
1878        CHECK_EQ(bits.getBits(12), 0xfffu);
1879        bits.skipBits(3);  // ID, layer
1880        bool protection_absent __unused = bits.getBits(1) != 0;
1881
1882        unsigned profile = bits.getBits(2);
1883        CHECK_NE(profile, 3u);
1884        unsigned sampling_freq_index = bits.getBits(4);
1885        bits.getBits(1);  // private_bit
1886        unsigned channel_configuration = bits.getBits(3);
1887        CHECK_NE(channel_configuration, 0u);
1888        bits.skipBits(2);  // original_copy, home
1889
1890        sp<MetaData> meta = MakeAACCodecSpecificData(
1891                profile, sampling_freq_index, channel_configuration);
1892
1893        meta->setInt32(kKeyIsADTS, true);
1894
1895        packetSource->setFormat(meta);
1896    }
1897
1898    int64_t numSamples = 0ll;
1899    int32_t sampleRate;
1900    CHECK(packetSource->getFormat()->findInt32(kKeySampleRate, &sampleRate));
1901
1902    int64_t timeUs = (PTS * 100ll) / 9ll;
1903    if (mStartup && !mFirstPTSValid) {
1904        mFirstPTSValid = true;
1905        mFirstTimeUs = timeUs;
1906    }
1907
1908    size_t offset = 0;
1909    while (offset < buffer->size()) {
1910        const uint8_t *adtsHeader = buffer->data() + offset;
1911        CHECK_LT(offset + 5, buffer->size());
1912
1913        unsigned aac_frame_length =
1914            ((adtsHeader[3] & 3) << 11)
1915            | (adtsHeader[4] << 3)
1916            | (adtsHeader[5] >> 5);
1917
1918        if (aac_frame_length == 0) {
1919            const uint8_t *id3Header = adtsHeader;
1920            if (!memcmp(id3Header, "ID3", 3)) {
1921                ID3 id3(id3Header, buffer->size() - offset, true);
1922                if (id3.isValid()) {
1923                    offset += id3.rawSize();
1924                    continue;
1925                };
1926            }
1927            return ERROR_MALFORMED;
1928        }
1929
1930        CHECK_LE(offset + aac_frame_length, buffer->size());
1931
1932        int64_t unitTimeUs = timeUs + numSamples * 1000000ll / sampleRate;
1933        offset += aac_frame_length;
1934
1935        // Each AAC frame encodes 1024 samples.
1936        numSamples += 1024;
1937
1938        if (mStartup) {
1939            int64_t startTimeUs = unitTimeUs;
1940            if (mStartTimeUsRelative) {
1941                startTimeUs -= mFirstTimeUs;
1942                if (startTimeUs  < 0) {
1943                    startTimeUs = 0;
1944                }
1945            }
1946            if (startTimeUs < mStartTimeUs) {
1947                continue;
1948            }
1949
1950            if (mStartTimeUsNotify != NULL) {
1951                int32_t targetDurationSecs;
1952                CHECK(mPlaylist->meta()->findInt32("target-duration", &targetDurationSecs));
1953                int64_t targetDurationUs = targetDurationSecs * 1000000ll;
1954
1955                int64_t targetDiffUs =(mSeekMode == LiveSession::kSeekModeNextSample
1956                        ? 0 : targetDurationUs);
1957                // Duplicated logic from how we handle .ts playlists.
1958                if (mStartup && mSegmentStartTimeUs >= 0
1959                        && timeUs - mStartTimeUs > targetDiffUs) {
1960                    int32_t newSeqNumber = getSeqNumberWithAnchorTime(
1961                            timeUs, targetDiffUs);
1962                    if (newSeqNumber >= mSeqNumber) {
1963                        --mSeqNumber;
1964                    } else {
1965                        mSeqNumber = newSeqNumber;
1966                    }
1967                    return -EAGAIN;
1968                }
1969
1970                mStartTimeUsNotify->setInt32("streamMask", LiveSession::STREAMTYPE_AUDIO);
1971                mStartup = false;
1972            }
1973        }
1974
1975        if (mStopParams != NULL) {
1976            int32_t discontinuitySeq;
1977            int64_t stopTimeUs;
1978            if (!mStopParams->findInt32("discontinuitySeq", &discontinuitySeq)
1979                    || discontinuitySeq > mDiscontinuitySeq
1980                    || !mStopParams->findInt64("timeUsAudio", &stopTimeUs)
1981                    || (discontinuitySeq == mDiscontinuitySeq && unitTimeUs >= stopTimeUs)) {
1982                mStreamTypeMask = 0;
1983                mPacketSources.clear();
1984                return ERROR_OUT_OF_RANGE;
1985            }
1986        }
1987
1988        sp<ABuffer> unit = new ABuffer(aac_frame_length);
1989        memcpy(unit->data(), adtsHeader, aac_frame_length);
1990
1991        unit->meta()->setInt64("timeUs", unitTimeUs);
1992        setAccessUnitProperties(unit, packetSource);
1993        packetSource->queueAccessUnit(unit);
1994    }
1995
1996    return OK;
1997}
1998
1999void PlaylistFetcher::updateDuration() {
2000    int64_t durationUs = 0ll;
2001    for (size_t index = 0; index < mPlaylist->size(); ++index) {
2002        sp<AMessage> itemMeta;
2003        CHECK(mPlaylist->itemAt(
2004                    index, NULL /* uri */, &itemMeta));
2005
2006        int64_t itemDurationUs;
2007        CHECK(itemMeta->findInt64("durationUs", &itemDurationUs));
2008
2009        durationUs += itemDurationUs;
2010    }
2011
2012    sp<AMessage> msg = mNotify->dup();
2013    msg->setInt32("what", kWhatDurationUpdate);
2014    msg->setInt64("durationUs", durationUs);
2015    msg->post();
2016}
2017
2018void PlaylistFetcher::updateTargetDuration() {
2019    int32_t targetDurationSecs;
2020    CHECK(mPlaylist->meta()->findInt32("target-duration", &targetDurationSecs));
2021    int64_t targetDurationUs = targetDurationSecs * 1000000ll;
2022
2023    sp<AMessage> msg = mNotify->dup();
2024    msg->setInt32("what", kWhatTargetDurationUpdate);
2025    msg->setInt64("targetDurationUs", targetDurationUs);
2026    msg->post();
2027}
2028
2029}  // namespace android
2030