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