MatroskaExtractor.cpp revision ae0dd12d85bdf93a20be49e0bbc9b97a2dd3c3e7
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            mbuf->release();
538            return ERROR_IO;
539        }
540
541        mPendingFrames.push_back(mbuf);
542    }
543
544    mBlockIter.advance();
545
546    return OK;
547}
548
549status_t MatroskaSource::read(
550        MediaBuffer **out, const ReadOptions *options) {
551    *out = NULL;
552
553    int64_t targetSampleTimeUs = -1ll;
554
555    int64_t seekTimeUs;
556    ReadOptions::SeekMode mode;
557    if (options && options->getSeekTo(&seekTimeUs, &mode)
558            && !mExtractor->isLiveStreaming()) {
559        clearPendingFrames();
560
561        // The audio we want is located by using the Cues to seek the video
562        // stream to find the target Cluster then iterating to finalize for
563        // audio.
564        int64_t actualFrameTimeUs;
565        mBlockIter.seek(seekTimeUs, mIsAudio, &actualFrameTimeUs);
566
567        if (mode == ReadOptions::SEEK_CLOSEST) {
568            targetSampleTimeUs = actualFrameTimeUs;
569        }
570    }
571
572    while (mPendingFrames.empty()) {
573        status_t err = readBlock();
574
575        if (err != OK) {
576            clearPendingFrames();
577
578            return err;
579        }
580    }
581
582    MediaBuffer *frame = *mPendingFrames.begin();
583    mPendingFrames.erase(mPendingFrames.begin());
584
585    if (mType != AVC) {
586        if (targetSampleTimeUs >= 0ll) {
587            frame->meta_data()->setInt64(
588                    kKeyTargetTime, targetSampleTimeUs);
589        }
590
591        *out = frame;
592
593        return OK;
594    }
595
596    // Each input frame contains one or more NAL fragments, each fragment
597    // is prefixed by mNALSizeLen bytes giving the fragment length,
598    // followed by a corresponding number of bytes containing the fragment.
599    // We output all these fragments into a single large buffer separated
600    // by startcodes (0x00 0x00 0x00 0x01).
601
602    const uint8_t *srcPtr =
603        (const uint8_t *)frame->data() + frame->range_offset();
604
605    size_t srcSize = frame->range_length();
606
607    size_t dstSize = 0;
608    MediaBuffer *buffer = NULL;
609    uint8_t *dstPtr = NULL;
610
611    for (int32_t pass = 0; pass < 2; ++pass) {
612        size_t srcOffset = 0;
613        size_t dstOffset = 0;
614        while (srcOffset + mNALSizeLen <= srcSize) {
615            size_t NALsize;
616            switch (mNALSizeLen) {
617                case 1: NALsize = srcPtr[srcOffset]; break;
618                case 2: NALsize = U16_AT(srcPtr + srcOffset); break;
619                case 3: NALsize = U24_AT(srcPtr + srcOffset); break;
620                case 4: NALsize = U32_AT(srcPtr + srcOffset); break;
621                default:
622                    TRESPASS();
623            }
624
625            if (srcOffset + mNALSizeLen + NALsize <= srcOffset + mNALSizeLen) {
626                frame->release();
627                frame = NULL;
628
629                return ERROR_MALFORMED;
630            } else if (srcOffset + mNALSizeLen + NALsize > srcSize) {
631                break;
632            }
633
634            if (pass == 1) {
635                memcpy(&dstPtr[dstOffset], "\x00\x00\x00\x01", 4);
636
637                if (frame != buffer) {
638                    memcpy(&dstPtr[dstOffset + 4],
639                           &srcPtr[srcOffset + mNALSizeLen],
640                           NALsize);
641                }
642            }
643
644            dstOffset += 4;  // 0x00 00 00 01
645            dstOffset += NALsize;
646
647            srcOffset += mNALSizeLen + NALsize;
648        }
649
650        if (srcOffset < srcSize) {
651            // There were trailing bytes or not enough data to complete
652            // a fragment.
653
654            frame->release();
655            frame = NULL;
656
657            return ERROR_MALFORMED;
658        }
659
660        if (pass == 0) {
661            dstSize = dstOffset;
662
663            if (dstSize == srcSize && mNALSizeLen == 4) {
664                // In this special case we can re-use the input buffer by substituting
665                // each 4-byte nal size with a 4-byte start code
666                buffer = frame;
667            } else {
668                buffer = new MediaBuffer(dstSize);
669            }
670
671            int64_t timeUs;
672            CHECK(frame->meta_data()->findInt64(kKeyTime, &timeUs));
673            int32_t isSync;
674            CHECK(frame->meta_data()->findInt32(kKeyIsSyncFrame, &isSync));
675
676            buffer->meta_data()->setInt64(kKeyTime, timeUs);
677            buffer->meta_data()->setInt32(kKeyIsSyncFrame, isSync);
678
679            dstPtr = (uint8_t *)buffer->data();
680        }
681    }
682
683    if (frame != buffer) {
684        frame->release();
685        frame = NULL;
686    }
687
688    if (targetSampleTimeUs >= 0ll) {
689        buffer->meta_data()->setInt64(
690                kKeyTargetTime, targetSampleTimeUs);
691    }
692
693    *out = buffer;
694
695    return OK;
696}
697
698////////////////////////////////////////////////////////////////////////////////
699
700MatroskaExtractor::MatroskaExtractor(const sp<DataSource> &source)
701    : mDataSource(source),
702      mReader(new DataSourceReader(mDataSource)),
703      mSegment(NULL),
704      mExtractedThumbnails(false),
705      mIsWebm(false),
706      mSeekPreRollNs(0) {
707    off64_t size;
708    mIsLiveStreaming =
709        (mDataSource->flags()
710            & (DataSource::kWantsPrefetching
711                | DataSource::kIsCachingDataSource))
712        && mDataSource->getSize(&size) != OK;
713
714    mkvparser::EBMLHeader ebmlHeader;
715    long long pos;
716    if (ebmlHeader.Parse(mReader, pos) < 0) {
717        return;
718    }
719
720    if (ebmlHeader.m_docType && !strcmp("webm", ebmlHeader.m_docType)) {
721        mIsWebm = true;
722    }
723
724    long long ret =
725        mkvparser::Segment::CreateInstance(mReader, pos, mSegment);
726
727    if (ret) {
728        CHECK(mSegment == NULL);
729        return;
730    }
731
732    // from mkvparser::Segment::Load(), but stop at first cluster
733    ret = mSegment->ParseHeaders();
734    if (ret == 0) {
735        long len;
736        ret = mSegment->LoadCluster(pos, len);
737        if (ret >= 1) {
738            // no more clusters
739            ret = 0;
740        }
741    } else if (ret > 0) {
742        ret = mkvparser::E_BUFFER_NOT_FULL;
743    }
744
745    if (ret < 0) {
746        ALOGW("Corrupt %s source: %s", mIsWebm ? "webm" : "matroska",
747                uriDebugString(mDataSource->getUri()).c_str());
748        delete mSegment;
749        mSegment = NULL;
750        return;
751    }
752
753#if 0
754    const mkvparser::SegmentInfo *info = mSegment->GetInfo();
755    ALOGI("muxing app: %s, writing app: %s",
756         info->GetMuxingAppAsUTF8(),
757         info->GetWritingAppAsUTF8());
758#endif
759
760    addTracks();
761}
762
763MatroskaExtractor::~MatroskaExtractor() {
764    delete mSegment;
765    mSegment = NULL;
766
767    delete mReader;
768    mReader = NULL;
769}
770
771size_t MatroskaExtractor::countTracks() {
772    return mTracks.size();
773}
774
775sp<IMediaSource> MatroskaExtractor::getTrack(size_t index) {
776    if (index >= mTracks.size()) {
777        return NULL;
778    }
779
780    return new MatroskaSource(this, index);
781}
782
783sp<MetaData> MatroskaExtractor::getTrackMetaData(
784        size_t index, uint32_t flags) {
785    if (index >= mTracks.size()) {
786        return NULL;
787    }
788
789    if ((flags & kIncludeExtensiveMetaData) && !mExtractedThumbnails
790            && !isLiveStreaming()) {
791        findThumbnails();
792        mExtractedThumbnails = true;
793    }
794
795    return mTracks.itemAt(index).mMeta;
796}
797
798bool MatroskaExtractor::isLiveStreaming() const {
799    return mIsLiveStreaming;
800}
801
802static int bytesForSize(size_t size) {
803    // use at most 28 bits (4 times 7)
804    CHECK(size <= 0xfffffff);
805
806    if (size > 0x1fffff) {
807        return 4;
808    } else if (size > 0x3fff) {
809        return 3;
810    } else if (size > 0x7f) {
811        return 2;
812    }
813    return 1;
814}
815
816static void storeSize(uint8_t *data, size_t &idx, size_t size) {
817    int numBytes = bytesForSize(size);
818    idx += numBytes;
819
820    data += idx;
821    size_t next = 0;
822    while (numBytes--) {
823        *--data = (size & 0x7f) | next;
824        size >>= 7;
825        next = 0x80;
826    }
827}
828
829static void addESDSFromCodecPrivate(
830        const sp<MetaData> &meta,
831        bool isAudio, const void *priv, size_t privSize) {
832
833    int privSizeBytesRequired = bytesForSize(privSize);
834    int esdsSize2 = 14 + privSizeBytesRequired + privSize;
835    int esdsSize2BytesRequired = bytesForSize(esdsSize2);
836    int esdsSize1 = 4 + esdsSize2BytesRequired + esdsSize2;
837    int esdsSize1BytesRequired = bytesForSize(esdsSize1);
838    size_t esdsSize = 1 + esdsSize1BytesRequired + esdsSize1;
839    uint8_t *esds = new uint8_t[esdsSize];
840
841    size_t idx = 0;
842    esds[idx++] = 0x03;
843    storeSize(esds, idx, esdsSize1);
844    esds[idx++] = 0x00; // ES_ID
845    esds[idx++] = 0x00; // ES_ID
846    esds[idx++] = 0x00; // streamDependenceFlag, URL_Flag, OCRstreamFlag
847    esds[idx++] = 0x04;
848    storeSize(esds, idx, esdsSize2);
849    esds[idx++] = isAudio ? 0x40   // Audio ISO/IEC 14496-3
850                          : 0x20;  // Visual ISO/IEC 14496-2
851    for (int i = 0; i < 12; i++) {
852        esds[idx++] = 0x00;
853    }
854    esds[idx++] = 0x05;
855    storeSize(esds, idx, privSize);
856    memcpy(esds + idx, priv, privSize);
857
858    meta->setData(kKeyESDS, 0, esds, esdsSize);
859
860    delete[] esds;
861    esds = NULL;
862}
863
864status_t addVorbisCodecInfo(
865        const sp<MetaData> &meta,
866        const void *_codecPrivate, size_t codecPrivateSize) {
867    // hexdump(_codecPrivate, codecPrivateSize);
868
869    if (codecPrivateSize < 1) {
870        return ERROR_MALFORMED;
871    }
872
873    const uint8_t *codecPrivate = (const uint8_t *)_codecPrivate;
874
875    if (codecPrivate[0] != 0x02) {
876        return ERROR_MALFORMED;
877    }
878
879    // codecInfo starts with two lengths, len1 and len2, that are
880    // "Xiph-style-lacing encoded"...
881
882    size_t offset = 1;
883    size_t len1 = 0;
884    while (offset < codecPrivateSize && codecPrivate[offset] == 0xff) {
885        if (len1 > (SIZE_MAX - 0xff)) {
886            return ERROR_MALFORMED; // would overflow
887        }
888        len1 += 0xff;
889        ++offset;
890    }
891    if (offset >= codecPrivateSize) {
892        return ERROR_MALFORMED;
893    }
894    if (len1 > (SIZE_MAX - codecPrivate[offset])) {
895        return ERROR_MALFORMED; // would overflow
896    }
897    len1 += codecPrivate[offset++];
898
899    size_t len2 = 0;
900    while (offset < codecPrivateSize && codecPrivate[offset] == 0xff) {
901        if (len2 > (SIZE_MAX - 0xff)) {
902            return ERROR_MALFORMED; // would overflow
903        }
904        len2 += 0xff;
905        ++offset;
906    }
907    if (offset >= codecPrivateSize) {
908        return ERROR_MALFORMED;
909    }
910    if (len2 > (SIZE_MAX - codecPrivate[offset])) {
911        return ERROR_MALFORMED; // would overflow
912    }
913    len2 += codecPrivate[offset++];
914
915    if (len1 > SIZE_MAX - len2 || offset > SIZE_MAX - (len1 + len2) ||
916            codecPrivateSize < offset + len1 + len2) {
917        return ERROR_MALFORMED;
918    }
919
920    if (codecPrivate[offset] != 0x01) {
921        return ERROR_MALFORMED;
922    }
923    meta->setData(kKeyVorbisInfo, 0, &codecPrivate[offset], len1);
924
925    offset += len1;
926    if (codecPrivate[offset] != 0x03) {
927        return ERROR_MALFORMED;
928    }
929
930    offset += len2;
931    if (codecPrivate[offset] != 0x05) {
932        return ERROR_MALFORMED;
933    }
934
935    meta->setData(
936            kKeyVorbisBooks, 0, &codecPrivate[offset],
937            codecPrivateSize - offset);
938
939    return OK;
940}
941
942void MatroskaExtractor::addTracks() {
943    const mkvparser::Tracks *tracks = mSegment->GetTracks();
944
945    for (size_t index = 0; index < tracks->GetTracksCount(); ++index) {
946        const mkvparser::Track *track = tracks->GetTrackByIndex(index);
947
948        if (track == NULL) {
949            // Apparently this is currently valid (if unexpected) behaviour
950            // of the mkv parser lib.
951            continue;
952        }
953
954        const char *const codecID = track->GetCodecId();
955        ALOGV("codec id = %s", codecID);
956        ALOGV("codec name = %s", track->GetCodecNameAsUTF8());
957
958        if (codecID == NULL) {
959            ALOGW("unknown codecID is not supported.");
960            continue;
961        }
962
963        size_t codecPrivateSize;
964        const unsigned char *codecPrivate =
965            track->GetCodecPrivate(codecPrivateSize);
966
967        enum { VIDEO_TRACK = 1, AUDIO_TRACK = 2 };
968
969        sp<MetaData> meta = new MetaData;
970
971        status_t err = OK;
972
973        switch (track->GetType()) {
974            case VIDEO_TRACK:
975            {
976                const mkvparser::VideoTrack *vtrack =
977                    static_cast<const mkvparser::VideoTrack *>(track);
978
979                if (!strcmp("V_MPEG4/ISO/AVC", codecID)) {
980                    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
981                    meta->setData(kKeyAVCC, 0, codecPrivate, codecPrivateSize);
982                } else if (!strcmp("V_MPEG4/ISO/ASP", codecID)) {
983                    if (codecPrivateSize > 0) {
984                        meta->setCString(
985                                kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
986                        addESDSFromCodecPrivate(
987                                meta, false, codecPrivate, codecPrivateSize);
988                    } else {
989                        ALOGW("%s is detected, but does not have configuration.",
990                                codecID);
991                        continue;
992                    }
993                } else if (!strcmp("V_VP8", codecID)) {
994                    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VP8);
995                } else if (!strcmp("V_VP9", codecID)) {
996                    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VP9);
997                } else {
998                    ALOGW("%s is not supported.", codecID);
999                    continue;
1000                }
1001
1002                meta->setInt32(kKeyWidth, vtrack->GetWidth());
1003                meta->setInt32(kKeyHeight, vtrack->GetHeight());
1004                break;
1005            }
1006
1007            case AUDIO_TRACK:
1008            {
1009                const mkvparser::AudioTrack *atrack =
1010                    static_cast<const mkvparser::AudioTrack *>(track);
1011
1012                if (!strcmp("A_AAC", codecID)) {
1013                    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
1014                    CHECK(codecPrivateSize >= 2);
1015
1016                    addESDSFromCodecPrivate(
1017                            meta, true, codecPrivate, codecPrivateSize);
1018                } else if (!strcmp("A_VORBIS", codecID)) {
1019                    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS);
1020
1021                    err = addVorbisCodecInfo(
1022                            meta, codecPrivate, codecPrivateSize);
1023                } else if (!strcmp("A_OPUS", codecID)) {
1024                    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_OPUS);
1025                    meta->setData(kKeyOpusHeader, 0, codecPrivate, codecPrivateSize);
1026                    meta->setInt64(kKeyOpusCodecDelay, track->GetCodecDelay());
1027                    meta->setInt64(kKeyOpusSeekPreRoll, track->GetSeekPreRoll());
1028                    mSeekPreRollNs = track->GetSeekPreRoll();
1029                } else if (!strcmp("A_MPEG/L3", codecID)) {
1030                    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
1031                } else {
1032                    ALOGW("%s is not supported.", codecID);
1033                    continue;
1034                }
1035
1036                meta->setInt32(kKeySampleRate, atrack->GetSamplingRate());
1037                meta->setInt32(kKeyChannelCount, atrack->GetChannels());
1038                break;
1039            }
1040
1041            default:
1042                continue;
1043        }
1044
1045        if (err != OK) {
1046            ALOGE("skipping track, codec specific data was malformed.");
1047            continue;
1048        }
1049
1050        long long durationNs = mSegment->GetDuration();
1051        meta->setInt64(kKeyDuration, (durationNs + 500) / 1000);
1052
1053        mTracks.push();
1054        TrackInfo *trackInfo = &mTracks.editItemAt(mTracks.size() - 1);
1055        trackInfo->mTrackNum = track->GetNumber();
1056        trackInfo->mMeta = meta;
1057        trackInfo->mExtractor = this;
1058    }
1059}
1060
1061void MatroskaExtractor::findThumbnails() {
1062    for (size_t i = 0; i < mTracks.size(); ++i) {
1063        TrackInfo *info = &mTracks.editItemAt(i);
1064
1065        const char *mime;
1066        CHECK(info->mMeta->findCString(kKeyMIMEType, &mime));
1067
1068        if (strncasecmp(mime, "video/", 6)) {
1069            continue;
1070        }
1071
1072        BlockIterator iter(this, info->mTrackNum, i);
1073        int32_t j = 0;
1074        int64_t thumbnailTimeUs = 0;
1075        size_t maxBlockSize = 0;
1076        while (!iter.eos() && j < 20) {
1077            if (iter.block()->IsKey()) {
1078                ++j;
1079
1080                size_t blockSize = 0;
1081                for (int k = 0; k < iter.block()->GetFrameCount(); ++k) {
1082                    blockSize += iter.block()->GetFrame(k).len;
1083                }
1084
1085                if (blockSize > maxBlockSize) {
1086                    maxBlockSize = blockSize;
1087                    thumbnailTimeUs = iter.blockTimeUs();
1088                }
1089            }
1090            iter.advance();
1091        }
1092        info->mMeta->setInt64(kKeyThumbnailTime, thumbnailTimeUs);
1093    }
1094}
1095
1096sp<MetaData> MatroskaExtractor::getMetaData() {
1097    sp<MetaData> meta = new MetaData;
1098
1099    meta->setCString(
1100            kKeyMIMEType,
1101            mIsWebm ? "video/webm" : MEDIA_MIMETYPE_CONTAINER_MATROSKA);
1102
1103    return meta;
1104}
1105
1106uint32_t MatroskaExtractor::flags() const {
1107    uint32_t x = CAN_PAUSE;
1108    if (!isLiveStreaming()) {
1109        x |= CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK;
1110    }
1111
1112    return x;
1113}
1114
1115bool SniffMatroska(
1116        const sp<DataSource> &source, String8 *mimeType, float *confidence,
1117        sp<AMessage> *) {
1118    DataSourceReader reader(source);
1119    mkvparser::EBMLHeader ebmlHeader;
1120    long long pos;
1121    if (ebmlHeader.Parse(&reader, pos) < 0) {
1122        return false;
1123    }
1124
1125    mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_MATROSKA);
1126    *confidence = 0.6;
1127
1128    return true;
1129}
1130
1131}  // namespace android
1132