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