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