MatroskaExtractor.cpp revision b2487f03f12dcafdb801fc0007c8df8412397f44
1/*
2 * Copyright (C) 2010 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 "MatroskaExtractor"
19#include <utils/Log.h>
20
21#include "MatroskaExtractor.h"
22
23#include <media/stagefright/foundation/ADebug.h>
24#include <media/stagefright/foundation/AUtils.h>
25#include <media/stagefright/foundation/hexdump.h>
26#include <media/stagefright/DataSource.h>
27#include <media/stagefright/MediaBuffer.h>
28#include <media/stagefright/MediaDefs.h>
29#include <media/stagefright/MediaErrors.h>
30#include <media/stagefright/MediaSource.h>
31#include <media/stagefright/MetaData.h>
32#include <media/stagefright/Utils.h>
33#include <utils/String8.h>
34
35#include <inttypes.h>
36
37namespace android {
38
39struct DataSourceReader : public mkvparser::IMkvReader {
40    DataSourceReader(const sp<DataSource> &source)
41        : mSource(source) {
42    }
43
44    virtual int Read(long long position, long length, unsigned char* buffer) {
45        CHECK(position >= 0);
46        CHECK(length >= 0);
47
48        if (length == 0) {
49            return 0;
50        }
51
52        ssize_t n = mSource->readAt(position, buffer, length);
53
54        if (n <= 0) {
55            return -1;
56        }
57
58        return 0;
59    }
60
61    virtual int Length(long long* total, long long* available) {
62        off64_t size;
63        if (mSource->getSize(&size) != OK) {
64            *total = -1;
65            *available = (long long)((1ull << 63) - 1);
66
67            return 0;
68        }
69
70        if (total) {
71            *total = size;
72        }
73
74        if (available) {
75            *available = size;
76        }
77
78        return 0;
79    }
80
81private:
82    sp<DataSource> mSource;
83
84    DataSourceReader(const DataSourceReader &);
85    DataSourceReader &operator=(const DataSourceReader &);
86};
87
88////////////////////////////////////////////////////////////////////////////////
89
90struct BlockIterator {
91    BlockIterator(MatroskaExtractor *extractor, unsigned long trackNum, unsigned long index);
92
93    bool eos() const;
94
95    void advance();
96    void reset();
97
98    void seek(
99            int64_t seekTimeUs, bool isAudio,
100            int64_t *actualFrameTimeUs);
101
102    const mkvparser::Block *block() const;
103    int64_t blockTimeUs() const;
104
105private:
106    MatroskaExtractor *mExtractor;
107    long long mTrackNum;
108    unsigned long mIndex;
109
110    const mkvparser::Cluster *mCluster;
111    const mkvparser::BlockEntry *mBlockEntry;
112    long mBlockEntryIndex;
113
114    void advance_l();
115
116    BlockIterator(const BlockIterator &);
117    BlockIterator &operator=(const BlockIterator &);
118};
119
120struct MatroskaSource : public MediaSource {
121    MatroskaSource(
122            const sp<MatroskaExtractor> &extractor, size_t index);
123
124    virtual status_t start(MetaData *params);
125    virtual status_t stop();
126
127    virtual sp<MetaData> getFormat();
128
129    virtual status_t read(
130            MediaBuffer **buffer, const ReadOptions *options);
131
132protected:
133    virtual ~MatroskaSource();
134
135private:
136    enum Type {
137        AVC,
138        AAC,
139        OTHER
140    };
141
142    sp<MatroskaExtractor> mExtractor;
143    size_t mTrackIndex;
144    Type mType;
145    bool mIsAudio;
146    BlockIterator mBlockIter;
147    size_t mNALSizeLen;  // for type AVC
148
149    List<MediaBuffer *> mPendingFrames;
150
151    status_t advance();
152
153    status_t readBlock();
154    void clearPendingFrames();
155
156    MatroskaSource(const MatroskaSource &);
157    MatroskaSource &operator=(const MatroskaSource &);
158};
159
160const mkvparser::Track* MatroskaExtractor::TrackInfo::getTrack() const {
161    return mExtractor->mSegment->GetTracks()->GetTrackByNumber(mTrackNum);
162}
163
164// This function does exactly the same as mkvparser::Cues::Find, except that it
165// searches in our own track based vectors. We should not need this once mkvparser
166// adds the same functionality.
167const mkvparser::CuePoint::TrackPosition *MatroskaExtractor::TrackInfo::find(
168        long long timeNs) const {
169    ALOGV("mCuePoints.size %zu", mCuePoints.size());
170    if (mCuePoints.empty()) {
171        return NULL;
172    }
173
174    const mkvparser::CuePoint* cp = mCuePoints.itemAt(0);
175    const mkvparser::Track* track = getTrack();
176    if (timeNs <= cp->GetTime(mExtractor->mSegment)) {
177        return cp->Find(track);
178    }
179
180    // Binary searches through relevant cues; assumes cues are ordered by timecode.
181    // If we do detect out-of-order cues, return NULL.
182    size_t lo = 0;
183    size_t hi = mCuePoints.size();
184    while (lo < hi) {
185        const size_t mid = lo + (hi - lo) / 2;
186        const mkvparser::CuePoint* const midCp = mCuePoints.itemAt(mid);
187        const long long cueTimeNs = midCp->GetTime(mExtractor->mSegment);
188        if (cueTimeNs <= timeNs) {
189            lo = mid + 1;
190        } else {
191            hi = mid;
192        }
193    }
194
195    if (lo == 0) {
196        return NULL;
197    }
198
199    cp = mCuePoints.itemAt(lo - 1);
200    if (cp->GetTime(mExtractor->mSegment) > timeNs) {
201        return NULL;
202    }
203
204    return cp->Find(track);
205}
206
207MatroskaSource::MatroskaSource(
208        const sp<MatroskaExtractor> &extractor, size_t index)
209    : mExtractor(extractor),
210      mTrackIndex(index),
211      mType(OTHER),
212      mIsAudio(false),
213      mBlockIter(mExtractor.get(),
214                 mExtractor->mTracks.itemAt(index).mTrackNum,
215                 index),
216      mNALSizeLen(0) {
217    sp<MetaData> meta = mExtractor->mTracks.itemAt(index).mMeta;
218
219    const char *mime;
220    CHECK(meta->findCString(kKeyMIMEType, &mime));
221
222    mIsAudio = !strncasecmp("audio/", mime, 6);
223
224    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
225        mType = AVC;
226
227        uint32_t dummy;
228        const uint8_t *avcc;
229        size_t avccSize;
230        CHECK(meta->findData(
231                    kKeyAVCC, &dummy, (const void **)&avcc, &avccSize));
232
233        CHECK_GE(avccSize, 5u);
234
235        mNALSizeLen = 1 + (avcc[4] & 3);
236        ALOGV("mNALSizeLen = %zu", mNALSizeLen);
237    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
238        mType = AAC;
239    }
240}
241
242MatroskaSource::~MatroskaSource() {
243    clearPendingFrames();
244}
245
246status_t MatroskaSource::start(MetaData * /* params */) {
247    mBlockIter.reset();
248
249    return OK;
250}
251
252status_t MatroskaSource::stop() {
253    clearPendingFrames();
254
255    return OK;
256}
257
258sp<MetaData> MatroskaSource::getFormat() {
259    return mExtractor->mTracks.itemAt(mTrackIndex).mMeta;
260}
261
262////////////////////////////////////////////////////////////////////////////////
263
264BlockIterator::BlockIterator(
265        MatroskaExtractor *extractor, unsigned long trackNum, unsigned long index)
266    : mExtractor(extractor),
267      mTrackNum(trackNum),
268      mIndex(index),
269      mCluster(NULL),
270      mBlockEntry(NULL),
271      mBlockEntryIndex(0) {
272    reset();
273}
274
275bool BlockIterator::eos() const {
276    return mCluster == NULL || mCluster->EOS();
277}
278
279void BlockIterator::advance() {
280    Mutex::Autolock autoLock(mExtractor->mLock);
281    advance_l();
282}
283
284void BlockIterator::advance_l() {
285    for (;;) {
286        long res = mCluster->GetEntry(mBlockEntryIndex, mBlockEntry);
287        ALOGV("GetEntry returned %ld", res);
288
289        long long pos;
290        long len;
291        if (res < 0) {
292            // Need to parse this cluster some more
293
294            CHECK_EQ(res, mkvparser::E_BUFFER_NOT_FULL);
295
296            res = mCluster->Parse(pos, len);
297            ALOGV("Parse returned %ld", res);
298
299            if (res < 0) {
300                // I/O error
301
302                ALOGE("Cluster::Parse returned result %ld", res);
303
304                mCluster = NULL;
305                break;
306            }
307
308            continue;
309        } else if (res == 0) {
310            // We're done with this cluster
311
312            const mkvparser::Cluster *nextCluster;
313            res = mExtractor->mSegment->ParseNext(
314                    mCluster, nextCluster, pos, len);
315            ALOGV("ParseNext returned %ld", res);
316
317            if (res != 0) {
318                // EOF or error
319
320                mCluster = NULL;
321                break;
322            }
323
324            CHECK_EQ(res, 0);
325            CHECK(nextCluster != NULL);
326            CHECK(!nextCluster->EOS());
327
328            mCluster = nextCluster;
329
330            res = mCluster->Parse(pos, len);
331            ALOGV("Parse (2) returned %ld", res);
332            CHECK_GE(res, 0);
333
334            mBlockEntryIndex = 0;
335            continue;
336        }
337
338        CHECK(mBlockEntry != NULL);
339        CHECK(mBlockEntry->GetBlock() != NULL);
340        ++mBlockEntryIndex;
341
342        if (mBlockEntry->GetBlock()->GetTrackNumber() == mTrackNum) {
343            break;
344        }
345    }
346}
347
348void BlockIterator::reset() {
349    Mutex::Autolock autoLock(mExtractor->mLock);
350
351    mCluster = mExtractor->mSegment->GetFirst();
352    mBlockEntry = NULL;
353    mBlockEntryIndex = 0;
354
355    do {
356        advance_l();
357    } while (!eos() && block()->GetTrackNumber() != mTrackNum);
358}
359
360void BlockIterator::seek(
361        int64_t seekTimeUs, bool isAudio,
362        int64_t *actualFrameTimeUs) {
363    Mutex::Autolock autoLock(mExtractor->mLock);
364
365    *actualFrameTimeUs = -1ll;
366
367    const int64_t seekTimeNs = seekTimeUs * 1000ll - mExtractor->mSeekPreRollNs;
368
369    mkvparser::Segment* const pSegment = mExtractor->mSegment;
370
371    // Special case the 0 seek to avoid loading Cues when the application
372    // extraneously seeks to 0 before playing.
373    if (seekTimeNs <= 0) {
374        ALOGV("Seek to beginning: %" PRId64, seekTimeUs);
375        mCluster = pSegment->GetFirst();
376        mBlockEntryIndex = 0;
377        do {
378            advance_l();
379        } while (!eos() && block()->GetTrackNumber() != mTrackNum);
380        return;
381    }
382
383    ALOGV("Seeking to: %" PRId64, seekTimeUs);
384
385    // If the Cues have not been located then find them.
386    const mkvparser::Cues* pCues = pSegment->GetCues();
387    const mkvparser::SeekHead* pSH = pSegment->GetSeekHead();
388    if (!pCues && pSH) {
389        const size_t count = pSH->GetCount();
390        const mkvparser::SeekHead::Entry* pEntry;
391        ALOGV("No Cues yet");
392
393        for (size_t index = 0; index < count; index++) {
394            pEntry = pSH->GetEntry(index);
395
396            if (pEntry->id == 0x0C53BB6B) { // Cues ID
397                long len; long long pos;
398                pSegment->ParseCues(pEntry->pos, pos, len);
399                pCues = pSegment->GetCues();
400                ALOGV("Cues found");
401                break;
402            }
403        }
404
405        if (!pCues) {
406            ALOGE("No Cues in file");
407            return;
408        }
409    }
410    else if (!pSH) {
411        ALOGE("No SeekHead");
412        return;
413    }
414
415    const mkvparser::CuePoint* pCP;
416    mkvparser::Tracks const *pTracks = pSegment->GetTracks();
417    while (!pCues->DoneParsing()) {
418        pCues->LoadCuePoint();
419        pCP = pCues->GetLast();
420        CHECK(pCP);
421
422        size_t trackCount = mExtractor->mTracks.size();
423        for (size_t index = 0; index < trackCount; ++index) {
424            MatroskaExtractor::TrackInfo& track = mExtractor->mTracks.editItemAt(index);
425            const mkvparser::Track *pTrack = pTracks->GetTrackByNumber(track.mTrackNum);
426            if (pTrack && pTrack->GetType() == 1 && pCP->Find(pTrack)) { // VIDEO_TRACK
427                track.mCuePoints.push_back(pCP);
428            }
429        }
430
431        if (pCP->GetTime(pSegment) >= seekTimeNs) {
432            ALOGV("Parsed past relevant Cue");
433            break;
434        }
435    }
436
437    const mkvparser::CuePoint::TrackPosition *pTP = NULL;
438    const mkvparser::Track *thisTrack = pTracks->GetTrackByNumber(mTrackNum);
439    if (thisTrack->GetType() == 1) { // video
440        MatroskaExtractor::TrackInfo& track = mExtractor->mTracks.editItemAt(mIndex);
441        pTP = track.find(seekTimeNs);
442    } else {
443        // The Cue index is built around video keyframes
444        unsigned long int trackCount = pTracks->GetTracksCount();
445        for (size_t index = 0; index < trackCount; ++index) {
446            const mkvparser::Track *pTrack = pTracks->GetTrackByIndex(index);
447            if (pTrack && pTrack->GetType() == 1 && pCues->Find(seekTimeNs, pTrack, pCP, pTP)) {
448                ALOGV("Video track located at %zu", index);
449                break;
450            }
451        }
452    }
453
454
455    // Always *search* based on the video track, but finalize based on mTrackNum
456    if (!pTP) {
457        ALOGE("Did not locate the video track for seeking");
458        return;
459    }
460
461    mCluster = pSegment->FindOrPreloadCluster(pTP->m_pos);
462
463    CHECK(mCluster);
464    CHECK(!mCluster->EOS());
465
466    // mBlockEntryIndex starts at 0 but m_block starts at 1
467    CHECK_GT(pTP->m_block, 0);
468    mBlockEntryIndex = pTP->m_block - 1;
469
470    for (;;) {
471        advance_l();
472
473        if (eos()) break;
474
475        if (isAudio || block()->IsKey()) {
476            // Accept the first key frame
477            int64_t frameTimeUs = (block()->GetTime(mCluster) + 500LL) / 1000LL;
478            if (thisTrack->GetType() == 1 || frameTimeUs >= seekTimeUs) {
479                *actualFrameTimeUs = frameTimeUs;
480                ALOGV("Requested seek point: %" PRId64 " actual: %" PRId64,
481                      seekTimeUs, *actualFrameTimeUs);
482                break;
483            }
484        }
485    }
486}
487
488const mkvparser::Block *BlockIterator::block() const {
489    CHECK(!eos());
490
491    return mBlockEntry->GetBlock();
492}
493
494int64_t BlockIterator::blockTimeUs() const {
495    return (mBlockEntry->GetBlock()->GetTime(mCluster) + 500ll) / 1000ll;
496}
497
498////////////////////////////////////////////////////////////////////////////////
499
500static unsigned U24_AT(const uint8_t *ptr) {
501    return ptr[0] << 16 | ptr[1] << 8 | ptr[2];
502}
503
504void MatroskaSource::clearPendingFrames() {
505    while (!mPendingFrames.empty()) {
506        MediaBuffer *frame = *mPendingFrames.begin();
507        mPendingFrames.erase(mPendingFrames.begin());
508
509        frame->release();
510        frame = NULL;
511    }
512}
513
514status_t MatroskaSource::readBlock() {
515    CHECK(mPendingFrames.empty());
516
517    if (mBlockIter.eos()) {
518        return ERROR_END_OF_STREAM;
519    }
520
521    const mkvparser::Block *block = mBlockIter.block();
522
523    int64_t timeUs = mBlockIter.blockTimeUs();
524
525    for (int i = 0; i < block->GetFrameCount(); ++i) {
526        const mkvparser::Block::Frame &frame = block->GetFrame(i);
527
528        MediaBuffer *mbuf = new MediaBuffer(frame.len);
529        mbuf->meta_data()->setInt64(kKeyTime, timeUs);
530        mbuf->meta_data()->setInt32(kKeyIsSyncFrame, block->IsKey());
531
532        long n = frame.Read(mExtractor->mReader, (unsigned char *)mbuf->data());
533        if (n != 0) {
534            mPendingFrames.clear();
535
536            mBlockIter.advance();
537            return ERROR_IO;
538        }
539
540        mPendingFrames.push_back(mbuf);
541    }
542
543    mBlockIter.advance();
544
545    return OK;
546}
547
548status_t MatroskaSource::read(
549        MediaBuffer **out, const ReadOptions *options) {
550    *out = NULL;
551
552    int64_t targetSampleTimeUs = -1ll;
553
554    int64_t seekTimeUs;
555    ReadOptions::SeekMode mode;
556    if (options && options->getSeekTo(&seekTimeUs, &mode)
557            && !mExtractor->isLiveStreaming()) {
558        clearPendingFrames();
559
560        // The audio we want is located by using the Cues to seek the video
561        // stream to find the target Cluster then iterating to finalize for
562        // audio.
563        int64_t actualFrameTimeUs;
564        mBlockIter.seek(seekTimeUs, mIsAudio, &actualFrameTimeUs);
565
566        if (mode == ReadOptions::SEEK_CLOSEST) {
567            targetSampleTimeUs = actualFrameTimeUs;
568        }
569    }
570
571    while (mPendingFrames.empty()) {
572        status_t err = readBlock();
573
574        if (err != OK) {
575            clearPendingFrames();
576
577            return err;
578        }
579    }
580
581    MediaBuffer *frame = *mPendingFrames.begin();
582    mPendingFrames.erase(mPendingFrames.begin());
583
584    if (mType != AVC) {
585        if (targetSampleTimeUs >= 0ll) {
586            frame->meta_data()->setInt64(
587                    kKeyTargetTime, targetSampleTimeUs);
588        }
589
590        *out = frame;
591
592        return OK;
593    }
594
595    // Each input frame contains one or more NAL fragments, each fragment
596    // is prefixed by mNALSizeLen bytes giving the fragment length,
597    // followed by a corresponding number of bytes containing the fragment.
598    // We output all these fragments into a single large buffer separated
599    // by startcodes (0x00 0x00 0x00 0x01).
600
601    const uint8_t *srcPtr =
602        (const uint8_t *)frame->data() + frame->range_offset();
603
604    size_t srcSize = frame->range_length();
605
606    size_t dstSize = 0;
607    MediaBuffer *buffer = NULL;
608    uint8_t *dstPtr = NULL;
609
610    for (int32_t pass = 0; pass < 2; ++pass) {
611        size_t srcOffset = 0;
612        size_t dstOffset = 0;
613        while (srcOffset + mNALSizeLen <= srcSize) {
614            size_t NALsize;
615            switch (mNALSizeLen) {
616                case 1: NALsize = srcPtr[srcOffset]; break;
617                case 2: NALsize = U16_AT(srcPtr + srcOffset); break;
618                case 3: NALsize = U24_AT(srcPtr + srcOffset); break;
619                case 4: NALsize = U32_AT(srcPtr + srcOffset); break;
620                default:
621                    TRESPASS();
622            }
623
624            if (srcOffset + mNALSizeLen + NALsize <= srcOffset + mNALSizeLen) {
625                frame->release();
626                frame = NULL;
627
628                return ERROR_MALFORMED;
629            } else if (srcOffset + mNALSizeLen + NALsize > srcSize) {
630                break;
631            }
632
633            if (pass == 1) {
634                memcpy(&dstPtr[dstOffset], "\x00\x00\x00\x01", 4);
635
636                memcpy(&dstPtr[dstOffset + 4],
637                       &srcPtr[srcOffset + mNALSizeLen],
638                       NALsize);
639            }
640
641            dstOffset += 4;  // 0x00 00 00 01
642            dstOffset += NALsize;
643
644            srcOffset += mNALSizeLen + NALsize;
645        }
646
647        if (srcOffset < srcSize) {
648            // There were trailing bytes or not enough data to complete
649            // a fragment.
650
651            frame->release();
652            frame = NULL;
653
654            return ERROR_MALFORMED;
655        }
656
657        if (pass == 0) {
658            dstSize = dstOffset;
659
660            buffer = new MediaBuffer(dstSize);
661
662            int64_t timeUs;
663            CHECK(frame->meta_data()->findInt64(kKeyTime, &timeUs));
664            int32_t isSync;
665            CHECK(frame->meta_data()->findInt32(kKeyIsSyncFrame, &isSync));
666
667            buffer->meta_data()->setInt64(kKeyTime, timeUs);
668            buffer->meta_data()->setInt32(kKeyIsSyncFrame, isSync);
669
670            dstPtr = (uint8_t *)buffer->data();
671        }
672    }
673
674    frame->release();
675    frame = NULL;
676
677    if (targetSampleTimeUs >= 0ll) {
678        buffer->meta_data()->setInt64(
679                kKeyTargetTime, targetSampleTimeUs);
680    }
681
682    *out = buffer;
683
684    return OK;
685}
686
687////////////////////////////////////////////////////////////////////////////////
688
689MatroskaExtractor::MatroskaExtractor(const sp<DataSource> &source)
690    : mDataSource(source),
691      mReader(new DataSourceReader(mDataSource)),
692      mSegment(NULL),
693      mExtractedThumbnails(false),
694      mIsWebm(false),
695      mSeekPreRollNs(0) {
696    off64_t size;
697    mIsLiveStreaming =
698        (mDataSource->flags()
699            & (DataSource::kWantsPrefetching
700                | DataSource::kIsCachingDataSource))
701        && mDataSource->getSize(&size) != OK;
702
703    mkvparser::EBMLHeader ebmlHeader;
704    long long pos;
705    if (ebmlHeader.Parse(mReader, pos) < 0) {
706        return;
707    }
708
709    if (ebmlHeader.m_docType && !strcmp("webm", ebmlHeader.m_docType)) {
710        mIsWebm = true;
711    }
712
713    long long ret =
714        mkvparser::Segment::CreateInstance(mReader, pos, mSegment);
715
716    if (ret) {
717        CHECK(mSegment == NULL);
718        return;
719    }
720
721    // from mkvparser::Segment::Load(), but stop at first cluster
722    ret = mSegment->ParseHeaders();
723    if (ret == 0) {
724        long len;
725        ret = mSegment->LoadCluster(pos, len);
726        if (ret >= 1) {
727            // no more clusters
728            ret = 0;
729        }
730    } else if (ret > 0) {
731        ret = mkvparser::E_BUFFER_NOT_FULL;
732    }
733
734    if (ret < 0) {
735        ALOGW("Corrupt %s source: %s", mIsWebm ? "webm" : "matroska",
736                uriDebugString(mDataSource->getUri()).c_str());
737        delete mSegment;
738        mSegment = NULL;
739        return;
740    }
741
742#if 0
743    const mkvparser::SegmentInfo *info = mSegment->GetInfo();
744    ALOGI("muxing app: %s, writing app: %s",
745         info->GetMuxingAppAsUTF8(),
746         info->GetWritingAppAsUTF8());
747#endif
748
749    addTracks();
750}
751
752MatroskaExtractor::~MatroskaExtractor() {
753    delete mSegment;
754    mSegment = NULL;
755
756    delete mReader;
757    mReader = NULL;
758}
759
760size_t MatroskaExtractor::countTracks() {
761    return mTracks.size();
762}
763
764sp<IMediaSource> MatroskaExtractor::getTrack(size_t index) {
765    if (index >= mTracks.size()) {
766        return NULL;
767    }
768
769    return new MatroskaSource(this, index);
770}
771
772sp<MetaData> MatroskaExtractor::getTrackMetaData(
773        size_t index, uint32_t flags) {
774    if (index >= mTracks.size()) {
775        return NULL;
776    }
777
778    if ((flags & kIncludeExtensiveMetaData) && !mExtractedThumbnails
779            && !isLiveStreaming()) {
780        findThumbnails();
781        mExtractedThumbnails = true;
782    }
783
784    return mTracks.itemAt(index).mMeta;
785}
786
787bool MatroskaExtractor::isLiveStreaming() const {
788    return mIsLiveStreaming;
789}
790
791static int bytesForSize(size_t size) {
792    // use at most 28 bits (4 times 7)
793    CHECK(size <= 0xfffffff);
794
795    if (size > 0x1fffff) {
796        return 4;
797    } else if (size > 0x3fff) {
798        return 3;
799    } else if (size > 0x7f) {
800        return 2;
801    }
802    return 1;
803}
804
805static void storeSize(uint8_t *data, size_t &idx, size_t size) {
806    int numBytes = bytesForSize(size);
807    idx += numBytes;
808
809    data += idx;
810    size_t next = 0;
811    while (numBytes--) {
812        *--data = (size & 0x7f) | next;
813        size >>= 7;
814        next = 0x80;
815    }
816}
817
818static void addESDSFromCodecPrivate(
819        const sp<MetaData> &meta,
820        bool isAudio, const void *priv, size_t privSize) {
821
822    int privSizeBytesRequired = bytesForSize(privSize);
823    int esdsSize2 = 14 + privSizeBytesRequired + privSize;
824    int esdsSize2BytesRequired = bytesForSize(esdsSize2);
825    int esdsSize1 = 4 + esdsSize2BytesRequired + esdsSize2;
826    int esdsSize1BytesRequired = bytesForSize(esdsSize1);
827    size_t esdsSize = 1 + esdsSize1BytesRequired + esdsSize1;
828    uint8_t *esds = new uint8_t[esdsSize];
829
830    size_t idx = 0;
831    esds[idx++] = 0x03;
832    storeSize(esds, idx, esdsSize1);
833    esds[idx++] = 0x00; // ES_ID
834    esds[idx++] = 0x00; // ES_ID
835    esds[idx++] = 0x00; // streamDependenceFlag, URL_Flag, OCRstreamFlag
836    esds[idx++] = 0x04;
837    storeSize(esds, idx, esdsSize2);
838    esds[idx++] = isAudio ? 0x40   // Audio ISO/IEC 14496-3
839                          : 0x20;  // Visual ISO/IEC 14496-2
840    for (int i = 0; i < 12; i++) {
841        esds[idx++] = 0x00;
842    }
843    esds[idx++] = 0x05;
844    storeSize(esds, idx, privSize);
845    memcpy(esds + idx, priv, privSize);
846
847    meta->setData(kKeyESDS, 0, esds, esdsSize);
848
849    delete[] esds;
850    esds = NULL;
851}
852
853status_t addVorbisCodecInfo(
854        const sp<MetaData> &meta,
855        const void *_codecPrivate, size_t codecPrivateSize) {
856    // hexdump(_codecPrivate, codecPrivateSize);
857
858    if (codecPrivateSize < 1) {
859        return ERROR_MALFORMED;
860    }
861
862    const uint8_t *codecPrivate = (const uint8_t *)_codecPrivate;
863
864    if (codecPrivate[0] != 0x02) {
865        return ERROR_MALFORMED;
866    }
867
868    // codecInfo starts with two lengths, len1 and len2, that are
869    // "Xiph-style-lacing encoded"...
870
871    size_t offset = 1;
872    size_t len1 = 0;
873    while (offset < codecPrivateSize && codecPrivate[offset] == 0xff) {
874        if (len1 > (SIZE_MAX - 0xff)) {
875            return ERROR_MALFORMED; // would overflow
876        }
877        len1 += 0xff;
878        ++offset;
879    }
880    if (offset >= codecPrivateSize) {
881        return ERROR_MALFORMED;
882    }
883    if (len1 > (SIZE_MAX - codecPrivate[offset])) {
884        return ERROR_MALFORMED; // would overflow
885    }
886    len1 += codecPrivate[offset++];
887
888    size_t len2 = 0;
889    while (offset < codecPrivateSize && codecPrivate[offset] == 0xff) {
890        if (len2 > (SIZE_MAX - 0xff)) {
891            return ERROR_MALFORMED; // would overflow
892        }
893        len2 += 0xff;
894        ++offset;
895    }
896    if (offset >= codecPrivateSize) {
897        return ERROR_MALFORMED;
898    }
899    if (len2 > (SIZE_MAX - codecPrivate[offset])) {
900        return ERROR_MALFORMED; // would overflow
901    }
902    len2 += codecPrivate[offset++];
903
904    if (len1 > SIZE_MAX - len2 || offset > SIZE_MAX - (len1 + len2) ||
905            codecPrivateSize < offset + len1 + len2) {
906        return ERROR_MALFORMED;
907    }
908
909    if (codecPrivate[offset] != 0x01) {
910        return ERROR_MALFORMED;
911    }
912    meta->setData(kKeyVorbisInfo, 0, &codecPrivate[offset], len1);
913
914    offset += len1;
915    if (codecPrivate[offset] != 0x03) {
916        return ERROR_MALFORMED;
917    }
918
919    offset += len2;
920    if (codecPrivate[offset] != 0x05) {
921        return ERROR_MALFORMED;
922    }
923
924    meta->setData(
925            kKeyVorbisBooks, 0, &codecPrivate[offset],
926            codecPrivateSize - offset);
927
928    return OK;
929}
930
931void MatroskaExtractor::addTracks() {
932    const mkvparser::Tracks *tracks = mSegment->GetTracks();
933
934    for (size_t index = 0; index < tracks->GetTracksCount(); ++index) {
935        const mkvparser::Track *track = tracks->GetTrackByIndex(index);
936
937        if (track == NULL) {
938            // Apparently this is currently valid (if unexpected) behaviour
939            // of the mkv parser lib.
940            continue;
941        }
942
943        const char *const codecID = track->GetCodecId();
944        ALOGV("codec id = %s", codecID);
945        ALOGV("codec name = %s", track->GetCodecNameAsUTF8());
946
947        if (codecID == NULL) {
948            ALOGW("unknown codecID is not supported.");
949            continue;
950        }
951
952        size_t codecPrivateSize;
953        const unsigned char *codecPrivate =
954            track->GetCodecPrivate(codecPrivateSize);
955
956        enum { VIDEO_TRACK = 1, AUDIO_TRACK = 2 };
957
958        sp<MetaData> meta = new MetaData;
959
960        status_t err = OK;
961
962        switch (track->GetType()) {
963            case VIDEO_TRACK:
964            {
965                const mkvparser::VideoTrack *vtrack =
966                    static_cast<const mkvparser::VideoTrack *>(track);
967
968                if (!strcmp("V_MPEG4/ISO/AVC", codecID)) {
969                    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
970                    meta->setData(kKeyAVCC, 0, codecPrivate, codecPrivateSize);
971                } else if (!strcmp("V_MPEG4/ISO/ASP", codecID)) {
972                    if (codecPrivateSize > 0) {
973                        meta->setCString(
974                                kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
975                        addESDSFromCodecPrivate(
976                                meta, false, codecPrivate, codecPrivateSize);
977                    } else {
978                        ALOGW("%s is detected, but does not have configuration.",
979                                codecID);
980                        continue;
981                    }
982                } else if (!strcmp("V_VP8", codecID)) {
983                    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VP8);
984                } else if (!strcmp("V_VP9", codecID)) {
985                    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VP9);
986                } else {
987                    ALOGW("%s is not supported.", codecID);
988                    continue;
989                }
990
991                meta->setInt32(kKeyWidth, vtrack->GetWidth());
992                meta->setInt32(kKeyHeight, vtrack->GetHeight());
993                break;
994            }
995
996            case AUDIO_TRACK:
997            {
998                const mkvparser::AudioTrack *atrack =
999                    static_cast<const mkvparser::AudioTrack *>(track);
1000
1001                if (!strcmp("A_AAC", codecID)) {
1002                    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
1003                    CHECK(codecPrivateSize >= 2);
1004
1005                    addESDSFromCodecPrivate(
1006                            meta, true, codecPrivate, codecPrivateSize);
1007                } else if (!strcmp("A_VORBIS", codecID)) {
1008                    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS);
1009
1010                    err = addVorbisCodecInfo(
1011                            meta, codecPrivate, codecPrivateSize);
1012                } else if (!strcmp("A_OPUS", codecID)) {
1013                    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_OPUS);
1014                    meta->setData(kKeyOpusHeader, 0, codecPrivate, codecPrivateSize);
1015                    meta->setInt64(kKeyOpusCodecDelay, track->GetCodecDelay());
1016                    meta->setInt64(kKeyOpusSeekPreRoll, track->GetSeekPreRoll());
1017                    mSeekPreRollNs = track->GetSeekPreRoll();
1018                } else if (!strcmp("A_MPEG/L3", codecID)) {
1019                    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
1020                } else {
1021                    ALOGW("%s is not supported.", codecID);
1022                    continue;
1023                }
1024
1025                meta->setInt32(kKeySampleRate, atrack->GetSamplingRate());
1026                meta->setInt32(kKeyChannelCount, atrack->GetChannels());
1027                break;
1028            }
1029
1030            default:
1031                continue;
1032        }
1033
1034        if (err != OK) {
1035            ALOGE("skipping track, codec specific data was malformed.");
1036            continue;
1037        }
1038
1039        long long durationNs = mSegment->GetDuration();
1040        meta->setInt64(kKeyDuration, (durationNs + 500) / 1000);
1041
1042        mTracks.push();
1043        TrackInfo *trackInfo = &mTracks.editItemAt(mTracks.size() - 1);
1044        trackInfo->mTrackNum = track->GetNumber();
1045        trackInfo->mMeta = meta;
1046        trackInfo->mExtractor = this;
1047    }
1048}
1049
1050void MatroskaExtractor::findThumbnails() {
1051    for (size_t i = 0; i < mTracks.size(); ++i) {
1052        TrackInfo *info = &mTracks.editItemAt(i);
1053
1054        const char *mime;
1055        CHECK(info->mMeta->findCString(kKeyMIMEType, &mime));
1056
1057        if (strncasecmp(mime, "video/", 6)) {
1058            continue;
1059        }
1060
1061        BlockIterator iter(this, info->mTrackNum, i);
1062        int32_t j = 0;
1063        int64_t thumbnailTimeUs = 0;
1064        size_t maxBlockSize = 0;
1065        while (!iter.eos() && j < 20) {
1066            if (iter.block()->IsKey()) {
1067                ++j;
1068
1069                size_t blockSize = 0;
1070                for (int k = 0; k < iter.block()->GetFrameCount(); ++k) {
1071                    blockSize += iter.block()->GetFrame(k).len;
1072                }
1073
1074                if (blockSize > maxBlockSize) {
1075                    maxBlockSize = blockSize;
1076                    thumbnailTimeUs = iter.blockTimeUs();
1077                }
1078            }
1079            iter.advance();
1080        }
1081        info->mMeta->setInt64(kKeyThumbnailTime, thumbnailTimeUs);
1082    }
1083}
1084
1085sp<MetaData> MatroskaExtractor::getMetaData() {
1086    sp<MetaData> meta = new MetaData;
1087
1088    meta->setCString(
1089            kKeyMIMEType,
1090            mIsWebm ? "video/webm" : MEDIA_MIMETYPE_CONTAINER_MATROSKA);
1091
1092    return meta;
1093}
1094
1095uint32_t MatroskaExtractor::flags() const {
1096    uint32_t x = CAN_PAUSE;
1097    if (!isLiveStreaming()) {
1098        x |= CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK;
1099    }
1100
1101    return x;
1102}
1103
1104bool SniffMatroska(
1105        const sp<DataSource> &source, String8 *mimeType, float *confidence,
1106        sp<AMessage> *) {
1107    DataSourceReader reader(source);
1108    mkvparser::EBMLHeader ebmlHeader;
1109    long long pos;
1110    if (ebmlHeader.Parse(&reader, pos) < 0) {
1111        return false;
1112    }
1113
1114    mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_MATROSKA);
1115    *confidence = 0.6;
1116
1117    return true;
1118}
1119
1120}  // namespace android
1121