PlaylistFetcher.cpp revision 3b0da19c78f6a61ed343a07f2448b94faafe4c02
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    // in the middle of an unfinished download, delay
754    // playlist refresh as it'll change seq numbers
755    if (!mDownloadState->hasSavedState()) {
756        refreshPlaylist();
757    }
758
759    int32_t targetDurationSecs;
760    int64_t targetDurationUs = kMinBufferedDurationUs;
761    if (mPlaylist != NULL) {
762        if (mPlaylist->meta() == NULL || !mPlaylist->meta()->findInt32(
763                "target-duration", &targetDurationSecs)) {
764            ALOGE("Playlist is missing required EXT-X-TARGETDURATION tag");
765            notifyError(ERROR_MALFORMED);
766            return;
767        }
768        targetDurationUs = targetDurationSecs * 1000000ll;
769    }
770
771    int64_t bufferedDurationUs = 0ll;
772    status_t finalResult = OK;
773    if (mStreamTypeMask == LiveSession::STREAMTYPE_SUBTITLES) {
774        sp<AnotherPacketSource> packetSource =
775            mPacketSources.valueFor(LiveSession::STREAMTYPE_SUBTITLES);
776
777        bufferedDurationUs =
778                packetSource->getBufferedDurationUs(&finalResult);
779    } else {
780        // Use min stream duration, but ignore streams that never have any packet
781        // enqueued to prevent us from waiting on a non-existent stream;
782        // when we cannot make out from the manifest what streams are included in
783        // a playlist we might assume extra streams.
784        bufferedDurationUs = -1ll;
785        for (size_t i = 0; i < mPacketSources.size(); ++i) {
786            if ((mStreamTypeMask & mPacketSources.keyAt(i)) == 0
787                    || mPacketSources[i]->getLatestEnqueuedMeta() == NULL) {
788                continue;
789            }
790
791            int64_t bufferedStreamDurationUs =
792                mPacketSources.valueAt(i)->getBufferedDurationUs(&finalResult);
793
794            FSLOGV(mPacketSources.keyAt(i), "buffered %lld", (long long)bufferedStreamDurationUs);
795
796            if (bufferedDurationUs == -1ll
797                 || bufferedStreamDurationUs < bufferedDurationUs) {
798                bufferedDurationUs = bufferedStreamDurationUs;
799            }
800        }
801        if (bufferedDurationUs == -1ll) {
802            bufferedDurationUs = 0ll;
803        }
804    }
805
806    if (finalResult == OK && bufferedDurationUs < kMinBufferedDurationUs) {
807        FLOGV("monitoring, buffered=%lld < %lld",
808                (long long)bufferedDurationUs, (long long)kMinBufferedDurationUs);
809
810        // delay the next download slightly; hopefully this gives other concurrent fetchers
811        // a better chance to run.
812        // onDownloadNext();
813        sp<AMessage> msg = new AMessage(kWhatDownloadNext, this);
814        msg->setInt32("generation", mMonitorQueueGeneration);
815        msg->post(1000l);
816    } else {
817        // We'd like to maintain buffering above durationToBufferUs, so try
818        // again when buffer just about to go below durationToBufferUs
819        // (or after targetDurationUs / 2, whichever is smaller).
820        int64_t delayUs = bufferedDurationUs - kMinBufferedDurationUs + 1000000ll;
821        if (delayUs > targetDurationUs / 2) {
822            delayUs = targetDurationUs / 2;
823        }
824
825        FLOGV("pausing for %lld, buffered=%lld > %lld",
826                (long long)delayUs,
827                (long long)bufferedDurationUs,
828                (long long)kMinBufferedDurationUs);
829
830        postMonitorQueue(delayUs);
831    }
832}
833
834status_t PlaylistFetcher::refreshPlaylist() {
835    if (delayUsToRefreshPlaylist() <= 0) {
836        bool unchanged;
837        sp<M3UParser> playlist = mSession->fetchPlaylist(
838                mURI.c_str(), mPlaylistHash, &unchanged);
839
840        if (playlist == NULL) {
841            if (unchanged) {
842                // We succeeded in fetching the playlist, but it was
843                // unchanged from the last time we tried.
844
845                if (mRefreshState != THIRD_UNCHANGED_RELOAD_ATTEMPT) {
846                    mRefreshState = (RefreshState)(mRefreshState + 1);
847                }
848            } else {
849                ALOGE("failed to load playlist at url '%s'", uriDebugString(mURI).c_str());
850                return ERROR_IO;
851            }
852        } else {
853            mRefreshState = INITIAL_MINIMUM_RELOAD_DELAY;
854            mPlaylist = playlist;
855
856            if (mPlaylist->isComplete() || mPlaylist->isEvent()) {
857                updateDuration();
858            }
859            // Notify LiveSession to use target-duration based buffering level
860            // for up/down switch. Default LiveSession::kUpSwitchMark may not
861            // be reachable for live streams, as our max buffering amount is
862            // limited to 3 segments.
863            if (!mPlaylist->isComplete()) {
864                updateTargetDuration();
865            }
866        }
867
868        mLastPlaylistFetchTimeUs = ALooper::GetNowUs();
869    }
870    return OK;
871}
872
873// static
874bool PlaylistFetcher::bufferStartsWithTsSyncByte(const sp<ABuffer>& buffer) {
875    return buffer->size() > 0 && buffer->data()[0] == 0x47;
876}
877
878bool PlaylistFetcher::shouldPauseDownload() {
879    if (mStreamTypeMask == LiveSession::STREAMTYPE_SUBTITLES) {
880        // doesn't apply to subtitles
881        return false;
882    }
883
884    // Calculate threshold to abort current download
885    int32_t targetDurationSecs;
886    CHECK(mPlaylist->meta()->findInt32("target-duration", &targetDurationSecs));
887    int64_t targetDurationUs = targetDurationSecs * 1000000ll;
888    int64_t thresholdUs = -1;
889    {
890        AutoMutex _l(mThresholdLock);
891        thresholdUs = (mThresholdRatio < 0.0f) ?
892                -1ll : mThresholdRatio * targetDurationUs;
893    }
894
895    if (thresholdUs < 0) {
896        // never abort
897        return false;
898    } else if (thresholdUs == 0) {
899        // immediately abort
900        return true;
901    }
902
903    // now we have a positive thresholdUs, abort if remaining
904    // portion to download is over that threshold.
905    if (mSegmentFirstPTS < 0) {
906        // this means we haven't even find the first access unit,
907        // abort now as we must be very far away from the end.
908        return true;
909    }
910    int64_t lastEnqueueUs = mSegmentFirstPTS;
911    for (size_t i = 0; i < mPacketSources.size(); ++i) {
912        if ((mStreamTypeMask & mPacketSources.keyAt(i)) == 0) {
913            continue;
914        }
915        sp<AMessage> meta = mPacketSources[i]->getLatestEnqueuedMeta();
916        int32_t type;
917        if (meta == NULL || meta->findInt32("discontinuity", &type)) {
918            continue;
919        }
920        int64_t tmpUs;
921        CHECK(meta->findInt64("timeUs", &tmpUs));
922        if (tmpUs > lastEnqueueUs) {
923            lastEnqueueUs = tmpUs;
924        }
925    }
926    lastEnqueueUs -= mSegmentFirstPTS;
927
928    FLOGV("%spausing now, thresholdUs %lld, remaining %lld",
929            targetDurationUs - lastEnqueueUs > thresholdUs ? "" : "not ",
930            (long long)thresholdUs,
931            (long long)(targetDurationUs - lastEnqueueUs));
932
933    if (targetDurationUs - lastEnqueueUs > thresholdUs) {
934        return true;
935    }
936    return false;
937}
938
939bool PlaylistFetcher::initDownloadState(
940        AString &uri,
941        sp<AMessage> &itemMeta,
942        int32_t &firstSeqNumberInPlaylist,
943        int32_t &lastSeqNumberInPlaylist) {
944    status_t err = refreshPlaylist();
945    firstSeqNumberInPlaylist = 0;
946    lastSeqNumberInPlaylist = 0;
947    bool discontinuity = false;
948
949    if (mPlaylist != NULL) {
950        if (mPlaylist->meta() != NULL) {
951            mPlaylist->meta()->findInt32("media-sequence", &firstSeqNumberInPlaylist);
952        }
953
954        lastSeqNumberInPlaylist =
955                firstSeqNumberInPlaylist + (int32_t)mPlaylist->size() - 1;
956
957        if (mDiscontinuitySeq < 0) {
958            mDiscontinuitySeq = mPlaylist->getDiscontinuitySeq();
959        }
960    }
961
962    mSegmentFirstPTS = -1ll;
963
964    if (mPlaylist != NULL && mSeqNumber < 0) {
965        CHECK_GE(mStartTimeUs, 0ll);
966
967        if (mSegmentStartTimeUs < 0) {
968            if (!mPlaylist->isComplete() && !mPlaylist->isEvent()) {
969                // If this is a live session, start 3 segments from the end on connect
970                mSeqNumber = lastSeqNumberInPlaylist - 3;
971                if (mSeqNumber < firstSeqNumberInPlaylist) {
972                    mSeqNumber = firstSeqNumberInPlaylist;
973                }
974            } else {
975                // When seeking mSegmentStartTimeUs is unavailable (< 0), we
976                // use mStartTimeUs (client supplied timestamp) to determine both start segment
977                // and relative position inside a segment
978                mSeqNumber = getSeqNumberForTime(mStartTimeUs);
979                mStartTimeUs -= getSegmentStartTimeUs(mSeqNumber);
980            }
981            mStartTimeUsRelative = true;
982            FLOGV("Initial sequence number for time %lld is %d from (%d .. %d)",
983                    (long long)mStartTimeUs, mSeqNumber, firstSeqNumberInPlaylist,
984                    lastSeqNumberInPlaylist);
985        } else {
986            // When adapting or track switching, mSegmentStartTimeUs (relative
987            // to media time 0) is used to determine the start segment; mStartTimeUs (absolute
988            // timestamps coming from the media container) is used to determine the position
989            // inside a segments.
990            mSeqNumber = getSeqNumberForTime(mSegmentStartTimeUs);
991            if (mStreamTypeMask != LiveSession::STREAMTYPE_SUBTITLES
992                    && mSeekMode != LiveSession::kSeekModeNextSample) {
993                // avoid double fetch/decode
994                mSeqNumber += 1;
995            }
996            ssize_t minSeq = getSeqNumberForDiscontinuity(mDiscontinuitySeq);
997            if (mSeqNumber < minSeq) {
998                mSeqNumber = minSeq;
999            }
1000
1001            if (mSeqNumber < firstSeqNumberInPlaylist) {
1002                mSeqNumber = firstSeqNumberInPlaylist;
1003            }
1004
1005            if (mSeqNumber > lastSeqNumberInPlaylist) {
1006                mSeqNumber = lastSeqNumberInPlaylist;
1007            }
1008            FLOGV("Initial sequence number is %d from (%d .. %d)",
1009                    mSeqNumber, firstSeqNumberInPlaylist,
1010                    lastSeqNumberInPlaylist);
1011        }
1012    }
1013
1014    // if mPlaylist is NULL then err must be non-OK; but the other way around might not be true
1015    if (mSeqNumber < firstSeqNumberInPlaylist
1016            || mSeqNumber > lastSeqNumberInPlaylist
1017            || err != OK) {
1018        if ((err != OK || !mPlaylist->isComplete()) && mNumRetries < kMaxNumRetries) {
1019            ++mNumRetries;
1020
1021            if (mSeqNumber > lastSeqNumberInPlaylist || err != OK) {
1022                // make sure we reach this retry logic on refresh failures
1023                // by adding an err != OK clause to all enclosing if's.
1024
1025                // refresh in increasing fraction (1/2, 1/3, ...) of the
1026                // playlist's target duration or 3 seconds, whichever is less
1027                int64_t delayUs = kMaxMonitorDelayUs;
1028                if (mPlaylist != NULL && mPlaylist->meta() != NULL) {
1029                    int32_t targetDurationSecs;
1030                    CHECK(mPlaylist->meta()->findInt32("target-duration", &targetDurationSecs));
1031                    delayUs = mPlaylist->size() * targetDurationSecs *
1032                            1000000ll / (1 + mNumRetries);
1033                }
1034                if (delayUs > kMaxMonitorDelayUs) {
1035                    delayUs = kMaxMonitorDelayUs;
1036                }
1037                FLOGV("sequence number high: %d from (%d .. %d), "
1038                      "monitor in %lld (retry=%d)",
1039                        mSeqNumber, firstSeqNumberInPlaylist,
1040                        lastSeqNumberInPlaylist, (long long)delayUs, mNumRetries);
1041                postMonitorQueue(delayUs);
1042                return false;
1043            }
1044
1045            if (err != OK) {
1046                notifyError(err);
1047                return false;
1048            }
1049
1050            // we've missed the boat, let's start 3 segments prior to the latest sequence
1051            // number available and signal a discontinuity.
1052
1053            ALOGI("We've missed the boat, restarting playback."
1054                  "  mStartup=%d, was  looking for %d in %d-%d",
1055                    mStartup, mSeqNumber, firstSeqNumberInPlaylist,
1056                    lastSeqNumberInPlaylist);
1057            if (mStopParams != NULL) {
1058                // we should have kept on fetching until we hit the boundaries in mStopParams,
1059                // but since the segments we are supposed to fetch have already rolled off
1060                // the playlist, i.e. we have already missed the boat, we inevitably have to
1061                // skip.
1062                notifyStopReached();
1063                return false;
1064            }
1065            mSeqNumber = lastSeqNumberInPlaylist - 3;
1066            if (mSeqNumber < firstSeqNumberInPlaylist) {
1067                mSeqNumber = firstSeqNumberInPlaylist;
1068            }
1069            discontinuity = true;
1070
1071            // fall through
1072        } else {
1073            if (mPlaylist != NULL) {
1074                ALOGE("Cannot find sequence number %d in playlist "
1075                     "(contains %d - %d)",
1076                     mSeqNumber, firstSeqNumberInPlaylist,
1077                      firstSeqNumberInPlaylist + (int32_t)mPlaylist->size() - 1);
1078
1079                notifyError(ERROR_END_OF_STREAM);
1080            } else {
1081                // It's possible that we were never able to download the playlist.
1082                // In this case we should notify error, instead of EOS, as EOS during
1083                // prepare means we succeeded in downloading everything.
1084                ALOGE("Failed to download playlist!");
1085                notifyError(ERROR_IO);
1086            }
1087
1088            return false;
1089        }
1090    }
1091
1092    mNumRetries = 0;
1093
1094    CHECK(mPlaylist->itemAt(
1095                mSeqNumber - firstSeqNumberInPlaylist,
1096                &uri,
1097                &itemMeta));
1098
1099    CHECK(itemMeta->findInt32("discontinuity-sequence", &mDiscontinuitySeq));
1100
1101    int32_t val;
1102    if (itemMeta->findInt32("discontinuity", &val) && val != 0) {
1103        discontinuity = true;
1104    } else if (mLastDiscontinuitySeq >= 0
1105            && mDiscontinuitySeq != mLastDiscontinuitySeq) {
1106        // Seek jumped to a new discontinuity sequence. We need to signal
1107        // a format change to decoder. Decoder needs to shutdown and be
1108        // created again if seamless format change is unsupported.
1109        FLOGV("saw discontinuity: mStartup %d, mLastDiscontinuitySeq %d, "
1110                "mDiscontinuitySeq %d, mStartTimeUs %lld",
1111                mStartup, mLastDiscontinuitySeq, mDiscontinuitySeq, (long long)mStartTimeUs);
1112        discontinuity = true;
1113    }
1114    mLastDiscontinuitySeq = -1;
1115
1116    // decrypt a junk buffer to prefetch key; since a session uses only one http connection,
1117    // this avoids interleaved connections to the key and segment file.
1118    {
1119        sp<ABuffer> junk = new ABuffer(16);
1120        junk->setRange(0, 16);
1121        status_t err = decryptBuffer(mSeqNumber - firstSeqNumberInPlaylist, junk,
1122                true /* first */);
1123        if (err != OK) {
1124            notifyError(err);
1125            return false;
1126        }
1127    }
1128
1129    if ((mStartup && !mTimeChangeSignaled) || discontinuity) {
1130        // We need to signal a time discontinuity to ATSParser on the
1131        // first segment after start, or on a discontinuity segment.
1132        // Setting mNextPTSTimeUs informs extractAndQueueAccessUnitsXX()
1133        // to send the time discontinuity.
1134        if (mPlaylist->isComplete() || mPlaylist->isEvent()) {
1135            // If this was a live event this made no sense since
1136            // we don't have access to all the segment before the current
1137            // one.
1138            mNextPTSTimeUs = getSegmentStartTimeUs(mSeqNumber);
1139        }
1140
1141        // Setting mTimeChangeSignaled to true, so that if start time
1142        // searching goes into 2nd segment (without a discontinuity),
1143        // we don't reset time again. It causes corruption when pending
1144        // data in ATSParser is cleared.
1145        mTimeChangeSignaled = true;
1146    }
1147
1148    if (discontinuity) {
1149        ALOGI("queueing discontinuity (explicit=%d)", discontinuity);
1150
1151        // Signal a format discontinuity to ATSParser to clear partial data
1152        // from previous streams. Not doing this causes bitstream corruption.
1153        if (mTSParser != NULL) {
1154            mTSParser->signalDiscontinuity(
1155                    ATSParser::DISCONTINUITY_FORMATCHANGE, NULL /* extra */);
1156        }
1157
1158        queueDiscontinuity(
1159                ATSParser::DISCONTINUITY_FORMATCHANGE,
1160                NULL /* extra */);
1161
1162        if (mStartup && mStartTimeUsRelative && mFirstPTSValid) {
1163            // This means we guessed mStartTimeUs to be in the previous
1164            // segment (likely very close to the end), but either video or
1165            // audio has not found start by the end of that segment.
1166            //
1167            // If this new segment is not a discontinuity, keep searching.
1168            //
1169            // If this new segment even got a discontinuity marker, just
1170            // set mStartTimeUs=0, and take all samples from now on.
1171            mStartTimeUs = 0;
1172            mFirstPTSValid = false;
1173        }
1174    }
1175
1176    FLOGV("fetching segment %d from (%d .. %d)",
1177            mSeqNumber, firstSeqNumberInPlaylist, lastSeqNumberInPlaylist);
1178    return true;
1179}
1180
1181void PlaylistFetcher::onDownloadNext() {
1182    AString uri;
1183    sp<AMessage> itemMeta;
1184    sp<ABuffer> buffer;
1185    sp<ABuffer> tsBuffer;
1186    int32_t firstSeqNumberInPlaylist = 0;
1187    int32_t lastSeqNumberInPlaylist = 0;
1188    bool connectHTTP = true;
1189
1190    if (mDownloadState->hasSavedState()) {
1191        mDownloadState->restoreState(
1192                uri,
1193                itemMeta,
1194                buffer,
1195                tsBuffer,
1196                firstSeqNumberInPlaylist,
1197                lastSeqNumberInPlaylist);
1198        connectHTTP = false;
1199        FLOGV("resuming: '%s'", uri.c_str());
1200    } else {
1201        if (!initDownloadState(
1202                uri,
1203                itemMeta,
1204                firstSeqNumberInPlaylist,
1205                lastSeqNumberInPlaylist)) {
1206            return;
1207        }
1208        FLOGV("fetching: '%s'", uri.c_str());
1209    }
1210
1211    int64_t range_offset, range_length;
1212    if (!itemMeta->findInt64("range-offset", &range_offset)
1213            || !itemMeta->findInt64("range-length", &range_length)) {
1214        range_offset = 0;
1215        range_length = -1;
1216    }
1217
1218    // block-wise download
1219    bool shouldPause = false;
1220    ssize_t bytesRead;
1221    do {
1222        sp<DataSource> source = mHTTPDataSource;
1223
1224        int64_t startUs = ALooper::GetNowUs();
1225        bytesRead = mSession->fetchFile(
1226                uri.c_str(), &buffer, range_offset, range_length, kDownloadBlockSize,
1227                &source, NULL, connectHTTP);
1228
1229        // add sample for bandwidth estimation, excluding samples from subtitles (as
1230        // its too small), or during startup/resumeUntil (when we could have more than
1231        // one connection open which affects bandwidth)
1232        if (!mStartup && mStopParams == NULL && bytesRead > 0
1233                && (mStreamTypeMask
1234                        & (LiveSession::STREAMTYPE_AUDIO
1235                        | LiveSession::STREAMTYPE_VIDEO))) {
1236            int64_t delayUs = ALooper::GetNowUs() - startUs;
1237            mSession->addBandwidthMeasurement(bytesRead, delayUs);
1238
1239            if (delayUs > 2000000ll) {
1240                FLOGV("bytesRead %zd took %.2f seconds - abnormal bandwidth dip",
1241                        bytesRead, (double)delayUs / 1.0e6);
1242            }
1243        }
1244
1245        connectHTTP = false;
1246
1247        if (bytesRead < 0) {
1248            status_t err = bytesRead;
1249            ALOGE("failed to fetch .ts segment at url '%s'", uri.c_str());
1250            notifyError(err);
1251            return;
1252        }
1253
1254        CHECK(buffer != NULL);
1255
1256        size_t size = buffer->size();
1257        // Set decryption range.
1258        buffer->setRange(size - bytesRead, bytesRead);
1259        status_t err = decryptBuffer(mSeqNumber - firstSeqNumberInPlaylist, buffer,
1260                buffer->offset() == 0 /* first */);
1261        // Unset decryption range.
1262        buffer->setRange(0, size);
1263
1264        if (err != OK) {
1265            ALOGE("decryptBuffer failed w/ error %d", err);
1266
1267            notifyError(err);
1268            return;
1269        }
1270
1271        bool startUp = mStartup; // save current start up state
1272
1273        err = OK;
1274        if (bufferStartsWithTsSyncByte(buffer)) {
1275            // Incremental extraction is only supported for MPEG2 transport streams.
1276            if (tsBuffer == NULL) {
1277                tsBuffer = new ABuffer(buffer->data(), buffer->capacity());
1278                tsBuffer->setRange(0, 0);
1279            } else if (tsBuffer->capacity() != buffer->capacity()) {
1280                size_t tsOff = tsBuffer->offset(), tsSize = tsBuffer->size();
1281                tsBuffer = new ABuffer(buffer->data(), buffer->capacity());
1282                tsBuffer->setRange(tsOff, tsSize);
1283            }
1284            tsBuffer->setRange(tsBuffer->offset(), tsBuffer->size() + bytesRead);
1285            err = extractAndQueueAccessUnitsFromTs(tsBuffer);
1286        }
1287
1288        if (err == -EAGAIN) {
1289            // starting sequence number too low/high
1290            mTSParser.clear();
1291            for (size_t i = 0; i < mPacketSources.size(); i++) {
1292                sp<AnotherPacketSource> packetSource = mPacketSources.valueAt(i);
1293                packetSource->clear();
1294            }
1295            postMonitorQueue();
1296            return;
1297        } else if (err == ERROR_OUT_OF_RANGE) {
1298            // reached stopping point
1299            notifyStopReached();
1300            return;
1301        } else if (err != OK) {
1302            notifyError(err);
1303            return;
1304        }
1305        // If we're switching, post start notification
1306        // this should only be posted when the last chunk is full processed by TSParser
1307        if (mSeekMode != LiveSession::kSeekModeExactPosition && startUp != mStartup) {
1308            CHECK(mStartTimeUsNotify != NULL);
1309            mStartTimeUsNotify->post();
1310            mStartTimeUsNotify.clear();
1311            shouldPause = true;
1312        }
1313        if (shouldPause || shouldPauseDownload()) {
1314            // save state and return if this is not the last chunk,
1315            // leaving the fetcher in paused state.
1316            if (bytesRead != 0) {
1317                mDownloadState->saveState(
1318                        uri,
1319                        itemMeta,
1320                        buffer,
1321                        tsBuffer,
1322                        firstSeqNumberInPlaylist,
1323                        lastSeqNumberInPlaylist);
1324                return;
1325            }
1326            shouldPause = true;
1327        }
1328    } while (bytesRead != 0);
1329
1330    if (bufferStartsWithTsSyncByte(buffer)) {
1331        // If we don't see a stream in the program table after fetching a full ts segment
1332        // mark it as nonexistent.
1333        ATSParser::SourceType srcTypes[] =
1334                { ATSParser::VIDEO, ATSParser::AUDIO };
1335        LiveSession::StreamType streamTypes[] =
1336                { LiveSession::STREAMTYPE_VIDEO, LiveSession::STREAMTYPE_AUDIO };
1337        const size_t kNumTypes = NELEM(srcTypes);
1338
1339        for (size_t i = 0; i < kNumTypes; i++) {
1340            ATSParser::SourceType srcType = srcTypes[i];
1341            LiveSession::StreamType streamType = streamTypes[i];
1342
1343            sp<AnotherPacketSource> source =
1344                static_cast<AnotherPacketSource *>(
1345                    mTSParser->getSource(srcType).get());
1346
1347            if (!mTSParser->hasSource(srcType)) {
1348                ALOGW("MPEG2 Transport stream does not contain %s data.",
1349                      srcType == ATSParser::VIDEO ? "video" : "audio");
1350
1351                mStreamTypeMask &= ~streamType;
1352                mPacketSources.removeItem(streamType);
1353            }
1354        }
1355
1356    }
1357
1358    if (checkDecryptPadding(buffer) != OK) {
1359        ALOGE("Incorrect padding bytes after decryption.");
1360        notifyError(ERROR_MALFORMED);
1361        return;
1362    }
1363
1364    if (tsBuffer != NULL) {
1365        AString method;
1366        CHECK(buffer->meta()->findString("cipher-method", &method));
1367        if ((tsBuffer->size() > 0 && method == "NONE")
1368                || tsBuffer->size() > 16) {
1369            ALOGE("MPEG2 transport stream is not an even multiple of 188 "
1370                    "bytes in length.");
1371            notifyError(ERROR_MALFORMED);
1372            return;
1373        }
1374    }
1375
1376    // bulk extract non-ts files
1377    bool startUp = mStartup;
1378    if (tsBuffer == NULL) {
1379        status_t err = extractAndQueueAccessUnits(buffer, itemMeta);
1380        if (err == -EAGAIN) {
1381            // starting sequence number too low/high
1382            postMonitorQueue();
1383            return;
1384        } else if (err == ERROR_OUT_OF_RANGE) {
1385            // reached stopping point
1386            notifyStopReached();
1387            return;
1388        } else if (err != OK) {
1389            notifyError(err);
1390            return;
1391        }
1392    }
1393
1394    ++mSeqNumber;
1395
1396    // if adapting, pause after found the next starting point
1397    if (mSeekMode != LiveSession::kSeekModeExactPosition && startUp != mStartup) {
1398        CHECK(mStartTimeUsNotify != NULL);
1399        mStartTimeUsNotify->post();
1400        mStartTimeUsNotify.clear();
1401        shouldPause = true;
1402    }
1403
1404    if (!shouldPause) {
1405        postMonitorQueue();
1406    }
1407}
1408
1409int32_t PlaylistFetcher::getSeqNumberWithAnchorTime(
1410        int64_t anchorTimeUs, int64_t targetDiffUs) const {
1411    int32_t firstSeqNumberInPlaylist, lastSeqNumberInPlaylist;
1412    if (mPlaylist->meta() == NULL
1413            || !mPlaylist->meta()->findInt32("media-sequence", &firstSeqNumberInPlaylist)) {
1414        firstSeqNumberInPlaylist = 0;
1415    }
1416    lastSeqNumberInPlaylist = firstSeqNumberInPlaylist + mPlaylist->size() - 1;
1417
1418    int32_t index = mSeqNumber - firstSeqNumberInPlaylist - 1;
1419    // adjust anchorTimeUs to within targetDiffUs from mStartTimeUs
1420    while (index >= 0 && anchorTimeUs - mStartTimeUs > targetDiffUs) {
1421        sp<AMessage> itemMeta;
1422        CHECK(mPlaylist->itemAt(index, NULL /* uri */, &itemMeta));
1423
1424        int64_t itemDurationUs;
1425        CHECK(itemMeta->findInt64("durationUs", &itemDurationUs));
1426
1427        anchorTimeUs -= itemDurationUs;
1428        --index;
1429    }
1430
1431    int32_t newSeqNumber = firstSeqNumberInPlaylist + index + 1;
1432    if (newSeqNumber <= lastSeqNumberInPlaylist) {
1433        return newSeqNumber;
1434    } else {
1435        return lastSeqNumberInPlaylist;
1436    }
1437}
1438
1439int32_t PlaylistFetcher::getSeqNumberForDiscontinuity(size_t discontinuitySeq) const {
1440    int32_t firstSeqNumberInPlaylist;
1441    if (mPlaylist->meta() == NULL || !mPlaylist->meta()->findInt32(
1442                "media-sequence", &firstSeqNumberInPlaylist)) {
1443        firstSeqNumberInPlaylist = 0;
1444    }
1445
1446    size_t index = 0;
1447    while (index < mPlaylist->size()) {
1448        sp<AMessage> itemMeta;
1449        CHECK(mPlaylist->itemAt( index, NULL /* uri */, &itemMeta));
1450        size_t curDiscontinuitySeq;
1451        CHECK(itemMeta->findInt32("discontinuity-sequence", (int32_t *)&curDiscontinuitySeq));
1452        int32_t seqNumber = firstSeqNumberInPlaylist + index;
1453        if (curDiscontinuitySeq == discontinuitySeq) {
1454            return seqNumber;
1455        } else if (curDiscontinuitySeq > discontinuitySeq) {
1456            return seqNumber <= 0 ? 0 : seqNumber - 1;
1457        }
1458
1459        ++index;
1460    }
1461
1462    return firstSeqNumberInPlaylist + mPlaylist->size();
1463}
1464
1465int32_t PlaylistFetcher::getSeqNumberForTime(int64_t timeUs) const {
1466    int32_t firstSeqNumberInPlaylist;
1467    if (mPlaylist->meta() == NULL || !mPlaylist->meta()->findInt32(
1468                "media-sequence", &firstSeqNumberInPlaylist)) {
1469        firstSeqNumberInPlaylist = 0;
1470    }
1471
1472    size_t index = 0;
1473    int64_t segmentStartUs = 0;
1474    while (index < mPlaylist->size()) {
1475        sp<AMessage> itemMeta;
1476        CHECK(mPlaylist->itemAt(
1477                    index, NULL /* uri */, &itemMeta));
1478
1479        int64_t itemDurationUs;
1480        CHECK(itemMeta->findInt64("durationUs", &itemDurationUs));
1481
1482        if (timeUs < segmentStartUs + itemDurationUs) {
1483            break;
1484        }
1485
1486        segmentStartUs += itemDurationUs;
1487        ++index;
1488    }
1489
1490    if (index >= mPlaylist->size()) {
1491        index = mPlaylist->size() - 1;
1492    }
1493
1494    return firstSeqNumberInPlaylist + index;
1495}
1496
1497const sp<ABuffer> &PlaylistFetcher::setAccessUnitProperties(
1498        const sp<ABuffer> &accessUnit, const sp<AnotherPacketSource> &source, bool discard) {
1499    sp<MetaData> format = source->getFormat();
1500    if (format != NULL) {
1501        // for simplicity, store a reference to the format in each unit
1502        accessUnit->meta()->setObject("format", format);
1503    }
1504
1505    if (discard) {
1506        accessUnit->meta()->setInt32("discard", discard);
1507    }
1508
1509    int32_t targetDurationSecs;
1510    if (mPlaylist->meta()->findInt32("target-duration", &targetDurationSecs)) {
1511        accessUnit->meta()->setInt32("targetDuration", targetDurationSecs);
1512    }
1513
1514    accessUnit->meta()->setInt32("discontinuitySeq", mDiscontinuitySeq);
1515    accessUnit->meta()->setInt64("segmentStartTimeUs", getSegmentStartTimeUs(mSeqNumber));
1516    accessUnit->meta()->setInt64("segmentDurationUs", getSegmentDurationUs(mSeqNumber));
1517    return accessUnit;
1518}
1519
1520bool PlaylistFetcher::isStartTimeReached(int64_t timeUs) {
1521    if (!mFirstPTSValid) {
1522        mFirstTimeUs = timeUs;
1523        mFirstPTSValid = true;
1524    }
1525    bool startTimeReached = true;
1526    if (mStartTimeUsRelative) {
1527        FLOGV("startTimeUsRelative, timeUs (%lld) - %lld = %lld",
1528                (long long)timeUs,
1529                (long long)mFirstTimeUs,
1530                (long long)(timeUs - mFirstTimeUs));
1531        timeUs -= mFirstTimeUs;
1532        if (timeUs < 0) {
1533            FLOGV("clamp negative timeUs to 0");
1534            timeUs = 0;
1535        }
1536        startTimeReached = (timeUs >= mStartTimeUs);
1537    }
1538    return startTimeReached;
1539}
1540
1541status_t PlaylistFetcher::extractAndQueueAccessUnitsFromTs(const sp<ABuffer> &buffer) {
1542    if (mTSParser == NULL) {
1543        // Use TS_TIMESTAMPS_ARE_ABSOLUTE so pts carry over between fetchers.
1544        mTSParser = new ATSParser(ATSParser::TS_TIMESTAMPS_ARE_ABSOLUTE);
1545    }
1546
1547    if (mNextPTSTimeUs >= 0ll) {
1548        sp<AMessage> extra = new AMessage;
1549        // Since we are using absolute timestamps, signal an offset of 0 to prevent
1550        // ATSParser from skewing the timestamps of access units.
1551        extra->setInt64(IStreamListener::kKeyMediaTimeUs, 0);
1552
1553        // When adapting, signal a recent media time to the parser,
1554        // so that PTS wrap around is handled for the new variant.
1555        if (mStartTimeUs >= 0 && !mStartTimeUsRelative) {
1556            extra->setInt64(IStreamListener::kKeyRecentMediaTimeUs, mStartTimeUs);
1557        }
1558
1559        mTSParser->signalDiscontinuity(
1560                ATSParser::DISCONTINUITY_TIME, extra);
1561
1562        mNextPTSTimeUs = -1ll;
1563    }
1564
1565    size_t offset = 0;
1566    while (offset + 188 <= buffer->size()) {
1567        status_t err = mTSParser->feedTSPacket(buffer->data() + offset, 188);
1568
1569        if (err != OK) {
1570            return err;
1571        }
1572
1573        offset += 188;
1574    }
1575    // setRange to indicate consumed bytes.
1576    buffer->setRange(buffer->offset() + offset, buffer->size() - offset);
1577
1578    status_t err = OK;
1579    for (size_t i = mPacketSources.size(); i-- > 0;) {
1580        sp<AnotherPacketSource> packetSource = mPacketSources.valueAt(i);
1581
1582        const LiveSession::StreamType stream = mPacketSources.keyAt(i);
1583        if (stream == LiveSession::STREAMTYPE_SUBTITLES) {
1584            ALOGE("MPEG2 Transport streams do not contain subtitles.");
1585            return ERROR_MALFORMED;
1586        }
1587
1588        const char *key = LiveSession::getKeyForStream(stream);
1589        ATSParser::SourceType type =LiveSession::getSourceTypeForStream(stream);
1590
1591        sp<AnotherPacketSource> source =
1592            static_cast<AnotherPacketSource *>(
1593                    mTSParser->getSource(type).get());
1594
1595        if (source == NULL) {
1596            continue;
1597        }
1598
1599        const char *mime;
1600        sp<MetaData> format  = source->getFormat();
1601        bool isAvc = format != NULL && format->findCString(kKeyMIMEType, &mime)
1602                && !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
1603
1604        sp<ABuffer> accessUnit;
1605        status_t finalResult;
1606        while (source->hasBufferAvailable(&finalResult)
1607                && source->dequeueAccessUnit(&accessUnit) == OK) {
1608
1609            int64_t timeUs;
1610            CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs));
1611
1612            if (mSegmentFirstPTS < 0ll) {
1613                mSegmentFirstPTS = timeUs;
1614                if (!mStartTimeUsRelative) {
1615                    int32_t firstSeqNumberInPlaylist;
1616                    if (mPlaylist->meta() == NULL || !mPlaylist->meta()->findInt32(
1617                                "media-sequence", &firstSeqNumberInPlaylist)) {
1618                        firstSeqNumberInPlaylist = 0;
1619                    }
1620
1621                    int32_t targetDurationSecs;
1622                    CHECK(mPlaylist->meta()->findInt32("target-duration", &targetDurationSecs));
1623                    int64_t targetDurationUs = targetDurationSecs * 1000000ll;
1624                    // mStartup
1625                    //   mStartup is true until we have queued a packet for all the streams
1626                    //   we are fetching. We queue packets whose timestamps are greater than
1627                    //   mStartTimeUs.
1628                    // mSegmentStartTimeUs >= 0
1629                    //   mSegmentStartTimeUs is non-negative when adapting or switching tracks
1630                    // mSeqNumber > firstSeqNumberInPlaylist
1631                    //   don't decrement mSeqNumber if it already points to the 1st segment
1632                    // timeUs - mStartTimeUs > targetDurationUs:
1633                    //   This and the 2 above conditions should only happen when adapting in a live
1634                    //   stream; the old fetcher has already fetched to mStartTimeUs; the new fetcher
1635                    //   would start fetching after timeUs, which should be greater than mStartTimeUs;
1636                    //   the old fetcher would then continue fetching data until timeUs. We don't want
1637                    //   timeUs to be too far ahead of mStartTimeUs because we want the old fetcher to
1638                    //   stop as early as possible. The definition of being "too far ahead" is
1639                    //   arbitrary; here we use targetDurationUs as threshold.
1640                    int64_t targetDiffUs = (mSeekMode == LiveSession::kSeekModeNextSample
1641                            ? 0 : targetDurationUs);
1642                    if (mStartup && mSegmentStartTimeUs >= 0
1643                            && mSeqNumber > firstSeqNumberInPlaylist
1644                            && timeUs - mStartTimeUs > targetDiffUs) {
1645                        // we just guessed a starting timestamp that is too high when adapting in a
1646                        // live stream; re-adjust based on the actual timestamp extracted from the
1647                        // media segment; if we didn't move backward after the re-adjustment
1648                        // (newSeqNumber), start at least 1 segment prior.
1649                        int32_t newSeqNumber = getSeqNumberWithAnchorTime(
1650                                timeUs, targetDiffUs);
1651
1652                        FLOGV("guessed wrong seq number: timeUs=%lld, mStartTimeUs=%lld, "
1653                                "targetDurationUs=%lld, mSeqNumber=%d, newSeq=%d, firstSeq=%d",
1654                                (long long)timeUs,
1655                                (long long)mStartTimeUs,
1656                                (long long)targetDurationUs,
1657                                mSeqNumber,
1658                                newSeqNumber,
1659                                firstSeqNumberInPlaylist);
1660
1661                        if (newSeqNumber >= mSeqNumber) {
1662                            --mSeqNumber;
1663                        } else {
1664                            mSeqNumber = newSeqNumber;
1665                        }
1666                        mStartTimeUsNotify = mNotify->dup();
1667                        mStartTimeUsNotify->setInt32("what", kWhatStartedAt);
1668                        mStartTimeUsNotify->setString("uri", mURI);
1669                        mIDRFound = false;
1670                        return -EAGAIN;
1671                    }
1672                }
1673            }
1674            if (mStartup) {
1675                bool startTimeReached = isStartTimeReached(timeUs);
1676
1677                if (!startTimeReached || (isAvc && !mIDRFound)) {
1678                    // buffer up to the closest preceding IDR frame in the next segement,
1679                    // or the closest succeeding IDR frame after the exact position
1680                    FSLOGV(stream, "timeUs=%lld, mStartTimeUs=%lld, mIDRFound=%d",
1681                            (long long)timeUs, (long long)mStartTimeUs, mIDRFound);
1682                    if (isAvc) {
1683                        if (IsIDR(accessUnit)) {
1684                            mVideoBuffer->clear();
1685                            FSLOGV(stream, "found IDR, clear mVideoBuffer");
1686                            mIDRFound = true;
1687                        }
1688                        if (mIDRFound && mStartTimeUsRelative && !startTimeReached) {
1689                            mVideoBuffer->queueAccessUnit(accessUnit);
1690                            FSLOGV(stream, "saving AVC video AccessUnit");
1691                        }
1692                    }
1693                    if (!startTimeReached || (isAvc && !mIDRFound)) {
1694                        continue;
1695                    }
1696                }
1697            }
1698
1699            if (mStartTimeUsNotify != NULL) {
1700                uint32_t streamMask = 0;
1701                mStartTimeUsNotify->findInt32("streamMask", (int32_t *) &streamMask);
1702                if ((mStreamTypeMask & mPacketSources.keyAt(i))
1703                        && !(streamMask & mPacketSources.keyAt(i))) {
1704                    streamMask |= mPacketSources.keyAt(i);
1705                    mStartTimeUsNotify->setInt32("streamMask", streamMask);
1706                    FSLOGV(stream, "found start point, timeUs=%lld, streamMask becomes %x",
1707                            (long long)timeUs, streamMask);
1708
1709                    if (streamMask == mStreamTypeMask) {
1710                        FLOGV("found start point for all streams");
1711                        mStartup = false;
1712                    }
1713                }
1714            }
1715
1716            if (mStopParams != NULL) {
1717                int32_t discontinuitySeq;
1718                int64_t stopTimeUs;
1719                if (!mStopParams->findInt32("discontinuitySeq", &discontinuitySeq)
1720                        || discontinuitySeq > mDiscontinuitySeq
1721                        || !mStopParams->findInt64(key, &stopTimeUs)
1722                        || (discontinuitySeq == mDiscontinuitySeq
1723                                && timeUs >= stopTimeUs)) {
1724                    FSLOGV(stream, "reached stop point, timeUs=%lld", (long long)timeUs);
1725                    mStreamTypeMask &= ~stream;
1726                    mPacketSources.removeItemsAt(i);
1727                    break;
1728                }
1729            }
1730
1731            if (stream == LiveSession::STREAMTYPE_VIDEO) {
1732                const bool discard = true;
1733                status_t status;
1734                while (mVideoBuffer->hasBufferAvailable(&status)) {
1735                    sp<ABuffer> videoBuffer;
1736                    mVideoBuffer->dequeueAccessUnit(&videoBuffer);
1737                    setAccessUnitProperties(videoBuffer, source, discard);
1738                    packetSource->queueAccessUnit(videoBuffer);
1739                    int64_t bufferTimeUs;
1740                    CHECK(videoBuffer->meta()->findInt64("timeUs", &bufferTimeUs));
1741                    FSLOGV(stream, "queueAccessUnit (saved), timeUs=%lld",
1742                            (long long)bufferTimeUs);
1743                }
1744            } else if (stream == LiveSession::STREAMTYPE_METADATA && !mHasMetadata) {
1745                mHasMetadata = true;
1746                sp<AMessage> notify = mNotify->dup();
1747                notify->setInt32("what", kWhatMetadataDetected);
1748                notify->post();
1749            }
1750
1751            setAccessUnitProperties(accessUnit, source);
1752            packetSource->queueAccessUnit(accessUnit);
1753            FSLOGV(stream, "queueAccessUnit, timeUs=%lld", (long long)timeUs);
1754        }
1755
1756        if (err != OK) {
1757            break;
1758        }
1759    }
1760
1761    if (err != OK) {
1762        for (size_t i = mPacketSources.size(); i-- > 0;) {
1763            sp<AnotherPacketSource> packetSource = mPacketSources.valueAt(i);
1764            packetSource->clear();
1765        }
1766        return err;
1767    }
1768
1769    if (!mStreamTypeMask) {
1770        // Signal gap is filled between original and new stream.
1771        FLOGV("reached stop point for all streams");
1772        return ERROR_OUT_OF_RANGE;
1773    }
1774
1775    return OK;
1776}
1777
1778/* static */
1779bool PlaylistFetcher::bufferStartsWithWebVTTMagicSequence(
1780        const sp<ABuffer> &buffer) {
1781    size_t pos = 0;
1782
1783    // skip possible BOM
1784    if (buffer->size() >= pos + 3 &&
1785            !memcmp("\xef\xbb\xbf", buffer->data() + pos, 3)) {
1786        pos += 3;
1787    }
1788
1789    // accept WEBVTT followed by SPACE, TAB or (CR) LF
1790    if (buffer->size() < pos + 6 ||
1791            memcmp("WEBVTT", buffer->data() + pos, 6)) {
1792        return false;
1793    }
1794    pos += 6;
1795
1796    if (buffer->size() == pos) {
1797        return true;
1798    }
1799
1800    uint8_t sep = buffer->data()[pos];
1801    return sep == ' ' || sep == '\t' || sep == '\n' || sep == '\r';
1802}
1803
1804status_t PlaylistFetcher::extractAndQueueAccessUnits(
1805        const sp<ABuffer> &buffer, const sp<AMessage> &itemMeta) {
1806    if (bufferStartsWithWebVTTMagicSequence(buffer)) {
1807        if (mStreamTypeMask != LiveSession::STREAMTYPE_SUBTITLES) {
1808            ALOGE("This stream only contains subtitles.");
1809            return ERROR_MALFORMED;
1810        }
1811
1812        const sp<AnotherPacketSource> packetSource =
1813            mPacketSources.valueFor(LiveSession::STREAMTYPE_SUBTITLES);
1814
1815        int64_t durationUs;
1816        CHECK(itemMeta->findInt64("durationUs", &durationUs));
1817        buffer->meta()->setInt64("timeUs", getSegmentStartTimeUs(mSeqNumber));
1818        buffer->meta()->setInt64("durationUs", durationUs);
1819        buffer->meta()->setInt64("segmentStartTimeUs", getSegmentStartTimeUs(mSeqNumber));
1820        buffer->meta()->setInt32("discontinuitySeq", mDiscontinuitySeq);
1821        buffer->meta()->setInt32("subtitleGeneration", mSubtitleGeneration);
1822
1823        packetSource->queueAccessUnit(buffer);
1824        return OK;
1825    }
1826
1827    if (mNextPTSTimeUs >= 0ll) {
1828        mNextPTSTimeUs = -1ll;
1829    }
1830
1831    // This better be an ISO 13818-7 (AAC) or ISO 13818-1 (MPEG) audio
1832    // stream prefixed by an ID3 tag.
1833
1834    bool firstID3Tag = true;
1835    uint64_t PTS = 0;
1836
1837    for (;;) {
1838        // Make sure to skip all ID3 tags preceding the audio data.
1839        // At least one must be present to provide the PTS timestamp.
1840
1841        ID3 id3(buffer->data(), buffer->size(), true /* ignoreV1 */);
1842        if (!id3.isValid()) {
1843            if (firstID3Tag) {
1844                ALOGE("Unable to parse ID3 tag.");
1845                return ERROR_MALFORMED;
1846            } else {
1847                break;
1848            }
1849        }
1850
1851        if (firstID3Tag) {
1852            bool found = false;
1853
1854            ID3::Iterator it(id3, "PRIV");
1855            while (!it.done()) {
1856                size_t length;
1857                const uint8_t *data = it.getData(&length);
1858
1859                static const char *kMatchName =
1860                    "com.apple.streaming.transportStreamTimestamp";
1861                static const size_t kMatchNameLen = strlen(kMatchName);
1862
1863                if (length == kMatchNameLen + 1 + 8
1864                        && !strncmp((const char *)data, kMatchName, kMatchNameLen)) {
1865                    found = true;
1866                    PTS = U64_AT(&data[kMatchNameLen + 1]);
1867                }
1868
1869                it.next();
1870            }
1871
1872            if (!found) {
1873                ALOGE("Unable to extract transportStreamTimestamp from ID3 tag.");
1874                return ERROR_MALFORMED;
1875            }
1876        }
1877
1878        // skip the ID3 tag
1879        buffer->setRange(
1880                buffer->offset() + id3.rawSize(), buffer->size() - id3.rawSize());
1881
1882        firstID3Tag = false;
1883    }
1884
1885    if (mStreamTypeMask != LiveSession::STREAMTYPE_AUDIO) {
1886        ALOGW("This stream only contains audio data!");
1887
1888        mStreamTypeMask &= LiveSession::STREAMTYPE_AUDIO;
1889
1890        if (mStreamTypeMask == 0) {
1891            return OK;
1892        }
1893    }
1894
1895    sp<AnotherPacketSource> packetSource =
1896        mPacketSources.valueFor(LiveSession::STREAMTYPE_AUDIO);
1897
1898    if (packetSource->getFormat() == NULL && buffer->size() >= 7) {
1899        ABitReader bits(buffer->data(), buffer->size());
1900
1901        // adts_fixed_header
1902
1903        CHECK_EQ(bits.getBits(12), 0xfffu);
1904        bits.skipBits(3);  // ID, layer
1905        bool protection_absent __unused = bits.getBits(1) != 0;
1906
1907        unsigned profile = bits.getBits(2);
1908        CHECK_NE(profile, 3u);
1909        unsigned sampling_freq_index = bits.getBits(4);
1910        bits.getBits(1);  // private_bit
1911        unsigned channel_configuration = bits.getBits(3);
1912        CHECK_NE(channel_configuration, 0u);
1913        bits.skipBits(2);  // original_copy, home
1914
1915        sp<MetaData> meta = MakeAACCodecSpecificData(
1916                profile, sampling_freq_index, channel_configuration);
1917
1918        meta->setInt32(kKeyIsADTS, true);
1919
1920        packetSource->setFormat(meta);
1921    }
1922
1923    int64_t numSamples = 0ll;
1924    int32_t sampleRate;
1925    CHECK(packetSource->getFormat()->findInt32(kKeySampleRate, &sampleRate));
1926
1927    int64_t timeUs = (PTS * 100ll) / 9ll;
1928    if (mStartup && !mFirstPTSValid) {
1929        mFirstPTSValid = true;
1930        mFirstTimeUs = timeUs;
1931    }
1932
1933    size_t offset = 0;
1934    while (offset < buffer->size()) {
1935        const uint8_t *adtsHeader = buffer->data() + offset;
1936        CHECK_LT(offset + 5, buffer->size());
1937
1938        unsigned aac_frame_length =
1939            ((adtsHeader[3] & 3) << 11)
1940            | (adtsHeader[4] << 3)
1941            | (adtsHeader[5] >> 5);
1942
1943        if (aac_frame_length == 0) {
1944            const uint8_t *id3Header = adtsHeader;
1945            if (!memcmp(id3Header, "ID3", 3)) {
1946                ID3 id3(id3Header, buffer->size() - offset, true);
1947                if (id3.isValid()) {
1948                    offset += id3.rawSize();
1949                    continue;
1950                };
1951            }
1952            return ERROR_MALFORMED;
1953        }
1954
1955        CHECK_LE(offset + aac_frame_length, buffer->size());
1956
1957        int64_t unitTimeUs = timeUs + numSamples * 1000000ll / sampleRate;
1958        offset += aac_frame_length;
1959
1960        // Each AAC frame encodes 1024 samples.
1961        numSamples += 1024;
1962
1963        if (mStartup) {
1964            int64_t startTimeUs = unitTimeUs;
1965            if (mStartTimeUsRelative) {
1966                startTimeUs -= mFirstTimeUs;
1967                if (startTimeUs  < 0) {
1968                    startTimeUs = 0;
1969                }
1970            }
1971            if (startTimeUs < mStartTimeUs) {
1972                continue;
1973            }
1974
1975            if (mStartTimeUsNotify != NULL) {
1976                int32_t targetDurationSecs;
1977                CHECK(mPlaylist->meta()->findInt32("target-duration", &targetDurationSecs));
1978                int64_t targetDurationUs = targetDurationSecs * 1000000ll;
1979
1980                int64_t targetDiffUs =(mSeekMode == LiveSession::kSeekModeNextSample
1981                        ? 0 : targetDurationUs);
1982                // Duplicated logic from how we handle .ts playlists.
1983                if (mStartup && mSegmentStartTimeUs >= 0
1984                        && timeUs - mStartTimeUs > targetDiffUs) {
1985                    int32_t newSeqNumber = getSeqNumberWithAnchorTime(
1986                            timeUs, targetDiffUs);
1987                    if (newSeqNumber >= mSeqNumber) {
1988                        --mSeqNumber;
1989                    } else {
1990                        mSeqNumber = newSeqNumber;
1991                    }
1992                    return -EAGAIN;
1993                }
1994
1995                mStartTimeUsNotify->setInt32("streamMask", LiveSession::STREAMTYPE_AUDIO);
1996                mStartup = false;
1997            }
1998        }
1999
2000        if (mStopParams != NULL) {
2001            int32_t discontinuitySeq;
2002            int64_t stopTimeUs;
2003            if (!mStopParams->findInt32("discontinuitySeq", &discontinuitySeq)
2004                    || discontinuitySeq > mDiscontinuitySeq
2005                    || !mStopParams->findInt64("timeUsAudio", &stopTimeUs)
2006                    || (discontinuitySeq == mDiscontinuitySeq && unitTimeUs >= stopTimeUs)) {
2007                mStreamTypeMask = 0;
2008                mPacketSources.clear();
2009                return ERROR_OUT_OF_RANGE;
2010            }
2011        }
2012
2013        sp<ABuffer> unit = new ABuffer(aac_frame_length);
2014        memcpy(unit->data(), adtsHeader, aac_frame_length);
2015
2016        unit->meta()->setInt64("timeUs", unitTimeUs);
2017        setAccessUnitProperties(unit, packetSource);
2018        packetSource->queueAccessUnit(unit);
2019    }
2020
2021    return OK;
2022}
2023
2024void PlaylistFetcher::updateDuration() {
2025    int64_t durationUs = 0ll;
2026    for (size_t index = 0; index < mPlaylist->size(); ++index) {
2027        sp<AMessage> itemMeta;
2028        CHECK(mPlaylist->itemAt(
2029                    index, NULL /* uri */, &itemMeta));
2030
2031        int64_t itemDurationUs;
2032        CHECK(itemMeta->findInt64("durationUs", &itemDurationUs));
2033
2034        durationUs += itemDurationUs;
2035    }
2036
2037    sp<AMessage> msg = mNotify->dup();
2038    msg->setInt32("what", kWhatDurationUpdate);
2039    msg->setInt64("durationUs", durationUs);
2040    msg->post();
2041}
2042
2043void PlaylistFetcher::updateTargetDuration() {
2044    int32_t targetDurationSecs;
2045    CHECK(mPlaylist->meta()->findInt32("target-duration", &targetDurationSecs));
2046    int64_t targetDurationUs = targetDurationSecs * 1000000ll;
2047
2048    sp<AMessage> msg = mNotify->dup();
2049    msg->setInt32("what", kWhatTargetDurationUpdate);
2050    msg->setInt64("targetDurationUs", targetDurationUs);
2051    msg->post();
2052}
2053
2054}  // namespace android
2055