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/DataSource.h>
     26 #include <media/stagefright/MediaBuffer.h>
     27 #include <media/stagefright/MediaDebug.h>
     28 #include <media/stagefright/MediaDefs.h>
     29 #include <media/stagefright/MediaErrors.h>
     30 #include <media/stagefright/MediaSource.h>
     31 #include <media/stagefright/MetaData.h>
     32 #include <utils/String8.h>
     33 
     34 namespace android {
     35 
     36 struct DataSourceReader : public mkvparser::IMkvReader {
     37     DataSourceReader(const sp<DataSource> &source)
     38         : mSource(source) {
     39     }
     40 
     41     virtual int Read(long long position, long length, unsigned char* buffer) {
     42         CHECK(position >= 0);
     43         CHECK(length >= 0);
     44 
     45         if (length == 0) {
     46             return 0;
     47         }
     48 
     49         ssize_t n = mSource->readAt(position, buffer, length);
     50 
     51         if (n <= 0) {
     52             return -1;
     53         }
     54 
     55         return 0;
     56     }
     57 
     58     virtual int Length(long long* total, long long* available) {
     59         off_t size;
     60         if (mSource->getSize(&size) != OK) {
     61             return -1;
     62         }
     63 
     64         if (total) {
     65             *total = size;
     66         }
     67 
     68         if (available) {
     69             *available = size;
     70         }
     71 
     72         return 0;
     73     }
     74 
     75 private:
     76     sp<DataSource> mSource;
     77 
     78     DataSourceReader(const DataSourceReader &);
     79     DataSourceReader &operator=(const DataSourceReader &);
     80 };
     81 
     82 ////////////////////////////////////////////////////////////////////////////////
     83 
     84 #include <ctype.h>
     85 static void hexdump(const void *_data, size_t size) {
     86     const uint8_t *data = (const uint8_t *)_data;
     87     size_t offset = 0;
     88     while (offset < size) {
     89         printf("0x%04x  ", offset);
     90 
     91         size_t n = size - offset;
     92         if (n > 16) {
     93             n = 16;
     94         }
     95 
     96         for (size_t i = 0; i < 16; ++i) {
     97             if (i == 8) {
     98                 printf(" ");
     99             }
    100 
    101             if (offset + i < size) {
    102                 printf("%02x ", data[offset + i]);
    103             } else {
    104                 printf("   ");
    105             }
    106         }
    107 
    108         printf(" ");
    109 
    110         for (size_t i = 0; i < n; ++i) {
    111             if (isprint(data[offset + i])) {
    112                 printf("%c", data[offset + i]);
    113             } else {
    114                 printf(".");
    115             }
    116         }
    117 
    118         printf("\n");
    119 
    120         offset += 16;
    121     }
    122 }
    123 
    124 struct BlockIterator {
    125     BlockIterator(mkvparser::Segment *segment, unsigned long trackNum);
    126 
    127     bool eos() const;
    128 
    129     void advance();
    130     void reset();
    131     void seek(int64_t seekTimeUs);
    132 
    133     const mkvparser::Block *block() const;
    134     int64_t blockTimeUs() const;
    135 
    136 private:
    137     mkvparser::Segment *mSegment;
    138     unsigned long mTrackNum;
    139 
    140     mkvparser::Cluster *mCluster;
    141     const mkvparser::BlockEntry *mBlockEntry;
    142 
    143     BlockIterator(const BlockIterator &);
    144     BlockIterator &operator=(const BlockIterator &);
    145 };
    146 
    147 struct MatroskaSource : public MediaSource {
    148     MatroskaSource(
    149             const sp<MatroskaExtractor> &extractor, size_t index);
    150 
    151     virtual status_t start(MetaData *params);
    152     virtual status_t stop();
    153 
    154     virtual sp<MetaData> getFormat();
    155 
    156     virtual status_t read(
    157             MediaBuffer **buffer, const ReadOptions *options);
    158 
    159 private:
    160     enum Type {
    161         AVC,
    162         AAC,
    163         OTHER
    164     };
    165 
    166     sp<MatroskaExtractor> mExtractor;
    167     size_t mTrackIndex;
    168     Type mType;
    169     BlockIterator mBlockIter;
    170 
    171     status_t advance();
    172 
    173     MatroskaSource(const MatroskaSource &);
    174     MatroskaSource &operator=(const MatroskaSource &);
    175 };
    176 
    177 MatroskaSource::MatroskaSource(
    178         const sp<MatroskaExtractor> &extractor, size_t index)
    179     : mExtractor(extractor),
    180       mTrackIndex(index),
    181       mType(OTHER),
    182       mBlockIter(mExtractor->mSegment,
    183                  mExtractor->mTracks.itemAt(index).mTrackNum) {
    184     const char *mime;
    185     CHECK(mExtractor->mTracks.itemAt(index).mMeta->
    186             findCString(kKeyMIMEType, &mime));
    187 
    188     if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
    189         mType = AVC;
    190     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
    191         mType = AAC;
    192     }
    193 }
    194 
    195 status_t MatroskaSource::start(MetaData *params) {
    196     mBlockIter.reset();
    197 
    198     return OK;
    199 }
    200 
    201 status_t MatroskaSource::stop() {
    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         mkvparser::Segment *segment, unsigned long trackNum)
    213     : mSegment(segment),
    214       mTrackNum(trackNum),
    215       mCluster(NULL),
    216       mBlockEntry(NULL) {
    217     reset();
    218 }
    219 
    220 bool BlockIterator::eos() const {
    221     return mCluster == NULL || mCluster->EOS();
    222 }
    223 
    224 void BlockIterator::advance() {
    225     while (!eos()) {
    226         if (mBlockEntry != NULL) {
    227             mBlockEntry = mCluster->GetNext(mBlockEntry);
    228         } else if (mCluster != NULL) {
    229             mCluster = mSegment->GetNext(mCluster);
    230 
    231             if (eos()) {
    232                 break;
    233             }
    234 
    235             mBlockEntry = mCluster->GetFirst();
    236         }
    237 
    238         if (mBlockEntry != NULL
    239                 && mBlockEntry->GetBlock()->GetTrackNumber() == mTrackNum) {
    240             break;
    241         }
    242     }
    243 }
    244 
    245 void BlockIterator::reset() {
    246     mCluster = mSegment->GetFirst();
    247     mBlockEntry = mCluster->GetFirst();
    248 
    249     while (!eos() && block()->GetTrackNumber() != mTrackNum) {
    250         advance();
    251     }
    252 }
    253 
    254 void BlockIterator::seek(int64_t seekTimeUs) {
    255     mCluster = mSegment->GetCluster(seekTimeUs * 1000ll);
    256     mBlockEntry = mCluster != NULL ? mCluster->GetFirst() : NULL;
    257 
    258     while (!eos() && block()->GetTrackNumber() != mTrackNum) {
    259         advance();
    260     }
    261 
    262     while (!eos() && !mBlockEntry->GetBlock()->IsKey()) {
    263         advance();
    264     }
    265 }
    266 
    267 const mkvparser::Block *BlockIterator::block() const {
    268     CHECK(!eos());
    269 
    270     return mBlockEntry->GetBlock();
    271 }
    272 
    273 int64_t BlockIterator::blockTimeUs() const {
    274     return (mBlockEntry->GetBlock()->GetTime(mCluster) + 500ll) / 1000ll;
    275 }
    276 
    277 ////////////////////////////////////////////////////////////////////////////////
    278 
    279 status_t MatroskaSource::read(
    280         MediaBuffer **out, const ReadOptions *options) {
    281     *out = NULL;
    282 
    283     int64_t seekTimeUs;
    284     ReadOptions::SeekMode mode;
    285     if (options && options->getSeekTo(&seekTimeUs, &mode)) {
    286         mBlockIter.seek(seekTimeUs);
    287     }
    288 
    289     if (mBlockIter.eos()) {
    290         return ERROR_END_OF_STREAM;
    291     }
    292 
    293     const mkvparser::Block *block = mBlockIter.block();
    294     size_t size = block->GetSize();
    295     int64_t timeUs = mBlockIter.blockTimeUs();
    296 
    297     MediaBuffer *buffer = new MediaBuffer(size + 2);
    298     buffer->meta_data()->setInt64(kKeyTime, timeUs);
    299     buffer->meta_data()->setInt32(kKeyIsSyncFrame, block->IsKey());
    300 
    301     long res = block->Read(
    302             mExtractor->mReader, (unsigned char *)buffer->data() + 2);
    303 
    304     if (res != 0) {
    305         return ERROR_END_OF_STREAM;
    306     }
    307 
    308     buffer->set_range(2, size);
    309 
    310     if (mType == AVC) {
    311         CHECK(size >= 2);
    312 
    313         uint8_t *data = (uint8_t *)buffer->data();
    314 
    315         unsigned NALsize = data[2] << 8 | data[3];
    316         CHECK_EQ(size, NALsize + 2);
    317 
    318         memcpy(data, "\x00\x00\x00\x01", 4);
    319         buffer->set_range(0, size + 2);
    320     } else if (mType == AAC) {
    321         // There's strange junk at the beginning...
    322 
    323         const uint8_t *data = (const uint8_t *)buffer->data() + 2;
    324         size_t offset = 0;
    325         while (offset < size && data[offset] != 0x21) {
    326             ++offset;
    327         }
    328         buffer->set_range(2 + offset, size - offset);
    329     }
    330 
    331     *out = buffer;
    332 
    333 #if 0
    334     hexdump((const uint8_t *)buffer->data() + buffer->range_offset(),
    335             buffer->range_length());
    336 #endif
    337 
    338     mBlockIter.advance();
    339 
    340     return OK;
    341 }
    342 
    343 ////////////////////////////////////////////////////////////////////////////////
    344 
    345 MatroskaExtractor::MatroskaExtractor(const sp<DataSource> &source)
    346     : mDataSource(source),
    347       mReader(new DataSourceReader(mDataSource)),
    348       mSegment(NULL),
    349       mExtractedThumbnails(false) {
    350     mkvparser::EBMLHeader ebmlHeader;
    351     long long pos;
    352     if (ebmlHeader.Parse(mReader, pos) < 0) {
    353         return;
    354     }
    355 
    356     long long ret =
    357         mkvparser::Segment::CreateInstance(mReader, pos, mSegment);
    358 
    359     if (ret) {
    360         CHECK(mSegment == NULL);
    361         return;
    362     }
    363 
    364     ret = mSegment->Load();
    365 
    366     if (ret < 0) {
    367         delete mSegment;
    368         mSegment = NULL;
    369         return;
    370     }
    371 
    372     addTracks();
    373 }
    374 
    375 MatroskaExtractor::~MatroskaExtractor() {
    376     delete mSegment;
    377     mSegment = NULL;
    378 
    379     delete mReader;
    380     mReader = NULL;
    381 }
    382 
    383 size_t MatroskaExtractor::countTracks() {
    384     return mTracks.size();
    385 }
    386 
    387 sp<MediaSource> MatroskaExtractor::getTrack(size_t index) {
    388     if (index >= mTracks.size()) {
    389         return NULL;
    390     }
    391 
    392     return new MatroskaSource(this, index);
    393 }
    394 
    395 sp<MetaData> MatroskaExtractor::getTrackMetaData(
    396         size_t index, uint32_t flags) {
    397     if (index >= mTracks.size()) {
    398         return NULL;
    399     }
    400 
    401     if ((flags & kIncludeExtensiveMetaData) && !mExtractedThumbnails) {
    402         findThumbnails();
    403         mExtractedThumbnails = true;
    404     }
    405 
    406     return mTracks.itemAt(index).mMeta;
    407 }
    408 
    409 static void addESDSFromAudioSpecificInfo(
    410         const sp<MetaData> &meta, const void *asi, size_t asiSize) {
    411     static const uint8_t kStaticESDS[] = {
    412         0x03, 22,
    413         0x00, 0x00,     // ES_ID
    414         0x00,           // streamDependenceFlag, URL_Flag, OCRstreamFlag
    415 
    416         0x04, 17,
    417         0x40,                       // Audio ISO/IEC 14496-3
    418         0x00, 0x00, 0x00, 0x00,
    419         0x00, 0x00, 0x00, 0x00,
    420         0x00, 0x00, 0x00, 0x00,
    421 
    422         0x05,
    423         // AudioSpecificInfo (with size prefix) follows
    424     };
    425 
    426     CHECK(asiSize < 128);
    427     size_t esdsSize = sizeof(kStaticESDS) + asiSize + 1;
    428     uint8_t *esds = new uint8_t[esdsSize];
    429     memcpy(esds, kStaticESDS, sizeof(kStaticESDS));
    430     uint8_t *ptr = esds + sizeof(kStaticESDS);
    431     *ptr++ = asiSize;
    432     memcpy(ptr, asi, asiSize);
    433 
    434     meta->setData(kKeyESDS, 0, esds, esdsSize);
    435 
    436     delete[] esds;
    437     esds = NULL;
    438 }
    439 
    440 void addVorbisCodecInfo(
    441         const sp<MetaData> &meta,
    442         const void *_codecPrivate, size_t codecPrivateSize) {
    443     // printf("vorbis private data follows:\n");
    444     // hexdump(_codecPrivate, codecPrivateSize);
    445 
    446     CHECK(codecPrivateSize >= 3);
    447 
    448     const uint8_t *codecPrivate = (const uint8_t *)_codecPrivate;
    449     CHECK(codecPrivate[0] == 0x02);
    450 
    451     size_t len1 = codecPrivate[1];
    452     size_t len2 = codecPrivate[2];
    453 
    454     CHECK(codecPrivateSize > 3 + len1 + len2);
    455 
    456     CHECK(codecPrivate[3] == 0x01);
    457     meta->setData(kKeyVorbisInfo, 0, &codecPrivate[3], len1);
    458 
    459     CHECK(codecPrivate[len1 + 3] == 0x03);
    460 
    461     CHECK(codecPrivate[len1 + len2 + 3] == 0x05);
    462     meta->setData(
    463             kKeyVorbisBooks, 0, &codecPrivate[len1 + len2 + 3],
    464             codecPrivateSize - len1 - len2 - 3);
    465 }
    466 
    467 void MatroskaExtractor::addTracks() {
    468     const mkvparser::Tracks *tracks = mSegment->GetTracks();
    469 
    470     for (size_t index = 0; index < tracks->GetTracksCount(); ++index) {
    471         const mkvparser::Track *track = tracks->GetTrackByIndex(index);
    472 
    473         const char *const codecID = track->GetCodecId();
    474         LOGV("codec id = %s", codecID);
    475         LOGV("codec name = %s", track->GetCodecNameAsUTF8());
    476 
    477         size_t codecPrivateSize;
    478         const unsigned char *codecPrivate =
    479             track->GetCodecPrivate(&codecPrivateSize);
    480 
    481         enum { VIDEO_TRACK = 1, AUDIO_TRACK = 2 };
    482 
    483         sp<MetaData> meta = new MetaData;
    484 
    485         switch (track->GetType()) {
    486             case VIDEO_TRACK:
    487             {
    488                 const mkvparser::VideoTrack *vtrack =
    489                     static_cast<const mkvparser::VideoTrack *>(track);
    490 
    491                 if (!strcmp("V_MPEG4/ISO/AVC", codecID)) {
    492                     meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
    493                     meta->setData(kKeyAVCC, 0, codecPrivate, codecPrivateSize);
    494                 } else if (!strcmp("V_VP8", codecID)) {
    495                     meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VPX);
    496                 } else {
    497                     continue;
    498                 }
    499 
    500                 meta->setInt32(kKeyWidth, vtrack->GetWidth());
    501                 meta->setInt32(kKeyHeight, vtrack->GetHeight());
    502                 break;
    503             }
    504 
    505             case AUDIO_TRACK:
    506             {
    507                 const mkvparser::AudioTrack *atrack =
    508                     static_cast<const mkvparser::AudioTrack *>(track);
    509 
    510                 if (!strcmp("A_AAC", codecID)) {
    511                     meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
    512                     CHECK(codecPrivateSize >= 2);
    513 
    514                     addESDSFromAudioSpecificInfo(
    515                             meta, codecPrivate, codecPrivateSize);
    516                 } else if (!strcmp("A_VORBIS", codecID)) {
    517                     meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS);
    518 
    519                     addVorbisCodecInfo(meta, codecPrivate, codecPrivateSize);
    520                 } else {
    521                     continue;
    522                 }
    523 
    524                 meta->setInt32(kKeySampleRate, atrack->GetSamplingRate());
    525                 meta->setInt32(kKeyChannelCount, atrack->GetChannels());
    526                 break;
    527             }
    528 
    529             default:
    530                 continue;
    531         }
    532 
    533         long long durationNs = mSegment->GetDuration();
    534         meta->setInt64(kKeyDuration, (durationNs + 500) / 1000);
    535 
    536         mTracks.push();
    537         TrackInfo *trackInfo = &mTracks.editItemAt(mTracks.size() - 1);
    538         trackInfo->mTrackNum = track->GetNumber();
    539         trackInfo->mMeta = meta;
    540     }
    541 }
    542 
    543 void MatroskaExtractor::findThumbnails() {
    544     for (size_t i = 0; i < mTracks.size(); ++i) {
    545         TrackInfo *info = &mTracks.editItemAt(i);
    546 
    547         const char *mime;
    548         CHECK(info->mMeta->findCString(kKeyMIMEType, &mime));
    549 
    550         if (strncasecmp(mime, "video/", 6)) {
    551             continue;
    552         }
    553 
    554         BlockIterator iter(mSegment, info->mTrackNum);
    555         int32_t i = 0;
    556         int64_t thumbnailTimeUs = 0;
    557         size_t maxBlockSize = 0;
    558         while (!iter.eos() && i < 20) {
    559             if (iter.block()->IsKey()) {
    560                 ++i;
    561 
    562                 size_t blockSize = iter.block()->GetSize();
    563                 if (blockSize > maxBlockSize) {
    564                     maxBlockSize = blockSize;
    565                     thumbnailTimeUs = iter.blockTimeUs();
    566                 }
    567             }
    568             iter.advance();
    569         }
    570         info->mMeta->setInt64(kKeyThumbnailTime, thumbnailTimeUs);
    571     }
    572 }
    573 
    574 sp<MetaData> MatroskaExtractor::getMetaData() {
    575     sp<MetaData> meta = new MetaData;
    576     meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MATROSKA);
    577 
    578     return meta;
    579 }
    580 
    581 bool SniffMatroska(
    582         const sp<DataSource> &source, String8 *mimeType, float *confidence,
    583         sp<AMessage> *) {
    584     DataSourceReader reader(source);
    585     mkvparser::EBMLHeader ebmlHeader;
    586     long long pos;
    587     if (ebmlHeader.Parse(&reader, pos) < 0) {
    588         return false;
    589     }
    590 
    591     mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_MATROSKA);
    592     *confidence = 0.6;
    593 
    594     return true;
    595 }
    596 
    597 }  // namespace android
    598