Home | History | Annotate | Download | only in matroska
      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 namespace android {
     37 
     38 struct 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 
     80 private:
     81     sp<DataSource> mSource;
     82 
     83     DataSourceReader(const DataSourceReader &);
     84     DataSourceReader &operator=(const DataSourceReader &);
     85 };
     86 
     87 ////////////////////////////////////////////////////////////////////////////////
     88 
     89 struct BlockIterator {
     90     BlockIterator(MatroskaExtractor *extractor, unsigned long trackNum);
     91 
     92     bool eos() const;
     93 
     94     void advance();
     95     void reset();
     96     void seek(int64_t seekTimeUs, bool seekToKeyFrame);
     97 
     98     const mkvparser::Block *block() const;
     99     int64_t blockTimeUs() const;
    100 
    101 private:
    102     MatroskaExtractor *mExtractor;
    103     unsigned long mTrackNum;
    104 
    105     const mkvparser::Cluster *mCluster;
    106     const mkvparser::BlockEntry *mBlockEntry;
    107     long mBlockEntryIndex;
    108 
    109     void advance_l();
    110 
    111     BlockIterator(const BlockIterator &);
    112     BlockIterator &operator=(const BlockIterator &);
    113 };
    114 
    115 struct MatroskaSource : public MediaSource {
    116     MatroskaSource(
    117             const sp<MatroskaExtractor> &extractor, size_t index);
    118 
    119     virtual status_t start(MetaData *params);
    120     virtual status_t stop();
    121 
    122     virtual sp<MetaData> getFormat();
    123 
    124     virtual status_t read(
    125             MediaBuffer **buffer, const ReadOptions *options);
    126 
    127 protected:
    128     virtual ~MatroskaSource();
    129 
    130 private:
    131     enum Type {
    132         AVC,
    133         AAC,
    134         OTHER
    135     };
    136 
    137     sp<MatroskaExtractor> mExtractor;
    138     size_t mTrackIndex;
    139     Type mType;
    140     bool mIsAudio;
    141     BlockIterator mBlockIter;
    142     size_t mNALSizeLen;  // for type AVC
    143 
    144     List<MediaBuffer *> mPendingFrames;
    145 
    146     status_t advance();
    147 
    148     status_t readBlock();
    149     void clearPendingFrames();
    150 
    151     MatroskaSource(const MatroskaSource &);
    152     MatroskaSource &operator=(const MatroskaSource &);
    153 };
    154 
    155 MatroskaSource::MatroskaSource(
    156         const sp<MatroskaExtractor> &extractor, size_t index)
    157     : mExtractor(extractor),
    158       mTrackIndex(index),
    159       mType(OTHER),
    160       mIsAudio(false),
    161       mBlockIter(mExtractor.get(),
    162                  mExtractor->mTracks.itemAt(index).mTrackNum),
    163       mNALSizeLen(0) {
    164     sp<MetaData> meta = mExtractor->mTracks.itemAt(index).mMeta;
    165 
    166     const char *mime;
    167     CHECK(meta->findCString(kKeyMIMEType, &mime));
    168 
    169     mIsAudio = !strncasecmp("audio/", mime, 6);
    170 
    171     if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
    172         mType = AVC;
    173 
    174         uint32_t dummy;
    175         const uint8_t *avcc;
    176         size_t avccSize;
    177         CHECK(meta->findData(
    178                     kKeyAVCC, &dummy, (const void **)&avcc, &avccSize));
    179 
    180         CHECK_GE(avccSize, 5u);
    181 
    182         mNALSizeLen = 1 + (avcc[4] & 3);
    183         LOGV("mNALSizeLen = %d", mNALSizeLen);
    184     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
    185         mType = AAC;
    186     }
    187 }
    188 
    189 MatroskaSource::~MatroskaSource() {
    190     clearPendingFrames();
    191 }
    192 
    193 status_t MatroskaSource::start(MetaData *params) {
    194     mBlockIter.reset();
    195 
    196     return OK;
    197 }
    198 
    199 status_t MatroskaSource::stop() {
    200     clearPendingFrames();
    201 
    202     return OK;
    203 }
    204 
    205 sp<MetaData> MatroskaSource::getFormat() {
    206     return mExtractor->mTracks.itemAt(mTrackIndex).mMeta;
    207 }
    208 
    209 ////////////////////////////////////////////////////////////////////////////////
    210 
    211 BlockIterator::BlockIterator(
    212         MatroskaExtractor *extractor, unsigned long trackNum)
    213     : mExtractor(extractor),
    214       mTrackNum(trackNum),
    215       mCluster(NULL),
    216       mBlockEntry(NULL),
    217       mBlockEntryIndex(0) {
    218     reset();
    219 }
    220 
    221 bool BlockIterator::eos() const {
    222     return mCluster == NULL || mCluster->EOS();
    223 }
    224 
    225 void BlockIterator::advance() {
    226     Mutex::Autolock autoLock(mExtractor->mLock);
    227     advance_l();
    228 }
    229 
    230 void BlockIterator::advance_l() {
    231     for (;;) {
    232         long res = mCluster->GetEntry(mBlockEntryIndex, mBlockEntry);
    233         LOGV("GetEntry returned %ld", res);
    234 
    235         long long pos;
    236         long len;
    237         if (res < 0) {
    238             // Need to parse this cluster some more
    239 
    240             CHECK_EQ(res, mkvparser::E_BUFFER_NOT_FULL);
    241 
    242             res = mCluster->Parse(pos, len);
    243             LOGV("Parse returned %ld", res);
    244 
    245             if (res < 0) {
    246                 // I/O error
    247 
    248                 LOGE("Cluster::Parse returned result %ld", res);
    249 
    250                 mCluster = NULL;
    251                 break;
    252             }
    253 
    254             continue;
    255         } else if (res == 0) {
    256             // We're done with this cluster
    257 
    258             const mkvparser::Cluster *nextCluster;
    259             res = mExtractor->mSegment->ParseNext(
    260                     mCluster, nextCluster, pos, len);
    261             LOGV("ParseNext returned %ld", res);
    262 
    263             if (res > 0) {
    264                 // EOF
    265 
    266                 mCluster = NULL;
    267                 break;
    268             }
    269 
    270             CHECK_EQ(res, 0);
    271             CHECK(nextCluster != NULL);
    272             CHECK(!nextCluster->EOS());
    273 
    274             mCluster = nextCluster;
    275 
    276             res = mCluster->Parse(pos, len);
    277             LOGV("Parse (2) returned %ld", res);
    278             CHECK_GE(res, 0);
    279 
    280             mBlockEntryIndex = 0;
    281             continue;
    282         }
    283 
    284         CHECK(mBlockEntry != NULL);
    285         CHECK(mBlockEntry->GetBlock() != NULL);
    286         ++mBlockEntryIndex;
    287 
    288         if (mBlockEntry->GetBlock()->GetTrackNumber() == mTrackNum) {
    289             break;
    290         }
    291     }
    292 }
    293 
    294 void BlockIterator::reset() {
    295     Mutex::Autolock autoLock(mExtractor->mLock);
    296 
    297     mCluster = mExtractor->mSegment->GetFirst();
    298     mBlockEntry = NULL;
    299     mBlockEntryIndex = 0;
    300 
    301     do {
    302         advance_l();
    303     } while (!eos() && block()->GetTrackNumber() != mTrackNum);
    304 }
    305 
    306 void BlockIterator::seek(int64_t seekTimeUs, bool seekToKeyFrame) {
    307     Mutex::Autolock autoLock(mExtractor->mLock);
    308 
    309     mCluster = mExtractor->mSegment->FindCluster(seekTimeUs * 1000ll);
    310     mBlockEntry = NULL;
    311     mBlockEntryIndex = 0;
    312 
    313     do {
    314         advance_l();
    315     }
    316     while (!eos() && block()->GetTrackNumber() != mTrackNum);
    317 
    318     if (seekToKeyFrame) {
    319         while (!eos() && !mBlockEntry->GetBlock()->IsKey()) {
    320             advance_l();
    321         }
    322     }
    323 }
    324 
    325 const mkvparser::Block *BlockIterator::block() const {
    326     CHECK(!eos());
    327 
    328     return mBlockEntry->GetBlock();
    329 }
    330 
    331 int64_t BlockIterator::blockTimeUs() const {
    332     return (mBlockEntry->GetBlock()->GetTime(mCluster) + 500ll) / 1000ll;
    333 }
    334 
    335 ////////////////////////////////////////////////////////////////////////////////
    336 
    337 static unsigned U24_AT(const uint8_t *ptr) {
    338     return ptr[0] << 16 | ptr[1] << 8 | ptr[2];
    339 }
    340 
    341 static size_t clz(uint8_t x) {
    342     size_t numLeadingZeroes = 0;
    343 
    344     while (!(x & 0x80)) {
    345         ++numLeadingZeroes;
    346         x = x << 1;
    347     }
    348 
    349     return numLeadingZeroes;
    350 }
    351 
    352 void MatroskaSource::clearPendingFrames() {
    353     while (!mPendingFrames.empty()) {
    354         MediaBuffer *frame = *mPendingFrames.begin();
    355         mPendingFrames.erase(mPendingFrames.begin());
    356 
    357         frame->release();
    358         frame = NULL;
    359     }
    360 }
    361 
    362 status_t MatroskaSource::readBlock() {
    363     CHECK(mPendingFrames.empty());
    364 
    365     if (mBlockIter.eos()) {
    366         return ERROR_END_OF_STREAM;
    367     }
    368 
    369     const mkvparser::Block *block = mBlockIter.block();
    370 
    371     int64_t timeUs = mBlockIter.blockTimeUs();
    372 
    373     for (int i = 0; i < block->GetFrameCount(); ++i) {
    374         const mkvparser::Block::Frame &frame = block->GetFrame(i);
    375 
    376         MediaBuffer *mbuf = new MediaBuffer(frame.len);
    377         mbuf->meta_data()->setInt64(kKeyTime, timeUs);
    378         mbuf->meta_data()->setInt32(kKeyIsSyncFrame, block->IsKey());
    379 
    380         long n = frame.Read(mExtractor->mReader, (unsigned char *)mbuf->data());
    381         if (n != 0) {
    382             mPendingFrames.clear();
    383 
    384             mBlockIter.advance();
    385             return ERROR_IO;
    386         }
    387 
    388         mPendingFrames.push_back(mbuf);
    389     }
    390 
    391     mBlockIter.advance();
    392 
    393     return OK;
    394 }
    395 
    396 status_t MatroskaSource::read(
    397         MediaBuffer **out, const ReadOptions *options) {
    398     *out = NULL;
    399 
    400     int64_t seekTimeUs;
    401     ReadOptions::SeekMode mode;
    402     if (options && options->getSeekTo(&seekTimeUs, &mode)
    403             && !mExtractor->isLiveStreaming()) {
    404         clearPendingFrames();
    405 
    406         // Apparently keyframe indication in audio tracks is unreliable,
    407         // fortunately in all our currently supported audio encodings every
    408         // frame is effectively a keyframe.
    409         mBlockIter.seek(seekTimeUs, !mIsAudio);
    410     }
    411 
    412 again:
    413     while (mPendingFrames.empty()) {
    414         status_t err = readBlock();
    415 
    416         if (err != OK) {
    417             clearPendingFrames();
    418 
    419             return err;
    420         }
    421     }
    422 
    423     MediaBuffer *frame = *mPendingFrames.begin();
    424     mPendingFrames.erase(mPendingFrames.begin());
    425 
    426     if (mType != AVC) {
    427         *out = frame;
    428 
    429         return OK;
    430     }
    431 
    432     // Each input frame contains one or more NAL fragments, each fragment
    433     // is prefixed by mNALSizeLen bytes giving the fragment length,
    434     // followed by a corresponding number of bytes containing the fragment.
    435     // We output all these fragments into a single large buffer separated
    436     // by startcodes (0x00 0x00 0x00 0x01).
    437 
    438     const uint8_t *srcPtr =
    439         (const uint8_t *)frame->data() + frame->range_offset();
    440 
    441     size_t srcSize = frame->range_length();
    442 
    443     size_t dstSize = 0;
    444     MediaBuffer *buffer = NULL;
    445     uint8_t *dstPtr = NULL;
    446 
    447     for (int32_t pass = 0; pass < 2; ++pass) {
    448         size_t srcOffset = 0;
    449         size_t dstOffset = 0;
    450         while (srcOffset + mNALSizeLen <= srcSize) {
    451             size_t NALsize;
    452             switch (mNALSizeLen) {
    453                 case 1: NALsize = srcPtr[srcOffset]; break;
    454                 case 2: NALsize = U16_AT(srcPtr + srcOffset); break;
    455                 case 3: NALsize = U24_AT(srcPtr + srcOffset); break;
    456                 case 4: NALsize = U32_AT(srcPtr + srcOffset); break;
    457                 default:
    458                     TRESPASS();
    459             }
    460 
    461             if (srcOffset + mNALSizeLen + NALsize > srcSize) {
    462                 break;
    463             }
    464 
    465             if (pass == 1) {
    466                 memcpy(&dstPtr[dstOffset], "\x00\x00\x00\x01", 4);
    467 
    468                 memcpy(&dstPtr[dstOffset + 4],
    469                        &srcPtr[srcOffset + mNALSizeLen],
    470                        NALsize);
    471             }
    472 
    473             dstOffset += 4;  // 0x00 00 00 01
    474             dstOffset += NALsize;
    475 
    476             srcOffset += mNALSizeLen + NALsize;
    477         }
    478 
    479         if (srcOffset < srcSize) {
    480             // There were trailing bytes or not enough data to complete
    481             // a fragment.
    482 
    483             frame->release();
    484             frame = NULL;
    485 
    486             return ERROR_MALFORMED;
    487         }
    488 
    489         if (pass == 0) {
    490             dstSize = dstOffset;
    491 
    492             buffer = new MediaBuffer(dstSize);
    493 
    494             int64_t timeUs;
    495             CHECK(frame->meta_data()->findInt64(kKeyTime, &timeUs));
    496             int32_t isSync;
    497             CHECK(frame->meta_data()->findInt32(kKeyIsSyncFrame, &isSync));
    498 
    499             buffer->meta_data()->setInt64(kKeyTime, timeUs);
    500             buffer->meta_data()->setInt32(kKeyIsSyncFrame, isSync);
    501 
    502             dstPtr = (uint8_t *)buffer->data();
    503         }
    504     }
    505 
    506     frame->release();
    507     frame = NULL;
    508 
    509     *out = buffer;
    510 
    511     return OK;
    512 }
    513 
    514 ////////////////////////////////////////////////////////////////////////////////
    515 
    516 MatroskaExtractor::MatroskaExtractor(const sp<DataSource> &source)
    517     : mDataSource(source),
    518       mReader(new DataSourceReader(mDataSource)),
    519       mSegment(NULL),
    520       mExtractedThumbnails(false),
    521       mIsWebm(false) {
    522     off64_t size;
    523     mIsLiveStreaming =
    524         (mDataSource->flags()
    525             & (DataSource::kWantsPrefetching
    526                 | DataSource::kIsCachingDataSource))
    527         && mDataSource->getSize(&size) != OK;
    528 
    529     mkvparser::EBMLHeader ebmlHeader;
    530     long long pos;
    531     if (ebmlHeader.Parse(mReader, pos) < 0) {
    532         return;
    533     }
    534 
    535     if (ebmlHeader.m_docType && !strcmp("webm", ebmlHeader.m_docType)) {
    536         mIsWebm = true;
    537     }
    538 
    539     long long ret =
    540         mkvparser::Segment::CreateInstance(mReader, pos, mSegment);
    541 
    542     if (ret) {
    543         CHECK(mSegment == NULL);
    544         return;
    545     }
    546 
    547     if (isLiveStreaming()) {
    548         ret = mSegment->ParseHeaders();
    549         CHECK_EQ(ret, 0);
    550 
    551         long len;
    552         ret = mSegment->LoadCluster(pos, len);
    553         CHECK_EQ(ret, 0);
    554     } else {
    555         ret = mSegment->Load();
    556     }
    557 
    558     if (ret < 0) {
    559         delete mSegment;
    560         mSegment = NULL;
    561         return;
    562     }
    563 
    564 #if 0
    565     const mkvparser::SegmentInfo *info = mSegment->GetInfo();
    566     LOGI("muxing app: %s, writing app: %s",
    567          info->GetMuxingAppAsUTF8(),
    568          info->GetWritingAppAsUTF8());
    569 #endif
    570 
    571     addTracks();
    572 }
    573 
    574 MatroskaExtractor::~MatroskaExtractor() {
    575     delete mSegment;
    576     mSegment = NULL;
    577 
    578     delete mReader;
    579     mReader = NULL;
    580 }
    581 
    582 size_t MatroskaExtractor::countTracks() {
    583     return mTracks.size();
    584 }
    585 
    586 sp<MediaSource> MatroskaExtractor::getTrack(size_t index) {
    587     if (index >= mTracks.size()) {
    588         return NULL;
    589     }
    590 
    591     return new MatroskaSource(this, index);
    592 }
    593 
    594 sp<MetaData> MatroskaExtractor::getTrackMetaData(
    595         size_t index, uint32_t flags) {
    596     if (index >= mTracks.size()) {
    597         return NULL;
    598     }
    599 
    600     if ((flags & kIncludeExtensiveMetaData) && !mExtractedThumbnails
    601             && !isLiveStreaming()) {
    602         findThumbnails();
    603         mExtractedThumbnails = true;
    604     }
    605 
    606     return mTracks.itemAt(index).mMeta;
    607 }
    608 
    609 bool MatroskaExtractor::isLiveStreaming() const {
    610     return mIsLiveStreaming;
    611 }
    612 
    613 static void addESDSFromAudioSpecificInfo(
    614         const sp<MetaData> &meta, const void *asi, size_t asiSize) {
    615     static const uint8_t kStaticESDS[] = {
    616         0x03, 22,
    617         0x00, 0x00,     // ES_ID
    618         0x00,           // streamDependenceFlag, URL_Flag, OCRstreamFlag
    619 
    620         0x04, 17,
    621         0x40,                       // Audio ISO/IEC 14496-3
    622         0x00, 0x00, 0x00, 0x00,
    623         0x00, 0x00, 0x00, 0x00,
    624         0x00, 0x00, 0x00, 0x00,
    625 
    626         0x05,
    627         // AudioSpecificInfo (with size prefix) follows
    628     };
    629 
    630     // Make sure all sizes can be coded in a single byte.
    631     CHECK(asiSize + 22 - 2 < 128);
    632     size_t esdsSize = sizeof(kStaticESDS) + asiSize + 1;
    633     uint8_t *esds = new uint8_t[esdsSize];
    634     memcpy(esds, kStaticESDS, sizeof(kStaticESDS));
    635     uint8_t *ptr = esds + sizeof(kStaticESDS);
    636     *ptr++ = asiSize;
    637     memcpy(ptr, asi, asiSize);
    638 
    639     // Increment by codecPrivateSize less 2 bytes that are accounted for
    640     // already in lengths of 22/17
    641     esds[1] += asiSize - 2;
    642     esds[6] += asiSize - 2;
    643 
    644     meta->setData(kKeyESDS, 0, esds, esdsSize);
    645 
    646     delete[] esds;
    647     esds = NULL;
    648 }
    649 
    650 void addVorbisCodecInfo(
    651         const sp<MetaData> &meta,
    652         const void *_codecPrivate, size_t codecPrivateSize) {
    653     // printf("vorbis private data follows:\n");
    654     // hexdump(_codecPrivate, codecPrivateSize);
    655 
    656     CHECK(codecPrivateSize >= 3);
    657 
    658     const uint8_t *codecPrivate = (const uint8_t *)_codecPrivate;
    659     CHECK(codecPrivate[0] == 0x02);
    660 
    661     size_t len1 = codecPrivate[1];
    662     size_t len2 = codecPrivate[2];
    663 
    664     CHECK(codecPrivateSize > 3 + len1 + len2);
    665 
    666     CHECK(codecPrivate[3] == 0x01);
    667     meta->setData(kKeyVorbisInfo, 0, &codecPrivate[3], len1);
    668 
    669     CHECK(codecPrivate[len1 + 3] == 0x03);
    670 
    671     CHECK(codecPrivate[len1 + len2 + 3] == 0x05);
    672     meta->setData(
    673             kKeyVorbisBooks, 0, &codecPrivate[len1 + len2 + 3],
    674             codecPrivateSize - len1 - len2 - 3);
    675 }
    676 
    677 void MatroskaExtractor::addTracks() {
    678     const mkvparser::Tracks *tracks = mSegment->GetTracks();
    679 
    680     for (size_t index = 0; index < tracks->GetTracksCount(); ++index) {
    681         const mkvparser::Track *track = tracks->GetTrackByIndex(index);
    682 
    683         if (track == NULL) {
    684             // Apparently this is currently valid (if unexpected) behaviour
    685             // of the mkv parser lib.
    686             continue;
    687         }
    688 
    689         const char *const codecID = track->GetCodecId();
    690         LOGV("codec id = %s", codecID);
    691         LOGV("codec name = %s", track->GetCodecNameAsUTF8());
    692 
    693         size_t codecPrivateSize;
    694         const unsigned char *codecPrivate =
    695             track->GetCodecPrivate(codecPrivateSize);
    696 
    697         enum { VIDEO_TRACK = 1, AUDIO_TRACK = 2 };
    698 
    699         sp<MetaData> meta = new MetaData;
    700 
    701         switch (track->GetType()) {
    702             case VIDEO_TRACK:
    703             {
    704                 const mkvparser::VideoTrack *vtrack =
    705                     static_cast<const mkvparser::VideoTrack *>(track);
    706 
    707                 if (!strcmp("V_MPEG4/ISO/AVC", codecID)) {
    708                     meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
    709                     meta->setData(kKeyAVCC, 0, codecPrivate, codecPrivateSize);
    710                 } else if (!strcmp("V_VP8", codecID)) {
    711                     meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VPX);
    712                 } else {
    713                     continue;
    714                 }
    715 
    716                 meta->setInt32(kKeyWidth, vtrack->GetWidth());
    717                 meta->setInt32(kKeyHeight, vtrack->GetHeight());
    718                 break;
    719             }
    720 
    721             case AUDIO_TRACK:
    722             {
    723                 const mkvparser::AudioTrack *atrack =
    724                     static_cast<const mkvparser::AudioTrack *>(track);
    725 
    726                 if (!strcmp("A_AAC", codecID)) {
    727                     meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
    728                     CHECK(codecPrivateSize >= 2);
    729 
    730                     addESDSFromAudioSpecificInfo(
    731                             meta, codecPrivate, codecPrivateSize);
    732                 } else if (!strcmp("A_VORBIS", codecID)) {
    733                     meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS);
    734 
    735                     addVorbisCodecInfo(meta, codecPrivate, codecPrivateSize);
    736                 } else {
    737                     continue;
    738                 }
    739 
    740                 meta->setInt32(kKeySampleRate, atrack->GetSamplingRate());
    741                 meta->setInt32(kKeyChannelCount, atrack->GetChannels());
    742                 break;
    743             }
    744 
    745             default:
    746                 continue;
    747         }
    748 
    749         long long durationNs = mSegment->GetDuration();
    750         meta->setInt64(kKeyDuration, (durationNs + 500) / 1000);
    751 
    752         mTracks.push();
    753         TrackInfo *trackInfo = &mTracks.editItemAt(mTracks.size() - 1);
    754         trackInfo->mTrackNum = track->GetNumber();
    755         trackInfo->mMeta = meta;
    756     }
    757 }
    758 
    759 void MatroskaExtractor::findThumbnails() {
    760     for (size_t i = 0; i < mTracks.size(); ++i) {
    761         TrackInfo *info = &mTracks.editItemAt(i);
    762 
    763         const char *mime;
    764         CHECK(info->mMeta->findCString(kKeyMIMEType, &mime));
    765 
    766         if (strncasecmp(mime, "video/", 6)) {
    767             continue;
    768         }
    769 
    770         BlockIterator iter(this, info->mTrackNum);
    771         int32_t i = 0;
    772         int64_t thumbnailTimeUs = 0;
    773         size_t maxBlockSize = 0;
    774         while (!iter.eos() && i < 20) {
    775             if (iter.block()->IsKey()) {
    776                 ++i;
    777 
    778                 size_t blockSize = 0;
    779                 for (int i = 0; i < iter.block()->GetFrameCount(); ++i) {
    780                     blockSize += iter.block()->GetFrame(i).len;
    781                 }
    782 
    783                 if (blockSize > maxBlockSize) {
    784                     maxBlockSize = blockSize;
    785                     thumbnailTimeUs = iter.blockTimeUs();
    786                 }
    787             }
    788             iter.advance();
    789         }
    790         info->mMeta->setInt64(kKeyThumbnailTime, thumbnailTimeUs);
    791     }
    792 }
    793 
    794 sp<MetaData> MatroskaExtractor::getMetaData() {
    795     sp<MetaData> meta = new MetaData;
    796 
    797     meta->setCString(
    798             kKeyMIMEType,
    799             mIsWebm ? "video/webm" : MEDIA_MIMETYPE_CONTAINER_MATROSKA);
    800 
    801     return meta;
    802 }
    803 
    804 uint32_t MatroskaExtractor::flags() const {
    805     uint32_t x = CAN_PAUSE;
    806     if (!isLiveStreaming()) {
    807         x |= CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK;
    808     }
    809 
    810     return x;
    811 }
    812 
    813 bool SniffMatroska(
    814         const sp<DataSource> &source, String8 *mimeType, float *confidence,
    815         sp<AMessage> *) {
    816     DataSourceReader reader(source);
    817     mkvparser::EBMLHeader ebmlHeader;
    818     long long pos;
    819     if (ebmlHeader.Parse(&reader, pos) < 0) {
    820         return false;
    821     }
    822 
    823     mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_MATROSKA);
    824     *confidence = 0.6;
    825 
    826     return true;
    827 }
    828 
    829 }  // namespace android
    830