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