• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "avc_utils.h"
23 
24 #include <media/stagefright/foundation/ADebug.h>
25 #include <media/stagefright/foundation/AUtils.h>
26 #include <media/stagefright/foundation/ABuffer.h>
27 #include <media/stagefright/foundation/ColorUtils.h>
28 #include <media/stagefright/foundation/hexdump.h>
29 #include <media/stagefright/DataSource.h>
30 #include <media/stagefright/MediaBuffer.h>
31 #include <media/stagefright/MediaDefs.h>
32 #include <media/stagefright/MediaErrors.h>
33 #include <media/stagefright/MediaSource.h>
34 #include <media/stagefright/MetaData.h>
35 #include <media/stagefright/Utils.h>
36 #include <utils/String8.h>
37 
38 #include <inttypes.h>
39 
40 namespace android {
41 
42 struct DataSourceReader : public mkvparser::IMkvReader {
DataSourceReaderandroid::DataSourceReader43     explicit DataSourceReader(const sp<DataSource> &source)
44         : mSource(source) {
45     }
46 
Readandroid::DataSourceReader47     virtual int Read(long long position, long length, unsigned char* buffer) {
48         CHECK(position >= 0);
49         CHECK(length >= 0);
50 
51         if (length == 0) {
52             return 0;
53         }
54 
55         ssize_t n = mSource->readAt(position, buffer, length);
56 
57         if (n <= 0) {
58             return -1;
59         }
60 
61         return 0;
62     }
63 
Lengthandroid::DataSourceReader64     virtual int Length(long long* total, long long* available) {
65         off64_t size;
66         if (mSource->getSize(&size) != OK) {
67             *total = -1;
68             *available = (long long)((1ull << 63) - 1);
69 
70             return 0;
71         }
72 
73         if (total) {
74             *total = size;
75         }
76 
77         if (available) {
78             *available = size;
79         }
80 
81         return 0;
82     }
83 
84 private:
85     sp<DataSource> mSource;
86 
87     DataSourceReader(const DataSourceReader &);
88     DataSourceReader &operator=(const DataSourceReader &);
89 };
90 
91 ////////////////////////////////////////////////////////////////////////////////
92 
93 struct BlockIterator {
94     BlockIterator(MatroskaExtractor *extractor, unsigned long trackNum, unsigned long index);
95 
96     bool eos() const;
97 
98     void advance();
99     void reset();
100 
101     void seek(
102             int64_t seekTimeUs, bool isAudio,
103             int64_t *actualFrameTimeUs);
104 
105     const mkvparser::Block *block() const;
106     int64_t blockTimeUs() const;
107 
108 private:
109     MatroskaExtractor *mExtractor;
110     long long mTrackNum;
111     unsigned long mIndex;
112 
113     const mkvparser::Cluster *mCluster;
114     const mkvparser::BlockEntry *mBlockEntry;
115     long mBlockEntryIndex;
116 
117     void advance_l();
118 
119     BlockIterator(const BlockIterator &);
120     BlockIterator &operator=(const BlockIterator &);
121 };
122 
123 struct MatroskaSource : public MediaSource {
124     MatroskaSource(
125             const sp<MatroskaExtractor> &extractor, size_t index);
126 
127     virtual status_t start(MetaData *params);
128     virtual status_t stop();
129 
130     virtual sp<MetaData> getFormat();
131 
132     virtual status_t read(
133             MediaBuffer **buffer, const ReadOptions *options);
134 
135 protected:
136     virtual ~MatroskaSource();
137 
138 private:
139     enum Type {
140         AVC,
141         AAC,
142         OTHER
143     };
144 
145     sp<MatroskaExtractor> mExtractor;
146     size_t mTrackIndex;
147     Type mType;
148     bool mIsAudio;
149     BlockIterator mBlockIter;
150     ssize_t mNALSizeLen;  // for type AVC
151 
152     List<MediaBuffer *> mPendingFrames;
153 
154     status_t advance();
155 
156     status_t setWebmBlockCryptoInfo(MediaBuffer *mbuf);
157     status_t readBlock();
158     void clearPendingFrames();
159 
160     MatroskaSource(const MatroskaSource &);
161     MatroskaSource &operator=(const MatroskaSource &);
162 };
163 
getTrack() const164 const mkvparser::Track* MatroskaExtractor::TrackInfo::getTrack() const {
165     return mExtractor->mSegment->GetTracks()->GetTrackByNumber(mTrackNum);
166 }
167 
168 // This function does exactly the same as mkvparser::Cues::Find, except that it
169 // searches in our own track based vectors. We should not need this once mkvparser
170 // adds the same functionality.
find(long long timeNs) const171 const mkvparser::CuePoint::TrackPosition *MatroskaExtractor::TrackInfo::find(
172         long long timeNs) const {
173     ALOGV("mCuePoints.size %zu", mCuePoints.size());
174     if (mCuePoints.empty()) {
175         return NULL;
176     }
177 
178     const mkvparser::CuePoint* cp = mCuePoints.itemAt(0);
179     const mkvparser::Track* track = getTrack();
180     if (timeNs <= cp->GetTime(mExtractor->mSegment)) {
181         return cp->Find(track);
182     }
183 
184     // Binary searches through relevant cues; assumes cues are ordered by timecode.
185     // If we do detect out-of-order cues, return NULL.
186     size_t lo = 0;
187     size_t hi = mCuePoints.size();
188     while (lo < hi) {
189         const size_t mid = lo + (hi - lo) / 2;
190         const mkvparser::CuePoint* const midCp = mCuePoints.itemAt(mid);
191         const long long cueTimeNs = midCp->GetTime(mExtractor->mSegment);
192         if (cueTimeNs <= timeNs) {
193             lo = mid + 1;
194         } else {
195             hi = mid;
196         }
197     }
198 
199     if (lo == 0) {
200         return NULL;
201     }
202 
203     cp = mCuePoints.itemAt(lo - 1);
204     if (cp->GetTime(mExtractor->mSegment) > timeNs) {
205         return NULL;
206     }
207 
208     return cp->Find(track);
209 }
210 
MatroskaSource(const sp<MatroskaExtractor> & extractor,size_t index)211 MatroskaSource::MatroskaSource(
212         const sp<MatroskaExtractor> &extractor, size_t index)
213     : mExtractor(extractor),
214       mTrackIndex(index),
215       mType(OTHER),
216       mIsAudio(false),
217       mBlockIter(mExtractor.get(),
218                  mExtractor->mTracks.itemAt(index).mTrackNum,
219                  index),
220       mNALSizeLen(-1) {
221     sp<MetaData> meta = mExtractor->mTracks.itemAt(index).mMeta;
222 
223     const char *mime;
224     CHECK(meta->findCString(kKeyMIMEType, &mime));
225 
226     mIsAudio = !strncasecmp("audio/", mime, 6);
227 
228     if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
229         mType = AVC;
230 
231         uint32_t dummy;
232         const uint8_t *avcc;
233         size_t avccSize;
234         int32_t nalSizeLen = 0;
235         if (meta->findInt32(kKeyNalLengthSize, &nalSizeLen)) {
236             if (nalSizeLen >= 0 && nalSizeLen <= 4) {
237                 mNALSizeLen = nalSizeLen;
238             }
239         } else if (meta->findData(kKeyAVCC, &dummy, (const void **)&avcc, &avccSize)
240                 && avccSize >= 5u) {
241             mNALSizeLen = 1 + (avcc[4] & 3);
242             ALOGV("mNALSizeLen = %zd", mNALSizeLen);
243         } else {
244             ALOGE("No mNALSizeLen");
245         }
246     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
247         mType = AAC;
248     }
249 }
250 
~MatroskaSource()251 MatroskaSource::~MatroskaSource() {
252     clearPendingFrames();
253 }
254 
start(MetaData *)255 status_t MatroskaSource::start(MetaData * /* params */) {
256     if (mType == AVC && mNALSizeLen < 0) {
257         return ERROR_MALFORMED;
258     }
259 
260     mBlockIter.reset();
261 
262     return OK;
263 }
264 
stop()265 status_t MatroskaSource::stop() {
266     clearPendingFrames();
267 
268     return OK;
269 }
270 
getFormat()271 sp<MetaData> MatroskaSource::getFormat() {
272     return mExtractor->mTracks.itemAt(mTrackIndex).mMeta;
273 }
274 
275 ////////////////////////////////////////////////////////////////////////////////
276 
BlockIterator(MatroskaExtractor * extractor,unsigned long trackNum,unsigned long index)277 BlockIterator::BlockIterator(
278         MatroskaExtractor *extractor, unsigned long trackNum, unsigned long index)
279     : mExtractor(extractor),
280       mTrackNum(trackNum),
281       mIndex(index),
282       mCluster(NULL),
283       mBlockEntry(NULL),
284       mBlockEntryIndex(0) {
285     reset();
286 }
287 
eos() const288 bool BlockIterator::eos() const {
289     return mCluster == NULL || mCluster->EOS();
290 }
291 
advance()292 void BlockIterator::advance() {
293     Mutex::Autolock autoLock(mExtractor->mLock);
294     advance_l();
295 }
296 
advance_l()297 void BlockIterator::advance_l() {
298     for (;;) {
299         long res = mCluster->GetEntry(mBlockEntryIndex, mBlockEntry);
300         ALOGV("GetEntry returned %ld", res);
301 
302         long long pos;
303         long len;
304         if (res < 0) {
305             // Need to parse this cluster some more
306 
307             CHECK_EQ(res, mkvparser::E_BUFFER_NOT_FULL);
308 
309             res = mCluster->Parse(pos, len);
310             ALOGV("Parse returned %ld", res);
311 
312             if (res < 0) {
313                 // I/O error
314 
315                 ALOGE("Cluster::Parse returned result %ld", res);
316 
317                 mCluster = NULL;
318                 break;
319             }
320 
321             continue;
322         } else if (res == 0) {
323             // We're done with this cluster
324 
325             const mkvparser::Cluster *nextCluster;
326             res = mExtractor->mSegment->ParseNext(
327                     mCluster, nextCluster, pos, len);
328             ALOGV("ParseNext returned %ld", res);
329 
330             if (res != 0) {
331                 // EOF or error
332 
333                 mCluster = NULL;
334                 break;
335             }
336 
337             CHECK_EQ(res, 0);
338             CHECK(nextCluster != NULL);
339             CHECK(!nextCluster->EOS());
340 
341             mCluster = nextCluster;
342 
343             res = mCluster->Parse(pos, len);
344             ALOGV("Parse (2) returned %ld", res);
345             CHECK_GE(res, 0);
346 
347             mBlockEntryIndex = 0;
348             continue;
349         }
350 
351         CHECK(mBlockEntry != NULL);
352         CHECK(mBlockEntry->GetBlock() != NULL);
353         ++mBlockEntryIndex;
354 
355         if (mBlockEntry->GetBlock()->GetTrackNumber() == mTrackNum) {
356             break;
357         }
358     }
359 }
360 
reset()361 void BlockIterator::reset() {
362     Mutex::Autolock autoLock(mExtractor->mLock);
363 
364     mCluster = mExtractor->mSegment->GetFirst();
365     mBlockEntry = NULL;
366     mBlockEntryIndex = 0;
367 
368     do {
369         advance_l();
370     } while (!eos() && block()->GetTrackNumber() != mTrackNum);
371 }
372 
seek(int64_t seekTimeUs,bool isAudio,int64_t * actualFrameTimeUs)373 void BlockIterator::seek(
374         int64_t seekTimeUs, bool isAudio,
375         int64_t *actualFrameTimeUs) {
376     Mutex::Autolock autoLock(mExtractor->mLock);
377 
378     *actualFrameTimeUs = -1ll;
379 
380     if (seekTimeUs > INT64_MAX / 1000ll ||
381             seekTimeUs < INT64_MIN / 1000ll ||
382             (mExtractor->mSeekPreRollNs > 0 &&
383                     (seekTimeUs * 1000ll) < INT64_MIN + mExtractor->mSeekPreRollNs) ||
384             (mExtractor->mSeekPreRollNs < 0 &&
385                     (seekTimeUs * 1000ll) > INT64_MAX + mExtractor->mSeekPreRollNs)) {
386         ALOGE("cannot seek to %lld", (long long) seekTimeUs);
387         return;
388     }
389 
390     const int64_t seekTimeNs = seekTimeUs * 1000ll - mExtractor->mSeekPreRollNs;
391 
392     mkvparser::Segment* const pSegment = mExtractor->mSegment;
393 
394     // Special case the 0 seek to avoid loading Cues when the application
395     // extraneously seeks to 0 before playing.
396     if (seekTimeNs <= 0) {
397         ALOGV("Seek to beginning: %" PRId64, seekTimeUs);
398         mCluster = pSegment->GetFirst();
399         mBlockEntryIndex = 0;
400         do {
401             advance_l();
402         } while (!eos() && block()->GetTrackNumber() != mTrackNum);
403         return;
404     }
405 
406     ALOGV("Seeking to: %" PRId64, seekTimeUs);
407 
408     // If the Cues have not been located then find them.
409     const mkvparser::Cues* pCues = pSegment->GetCues();
410     const mkvparser::SeekHead* pSH = pSegment->GetSeekHead();
411     if (!pCues && pSH) {
412         const size_t count = pSH->GetCount();
413         const mkvparser::SeekHead::Entry* pEntry;
414         ALOGV("No Cues yet");
415 
416         for (size_t index = 0; index < count; index++) {
417             pEntry = pSH->GetEntry(index);
418 
419             if (pEntry->id == 0x0C53BB6B) { // Cues ID
420                 long len; long long pos;
421                 pSegment->ParseCues(pEntry->pos, pos, len);
422                 pCues = pSegment->GetCues();
423                 ALOGV("Cues found");
424                 break;
425             }
426         }
427 
428         if (!pCues) {
429             ALOGE("No Cues in file");
430             return;
431         }
432     }
433     else if (!pSH) {
434         ALOGE("No SeekHead");
435         return;
436     }
437 
438     const mkvparser::CuePoint* pCP;
439     mkvparser::Tracks const *pTracks = pSegment->GetTracks();
440     while (!pCues->DoneParsing()) {
441         pCues->LoadCuePoint();
442         pCP = pCues->GetLast();
443         CHECK(pCP);
444 
445         size_t trackCount = mExtractor->mTracks.size();
446         for (size_t index = 0; index < trackCount; ++index) {
447             MatroskaExtractor::TrackInfo& track = mExtractor->mTracks.editItemAt(index);
448             const mkvparser::Track *pTrack = pTracks->GetTrackByNumber(track.mTrackNum);
449             if (pTrack && pTrack->GetType() == 1 && pCP->Find(pTrack)) { // VIDEO_TRACK
450                 track.mCuePoints.push_back(pCP);
451             }
452         }
453 
454         if (pCP->GetTime(pSegment) >= seekTimeNs) {
455             ALOGV("Parsed past relevant Cue");
456             break;
457         }
458     }
459 
460     const mkvparser::CuePoint::TrackPosition *pTP = NULL;
461     const mkvparser::Track *thisTrack = pTracks->GetTrackByNumber(mTrackNum);
462     if (thisTrack->GetType() == 1) { // video
463         MatroskaExtractor::TrackInfo& track = mExtractor->mTracks.editItemAt(mIndex);
464         pTP = track.find(seekTimeNs);
465     } else {
466         // The Cue index is built around video keyframes
467         unsigned long int trackCount = pTracks->GetTracksCount();
468         for (size_t index = 0; index < trackCount; ++index) {
469             const mkvparser::Track *pTrack = pTracks->GetTrackByIndex(index);
470             if (pTrack && pTrack->GetType() == 1 && pCues->Find(seekTimeNs, pTrack, pCP, pTP)) {
471                 ALOGV("Video track located at %zu", index);
472                 break;
473             }
474         }
475     }
476 
477 
478     // Always *search* based on the video track, but finalize based on mTrackNum
479     if (!pTP) {
480         ALOGE("Did not locate the video track for seeking");
481         return;
482     }
483 
484     mCluster = pSegment->FindOrPreloadCluster(pTP->m_pos);
485 
486     CHECK(mCluster);
487     CHECK(!mCluster->EOS());
488 
489     // mBlockEntryIndex starts at 0 but m_block starts at 1
490     CHECK_GT(pTP->m_block, 0);
491     mBlockEntryIndex = pTP->m_block - 1;
492 
493     for (;;) {
494         advance_l();
495 
496         if (eos()) break;
497 
498         if (isAudio || block()->IsKey()) {
499             // Accept the first key frame
500             int64_t frameTimeUs = (block()->GetTime(mCluster) + 500LL) / 1000LL;
501             if (thisTrack->GetType() == 1 || frameTimeUs >= seekTimeUs) {
502                 *actualFrameTimeUs = frameTimeUs;
503                 ALOGV("Requested seek point: %" PRId64 " actual: %" PRId64,
504                       seekTimeUs, *actualFrameTimeUs);
505                 break;
506             }
507         }
508     }
509 }
510 
block() const511 const mkvparser::Block *BlockIterator::block() const {
512     CHECK(!eos());
513 
514     return mBlockEntry->GetBlock();
515 }
516 
blockTimeUs() const517 int64_t BlockIterator::blockTimeUs() const {
518     if (mCluster == NULL || mBlockEntry == NULL) {
519         return -1;
520     }
521     return (mBlockEntry->GetBlock()->GetTime(mCluster) + 500ll) / 1000ll;
522 }
523 
524 ////////////////////////////////////////////////////////////////////////////////
525 
U24_AT(const uint8_t * ptr)526 static unsigned U24_AT(const uint8_t *ptr) {
527     return ptr[0] << 16 | ptr[1] << 8 | ptr[2];
528 }
529 
clearPendingFrames()530 void MatroskaSource::clearPendingFrames() {
531     while (!mPendingFrames.empty()) {
532         MediaBuffer *frame = *mPendingFrames.begin();
533         mPendingFrames.erase(mPendingFrames.begin());
534 
535         frame->release();
536         frame = NULL;
537     }
538 }
539 
setWebmBlockCryptoInfo(MediaBuffer * mbuf)540 status_t MatroskaSource::setWebmBlockCryptoInfo(MediaBuffer *mbuf) {
541     if (mbuf->range_length() < 1 || mbuf->range_length() - 1 > INT32_MAX) {
542         // 1-byte signal
543         return ERROR_MALFORMED;
544     }
545 
546     const uint8_t *data = (const uint8_t *)mbuf->data() + mbuf->range_offset();
547     bool blockEncrypted = data[0] & 0x1;
548     if (blockEncrypted && mbuf->range_length() < 9) {
549         // 1-byte signal + 8-byte IV
550         return ERROR_MALFORMED;
551     }
552 
553     sp<MetaData> meta = mbuf->meta_data();
554     if (blockEncrypted) {
555         /*
556          *  0                   1                   2                   3
557          *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
558          *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
559          *  |  Signal Byte  |                                               |
560          *  +-+-+-+-+-+-+-+-+             IV                                |
561          *  |                                                               |
562          *  |               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
563          *  |               |                                               |
564          *  |-+-+-+-+-+-+-+-+                                               |
565          *  :               Bytes 1..N of encrypted frame                   :
566          *  |                                                               |
567          *  |                                                               |
568          *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
569          */
570         int32_t plainSizes[] = { 0 };
571         int32_t encryptedSizes[] = { static_cast<int32_t>(mbuf->range_length() - 9) };
572         uint8_t ctrCounter[16] = { 0 };
573         uint32_t type;
574         const uint8_t *keyId;
575         size_t keyIdSize;
576         sp<MetaData> trackMeta = mExtractor->mTracks.itemAt(mTrackIndex).mMeta;
577         CHECK(trackMeta->findData(kKeyCryptoKey, &type, (const void **)&keyId, &keyIdSize));
578         meta->setData(kKeyCryptoKey, 0, keyId, keyIdSize);
579         memcpy(ctrCounter, data + 1, 8);
580         meta->setData(kKeyCryptoIV, 0, ctrCounter, 16);
581         meta->setData(kKeyPlainSizes, 0, plainSizes, sizeof(plainSizes));
582         meta->setData(kKeyEncryptedSizes, 0, encryptedSizes, sizeof(encryptedSizes));
583         mbuf->set_range(9, mbuf->range_length() - 9);
584     } else {
585         /*
586          *  0                   1                   2                   3
587          *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
588          *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
589          *  |  Signal Byte  |                                               |
590          *  +-+-+-+-+-+-+-+-+                                               |
591          *  :               Bytes 1..N of unencrypted frame                 :
592          *  |                                                               |
593          *  |                                                               |
594          *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
595          */
596         int32_t plainSizes[] = { static_cast<int32_t>(mbuf->range_length() - 1) };
597         int32_t encryptedSizes[] = { 0 };
598         meta->setData(kKeyPlainSizes, 0, plainSizes, sizeof(plainSizes));
599         meta->setData(kKeyEncryptedSizes, 0, encryptedSizes, sizeof(encryptedSizes));
600         mbuf->set_range(1, mbuf->range_length() - 1);
601     }
602 
603     return OK;
604 }
605 
readBlock()606 status_t MatroskaSource::readBlock() {
607     CHECK(mPendingFrames.empty());
608 
609     if (mBlockIter.eos()) {
610         return ERROR_END_OF_STREAM;
611     }
612 
613     const mkvparser::Block *block = mBlockIter.block();
614 
615     int64_t timeUs = mBlockIter.blockTimeUs();
616 
617     for (int i = 0; i < block->GetFrameCount(); ++i) {
618         MatroskaExtractor::TrackInfo *trackInfo = &mExtractor->mTracks.editItemAt(mTrackIndex);
619         const mkvparser::Block::Frame &frame = block->GetFrame(i);
620         size_t len = frame.len;
621         if (SIZE_MAX - len < trackInfo->mHeaderLen) {
622             return ERROR_MALFORMED;
623         }
624 
625         len += trackInfo->mHeaderLen;
626         MediaBuffer *mbuf = new MediaBuffer(len);
627         uint8_t *data = static_cast<uint8_t *>(mbuf->data());
628         if (trackInfo->mHeader) {
629             memcpy(data, trackInfo->mHeader, trackInfo->mHeaderLen);
630         }
631 
632         mbuf->meta_data()->setInt64(kKeyTime, timeUs);
633         mbuf->meta_data()->setInt32(kKeyIsSyncFrame, block->IsKey());
634 
635         status_t err = frame.Read(mExtractor->mReader, data + trackInfo->mHeaderLen);
636         if (err == OK
637                 && mExtractor->mIsWebm
638                 && trackInfo->mEncrypted) {
639             err = setWebmBlockCryptoInfo(mbuf);
640         }
641 
642         if (err != OK) {
643             mPendingFrames.clear();
644 
645             mBlockIter.advance();
646             mbuf->release();
647             return err;
648         }
649 
650         mPendingFrames.push_back(mbuf);
651     }
652 
653     mBlockIter.advance();
654 
655     return OK;
656 }
657 
read(MediaBuffer ** out,const ReadOptions * options)658 status_t MatroskaSource::read(
659         MediaBuffer **out, const ReadOptions *options) {
660     *out = NULL;
661 
662     int64_t targetSampleTimeUs = -1ll;
663 
664     int64_t seekTimeUs;
665     ReadOptions::SeekMode mode;
666     if (options && options->getSeekTo(&seekTimeUs, &mode)
667             && !mExtractor->isLiveStreaming()) {
668         clearPendingFrames();
669 
670         // The audio we want is located by using the Cues to seek the video
671         // stream to find the target Cluster then iterating to finalize for
672         // audio.
673         int64_t actualFrameTimeUs;
674         mBlockIter.seek(seekTimeUs, mIsAudio, &actualFrameTimeUs);
675 
676         if (mode == ReadOptions::SEEK_CLOSEST) {
677             targetSampleTimeUs = actualFrameTimeUs;
678         }
679     }
680 
681     while (mPendingFrames.empty()) {
682         status_t err = readBlock();
683 
684         if (err != OK) {
685             clearPendingFrames();
686 
687             return err;
688         }
689     }
690 
691     MediaBuffer *frame = *mPendingFrames.begin();
692     mPendingFrames.erase(mPendingFrames.begin());
693 
694     if (mType != AVC || mNALSizeLen == 0) {
695         if (targetSampleTimeUs >= 0ll) {
696             frame->meta_data()->setInt64(
697                     kKeyTargetTime, targetSampleTimeUs);
698         }
699 
700         *out = frame;
701 
702         return OK;
703     }
704 
705     // Each input frame contains one or more NAL fragments, each fragment
706     // is prefixed by mNALSizeLen bytes giving the fragment length,
707     // followed by a corresponding number of bytes containing the fragment.
708     // We output all these fragments into a single large buffer separated
709     // by startcodes (0x00 0x00 0x00 0x01).
710     //
711     // When mNALSizeLen is 0, we assume the data is already in the format
712     // desired.
713 
714     const uint8_t *srcPtr =
715         (const uint8_t *)frame->data() + frame->range_offset();
716 
717     size_t srcSize = frame->range_length();
718 
719     size_t dstSize = 0;
720     MediaBuffer *buffer = NULL;
721     uint8_t *dstPtr = NULL;
722 
723     for (int32_t pass = 0; pass < 2; ++pass) {
724         size_t srcOffset = 0;
725         size_t dstOffset = 0;
726         while (srcOffset + mNALSizeLen <= srcSize) {
727             size_t NALsize;
728             switch (mNALSizeLen) {
729                 case 1: NALsize = srcPtr[srcOffset]; break;
730                 case 2: NALsize = U16_AT(srcPtr + srcOffset); break;
731                 case 3: NALsize = U24_AT(srcPtr + srcOffset); break;
732                 case 4: NALsize = U32_AT(srcPtr + srcOffset); break;
733                 default:
734                     TRESPASS();
735             }
736 
737             if (srcOffset + mNALSizeLen + NALsize <= srcOffset + mNALSizeLen) {
738                 frame->release();
739                 frame = NULL;
740 
741                 return ERROR_MALFORMED;
742             } else if (srcOffset + mNALSizeLen + NALsize > srcSize) {
743                 break;
744             }
745 
746             if (pass == 1) {
747                 memcpy(&dstPtr[dstOffset], "\x00\x00\x00\x01", 4);
748 
749                 if (frame != buffer) {
750                     memcpy(&dstPtr[dstOffset + 4],
751                            &srcPtr[srcOffset + mNALSizeLen],
752                            NALsize);
753                 }
754             }
755 
756             dstOffset += 4;  // 0x00 00 00 01
757             dstOffset += NALsize;
758 
759             srcOffset += mNALSizeLen + NALsize;
760         }
761 
762         if (srcOffset < srcSize) {
763             // There were trailing bytes or not enough data to complete
764             // a fragment.
765 
766             frame->release();
767             frame = NULL;
768 
769             return ERROR_MALFORMED;
770         }
771 
772         if (pass == 0) {
773             dstSize = dstOffset;
774 
775             if (dstSize == srcSize && mNALSizeLen == 4) {
776                 // In this special case we can re-use the input buffer by substituting
777                 // each 4-byte nal size with a 4-byte start code
778                 buffer = frame;
779             } else {
780                 buffer = new MediaBuffer(dstSize);
781             }
782 
783             int64_t timeUs;
784             CHECK(frame->meta_data()->findInt64(kKeyTime, &timeUs));
785             int32_t isSync;
786             CHECK(frame->meta_data()->findInt32(kKeyIsSyncFrame, &isSync));
787 
788             buffer->meta_data()->setInt64(kKeyTime, timeUs);
789             buffer->meta_data()->setInt32(kKeyIsSyncFrame, isSync);
790 
791             dstPtr = (uint8_t *)buffer->data();
792         }
793     }
794 
795     if (frame != buffer) {
796         frame->release();
797         frame = NULL;
798     }
799 
800     if (targetSampleTimeUs >= 0ll) {
801         buffer->meta_data()->setInt64(
802                 kKeyTargetTime, targetSampleTimeUs);
803     }
804 
805     *out = buffer;
806 
807     return OK;
808 }
809 
810 ////////////////////////////////////////////////////////////////////////////////
811 
MatroskaExtractor(const sp<DataSource> & source)812 MatroskaExtractor::MatroskaExtractor(const sp<DataSource> &source)
813     : mDataSource(source),
814       mReader(new DataSourceReader(mDataSource)),
815       mSegment(NULL),
816       mExtractedThumbnails(false),
817       mIsWebm(false),
818       mSeekPreRollNs(0) {
819     off64_t size;
820     mIsLiveStreaming =
821         (mDataSource->flags()
822             & (DataSource::kWantsPrefetching
823                 | DataSource::kIsCachingDataSource))
824         && mDataSource->getSize(&size) != OK;
825 
826     mkvparser::EBMLHeader ebmlHeader;
827     long long pos;
828     if (ebmlHeader.Parse(mReader, pos) < 0) {
829         return;
830     }
831 
832     if (ebmlHeader.m_docType && !strcmp("webm", ebmlHeader.m_docType)) {
833         mIsWebm = true;
834     }
835 
836     long long ret =
837         mkvparser::Segment::CreateInstance(mReader, pos, mSegment);
838 
839     if (ret) {
840         CHECK(mSegment == NULL);
841         return;
842     }
843 
844     // from mkvparser::Segment::Load(), but stop at first cluster
845     ret = mSegment->ParseHeaders();
846     if (ret == 0) {
847         long len;
848         ret = mSegment->LoadCluster(pos, len);
849         if (ret >= 1) {
850             // no more clusters
851             ret = 0;
852         }
853     } else if (ret > 0) {
854         ret = mkvparser::E_BUFFER_NOT_FULL;
855     }
856 
857     if (ret < 0) {
858         ALOGW("Corrupt %s source: %s", mIsWebm ? "webm" : "matroska",
859                 uriDebugString(mDataSource->getUri()).c_str());
860         delete mSegment;
861         mSegment = NULL;
862         return;
863     }
864 
865 #if 0
866     const mkvparser::SegmentInfo *info = mSegment->GetInfo();
867     ALOGI("muxing app: %s, writing app: %s",
868          info->GetMuxingAppAsUTF8(),
869          info->GetWritingAppAsUTF8());
870 #endif
871 
872     addTracks();
873 }
874 
~MatroskaExtractor()875 MatroskaExtractor::~MatroskaExtractor() {
876     delete mSegment;
877     mSegment = NULL;
878 
879     delete mReader;
880     mReader = NULL;
881 }
882 
countTracks()883 size_t MatroskaExtractor::countTracks() {
884     return mTracks.size();
885 }
886 
getTrack(size_t index)887 sp<IMediaSource> MatroskaExtractor::getTrack(size_t index) {
888     if (index >= mTracks.size()) {
889         return NULL;
890     }
891 
892     return new MatroskaSource(this, index);
893 }
894 
getTrackMetaData(size_t index,uint32_t flags)895 sp<MetaData> MatroskaExtractor::getTrackMetaData(
896         size_t index, uint32_t flags) {
897     if (index >= mTracks.size()) {
898         return NULL;
899     }
900 
901     if ((flags & kIncludeExtensiveMetaData) && !mExtractedThumbnails
902             && !isLiveStreaming()) {
903         findThumbnails();
904         mExtractedThumbnails = true;
905     }
906 
907     return mTracks.itemAt(index).mMeta;
908 }
909 
isLiveStreaming() const910 bool MatroskaExtractor::isLiveStreaming() const {
911     return mIsLiveStreaming;
912 }
913 
bytesForSize(size_t size)914 static int bytesForSize(size_t size) {
915     // use at most 28 bits (4 times 7)
916     CHECK(size <= 0xfffffff);
917 
918     if (size > 0x1fffff) {
919         return 4;
920     } else if (size > 0x3fff) {
921         return 3;
922     } else if (size > 0x7f) {
923         return 2;
924     }
925     return 1;
926 }
927 
storeSize(uint8_t * data,size_t & idx,size_t size)928 static void storeSize(uint8_t *data, size_t &idx, size_t size) {
929     int numBytes = bytesForSize(size);
930     idx += numBytes;
931 
932     data += idx;
933     size_t next = 0;
934     while (numBytes--) {
935         *--data = (size & 0x7f) | next;
936         size >>= 7;
937         next = 0x80;
938     }
939 }
940 
addESDSFromCodecPrivate(const sp<MetaData> & meta,bool isAudio,const void * priv,size_t privSize)941 static void addESDSFromCodecPrivate(
942         const sp<MetaData> &meta,
943         bool isAudio, const void *priv, size_t privSize) {
944 
945     int privSizeBytesRequired = bytesForSize(privSize);
946     int esdsSize2 = 14 + privSizeBytesRequired + privSize;
947     int esdsSize2BytesRequired = bytesForSize(esdsSize2);
948     int esdsSize1 = 4 + esdsSize2BytesRequired + esdsSize2;
949     int esdsSize1BytesRequired = bytesForSize(esdsSize1);
950     size_t esdsSize = 1 + esdsSize1BytesRequired + esdsSize1;
951     uint8_t *esds = new uint8_t[esdsSize];
952 
953     size_t idx = 0;
954     esds[idx++] = 0x03;
955     storeSize(esds, idx, esdsSize1);
956     esds[idx++] = 0x00; // ES_ID
957     esds[idx++] = 0x00; // ES_ID
958     esds[idx++] = 0x00; // streamDependenceFlag, URL_Flag, OCRstreamFlag
959     esds[idx++] = 0x04;
960     storeSize(esds, idx, esdsSize2);
961     esds[idx++] = isAudio ? 0x40   // Audio ISO/IEC 14496-3
962                           : 0x20;  // Visual ISO/IEC 14496-2
963     for (int i = 0; i < 12; i++) {
964         esds[idx++] = 0x00;
965     }
966     esds[idx++] = 0x05;
967     storeSize(esds, idx, privSize);
968     memcpy(esds + idx, priv, privSize);
969 
970     meta->setData(kKeyESDS, 0, esds, esdsSize);
971 
972     delete[] esds;
973     esds = NULL;
974 }
975 
addVorbisCodecInfo(const sp<MetaData> & meta,const void * _codecPrivate,size_t codecPrivateSize)976 status_t addVorbisCodecInfo(
977         const sp<MetaData> &meta,
978         const void *_codecPrivate, size_t codecPrivateSize) {
979     // hexdump(_codecPrivate, codecPrivateSize);
980 
981     if (codecPrivateSize < 1) {
982         return ERROR_MALFORMED;
983     }
984 
985     const uint8_t *codecPrivate = (const uint8_t *)_codecPrivate;
986 
987     if (codecPrivate[0] != 0x02) {
988         return ERROR_MALFORMED;
989     }
990 
991     // codecInfo starts with two lengths, len1 and len2, that are
992     // "Xiph-style-lacing encoded"...
993 
994     size_t offset = 1;
995     size_t len1 = 0;
996     while (offset < codecPrivateSize && codecPrivate[offset] == 0xff) {
997         if (len1 > (SIZE_MAX - 0xff)) {
998             return ERROR_MALFORMED; // would overflow
999         }
1000         len1 += 0xff;
1001         ++offset;
1002     }
1003     if (offset >= codecPrivateSize) {
1004         return ERROR_MALFORMED;
1005     }
1006     if (len1 > (SIZE_MAX - codecPrivate[offset])) {
1007         return ERROR_MALFORMED; // would overflow
1008     }
1009     len1 += codecPrivate[offset++];
1010 
1011     size_t len2 = 0;
1012     while (offset < codecPrivateSize && codecPrivate[offset] == 0xff) {
1013         if (len2 > (SIZE_MAX - 0xff)) {
1014             return ERROR_MALFORMED; // would overflow
1015         }
1016         len2 += 0xff;
1017         ++offset;
1018     }
1019     if (offset >= codecPrivateSize) {
1020         return ERROR_MALFORMED;
1021     }
1022     if (len2 > (SIZE_MAX - codecPrivate[offset])) {
1023         return ERROR_MALFORMED; // would overflow
1024     }
1025     len2 += codecPrivate[offset++];
1026 
1027     if (len1 > SIZE_MAX - len2 || offset > SIZE_MAX - (len1 + len2) ||
1028             codecPrivateSize < offset + len1 + len2) {
1029         return ERROR_MALFORMED;
1030     }
1031 
1032     if (codecPrivate[offset] != 0x01) {
1033         return ERROR_MALFORMED;
1034     }
1035     meta->setData(kKeyVorbisInfo, 0, &codecPrivate[offset], len1);
1036 
1037     offset += len1;
1038     if (codecPrivate[offset] != 0x03) {
1039         return ERROR_MALFORMED;
1040     }
1041 
1042     offset += len2;
1043     if (codecPrivate[offset] != 0x05) {
1044         return ERROR_MALFORMED;
1045     }
1046 
1047     meta->setData(
1048             kKeyVorbisBooks, 0, &codecPrivate[offset],
1049             codecPrivateSize - offset);
1050 
1051     return OK;
1052 }
1053 
synthesizeAVCC(TrackInfo * trackInfo,size_t index)1054 status_t MatroskaExtractor::synthesizeAVCC(TrackInfo *trackInfo, size_t index) {
1055     BlockIterator iter(this, trackInfo->mTrackNum, index);
1056     if (iter.eos()) {
1057         return ERROR_MALFORMED;
1058     }
1059 
1060     const mkvparser::Block *block = iter.block();
1061     if (block->GetFrameCount() <= 0) {
1062         return ERROR_MALFORMED;
1063     }
1064 
1065     const mkvparser::Block::Frame &frame = block->GetFrame(0);
1066     sp<ABuffer> abuf = new ABuffer(frame.len);
1067     long n = frame.Read(mReader, abuf->data());
1068     if (n != 0) {
1069         return ERROR_MALFORMED;
1070     }
1071 
1072     sp<MetaData> avcMeta = MakeAVCCodecSpecificData(abuf);
1073     if (avcMeta == NULL) {
1074         return ERROR_MALFORMED;
1075     }
1076 
1077     // Override the synthesized nal length size, which is arbitrary
1078     avcMeta->setInt32(kKeyNalLengthSize, 0);
1079     trackInfo->mMeta = avcMeta;
1080     return OK;
1081 }
1082 
isValidInt32ColourValue(long long value)1083 static inline bool isValidInt32ColourValue(long long value) {
1084     return value != mkvparser::Colour::kValueNotPresent
1085             && value >= INT32_MIN
1086             && value <= INT32_MAX;
1087 }
1088 
isValidUint16ColourValue(long long value)1089 static inline bool isValidUint16ColourValue(long long value) {
1090     return value != mkvparser::Colour::kValueNotPresent
1091             && value >= 0
1092             && value <= UINT16_MAX;
1093 }
1094 
isValidPrimary(const mkvparser::PrimaryChromaticity * primary)1095 static inline bool isValidPrimary(const mkvparser::PrimaryChromaticity *primary) {
1096     return primary != NULL && primary->x >= 0 && primary->x <= 1
1097              && primary->y >= 0 && primary->y <= 1;
1098 }
1099 
getColorInformation(const mkvparser::VideoTrack * vtrack,sp<MetaData> & meta)1100 void MatroskaExtractor::getColorInformation(
1101         const mkvparser::VideoTrack *vtrack, sp<MetaData> &meta) {
1102     const mkvparser::Colour *color = vtrack->GetColour();
1103     if (color == NULL) {
1104         return;
1105     }
1106 
1107     // Color Aspects
1108     {
1109         int32_t primaries = 2; // ISO unspecified
1110         int32_t transfer = 2; // ISO unspecified
1111         int32_t coeffs = 2; // ISO unspecified
1112         bool fullRange = false; // default
1113         bool rangeSpecified = false;
1114 
1115         if (isValidInt32ColourValue(color->primaries)) {
1116             primaries = color->primaries;
1117         }
1118         if (isValidInt32ColourValue(color->transfer_characteristics)) {
1119             transfer = color->transfer_characteristics;
1120         }
1121         if (isValidInt32ColourValue(color->matrix_coefficients)) {
1122             coeffs = color->matrix_coefficients;
1123         }
1124         if (color->range != mkvparser::Colour::kValueNotPresent
1125                 && color->range != 0 /* MKV unspecified */) {
1126             // We only support MKV broadcast range (== limited) and full range.
1127             // We treat all other value as the default limited range.
1128             fullRange = color->range == 2 /* MKV fullRange */;
1129             rangeSpecified = true;
1130         }
1131 
1132         ColorAspects aspects;
1133         ColorUtils::convertIsoColorAspectsToCodecAspects(
1134                 primaries, transfer, coeffs, fullRange, aspects);
1135         meta->setInt32(kKeyColorPrimaries, aspects.mPrimaries);
1136         meta->setInt32(kKeyTransferFunction, aspects.mTransfer);
1137         meta->setInt32(kKeyColorMatrix, aspects.mMatrixCoeffs);
1138         meta->setInt32(
1139                 kKeyColorRange, rangeSpecified ? aspects.mRange : ColorAspects::RangeUnspecified);
1140     }
1141 
1142     // HDR Static Info
1143     {
1144         HDRStaticInfo info, nullInfo; // nullInfo is a fully unspecified static info
1145         memset(&info, 0, sizeof(info));
1146         memset(&nullInfo, 0, sizeof(nullInfo));
1147         if (isValidUint16ColourValue(color->max_cll)) {
1148             info.sType1.mMaxContentLightLevel = color->max_cll;
1149         }
1150         if (isValidUint16ColourValue(color->max_fall)) {
1151             info.sType1.mMaxFrameAverageLightLevel = color->max_fall;
1152         }
1153         const mkvparser::MasteringMetadata *mastering = color->mastering_metadata;
1154         if (mastering != NULL) {
1155             // Convert matroska values to HDRStaticInfo equivalent values for each fully specified
1156             // group. See CTA-681.3 section 3.2.1 for more info.
1157             if (mastering->luminance_max >= 0.5 && mastering->luminance_max < 65535.5) {
1158                 info.sType1.mMaxDisplayLuminance = (uint16_t)(mastering->luminance_max + 0.5);
1159             }
1160             if (mastering->luminance_min >= 0.00005 && mastering->luminance_min < 6.55355) {
1161                 // HDRStaticInfo Type1 stores min luminance scaled 10000:1
1162                 info.sType1.mMinDisplayLuminance =
1163                     (uint16_t)(10000 * mastering->luminance_min + 0.5);
1164             }
1165             // HDRStaticInfo Type1 stores primaries scaled 50000:1
1166             if (isValidPrimary(mastering->white_point)) {
1167                 info.sType1.mW.x = (uint16_t)(50000 * mastering->white_point->x + 0.5);
1168                 info.sType1.mW.y = (uint16_t)(50000 * mastering->white_point->y + 0.5);
1169             }
1170             if (isValidPrimary(mastering->r) && isValidPrimary(mastering->g)
1171                     && isValidPrimary(mastering->b)) {
1172                 info.sType1.mR.x = (uint16_t)(50000 * mastering->r->x + 0.5);
1173                 info.sType1.mR.y = (uint16_t)(50000 * mastering->r->y + 0.5);
1174                 info.sType1.mG.x = (uint16_t)(50000 * mastering->g->x + 0.5);
1175                 info.sType1.mG.y = (uint16_t)(50000 * mastering->g->y + 0.5);
1176                 info.sType1.mB.x = (uint16_t)(50000 * mastering->b->x + 0.5);
1177                 info.sType1.mB.y = (uint16_t)(50000 * mastering->b->y + 0.5);
1178             }
1179         }
1180         // Only advertise static info if at least one of the groups have been specified.
1181         if (memcmp(&info, &nullInfo, sizeof(info)) != 0) {
1182             info.mID = HDRStaticInfo::kType1;
1183             meta->setData(kKeyHdrStaticInfo, 'hdrS', &info, sizeof(info));
1184         }
1185     }
1186 }
1187 
initTrackInfo(const mkvparser::Track * track,const sp<MetaData> & meta,TrackInfo * trackInfo)1188 status_t MatroskaExtractor::initTrackInfo(
1189         const mkvparser::Track *track, const sp<MetaData> &meta, TrackInfo *trackInfo) {
1190     trackInfo->mTrackNum = track->GetNumber();
1191     trackInfo->mMeta = meta;
1192     trackInfo->mExtractor = this;
1193     trackInfo->mEncrypted = false;
1194     trackInfo->mHeader = NULL;
1195     trackInfo->mHeaderLen = 0;
1196 
1197     for(size_t i = 0; i < track->GetContentEncodingCount(); i++) {
1198         const mkvparser::ContentEncoding *encoding = track->GetContentEncodingByIndex(i);
1199         for(size_t j = 0; j < encoding->GetEncryptionCount(); j++) {
1200             const mkvparser::ContentEncoding::ContentEncryption *encryption;
1201             encryption = encoding->GetEncryptionByIndex(j);
1202             trackInfo->mMeta->setData(kKeyCryptoKey, 0, encryption->key_id, encryption->key_id_len);
1203             trackInfo->mEncrypted = true;
1204             break;
1205         }
1206 
1207         for(size_t j = 0; j < encoding->GetCompressionCount(); j++) {
1208             const mkvparser::ContentEncoding::ContentCompression *compression;
1209             compression = encoding->GetCompressionByIndex(j);
1210             ALOGV("compression algo %llu settings_len %lld",
1211                 compression->algo, compression->settings_len);
1212             if (compression->algo == 3
1213                     && compression->settings
1214                     && compression->settings_len > 0) {
1215                 trackInfo->mHeader = compression->settings;
1216                 trackInfo->mHeaderLen = compression->settings_len;
1217             }
1218         }
1219     }
1220 
1221     return OK;
1222 }
1223 
addTracks()1224 void MatroskaExtractor::addTracks() {
1225     const mkvparser::Tracks *tracks = mSegment->GetTracks();
1226 
1227     for (size_t index = 0; index < tracks->GetTracksCount(); ++index) {
1228         const mkvparser::Track *track = tracks->GetTrackByIndex(index);
1229 
1230         if (track == NULL) {
1231             // Apparently this is currently valid (if unexpected) behaviour
1232             // of the mkv parser lib.
1233             continue;
1234         }
1235 
1236         const char *const codecID = track->GetCodecId();
1237         ALOGV("codec id = %s", codecID);
1238         ALOGV("codec name = %s", track->GetCodecNameAsUTF8());
1239 
1240         if (codecID == NULL) {
1241             ALOGW("unknown codecID is not supported.");
1242             continue;
1243         }
1244 
1245         size_t codecPrivateSize;
1246         const unsigned char *codecPrivate =
1247             track->GetCodecPrivate(codecPrivateSize);
1248 
1249         enum { VIDEO_TRACK = 1, AUDIO_TRACK = 2 };
1250 
1251         sp<MetaData> meta = new MetaData;
1252 
1253         status_t err = OK;
1254 
1255         switch (track->GetType()) {
1256             case VIDEO_TRACK:
1257             {
1258                 const mkvparser::VideoTrack *vtrack =
1259                     static_cast<const mkvparser::VideoTrack *>(track);
1260 
1261                 if (!strcmp("V_MPEG4/ISO/AVC", codecID)) {
1262                     meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
1263                     meta->setData(kKeyAVCC, 0, codecPrivate, codecPrivateSize);
1264                 } else if (!strcmp("V_MPEG4/ISO/ASP", codecID)) {
1265                     if (codecPrivateSize > 0) {
1266                         meta->setCString(
1267                                 kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
1268                         addESDSFromCodecPrivate(
1269                                 meta, false, codecPrivate, codecPrivateSize);
1270                     } else {
1271                         ALOGW("%s is detected, but does not have configuration.",
1272                                 codecID);
1273                         continue;
1274                     }
1275                 } else if (!strcmp("V_VP8", codecID)) {
1276                     meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VP8);
1277                 } else if (!strcmp("V_VP9", codecID)) {
1278                     meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VP9);
1279                     if (codecPrivateSize > 0) {
1280                       // 'csd-0' for VP9 is the Blob of Codec Private data as
1281                       // specified in http://www.webmproject.org/vp9/profiles/.
1282                       meta->setData(
1283                               kKeyVp9CodecPrivate, 0, codecPrivate,
1284                               codecPrivateSize);
1285                     }
1286                 } else {
1287                     ALOGW("%s is not supported.", codecID);
1288                     continue;
1289                 }
1290 
1291                 const long long width = vtrack->GetWidth();
1292                 const long long height = vtrack->GetHeight();
1293                 if (width <= 0 || width > INT32_MAX) {
1294                     ALOGW("track width exceeds int32_t, %lld", width);
1295                     continue;
1296                 }
1297                 if (height <= 0 || height > INT32_MAX) {
1298                     ALOGW("track height exceeds int32_t, %lld", height);
1299                     continue;
1300                 }
1301                 meta->setInt32(kKeyWidth, (int32_t)width);
1302                 meta->setInt32(kKeyHeight, (int32_t)height);
1303 
1304                 // setting display width/height is optional
1305                 const long long displayUnit = vtrack->GetDisplayUnit();
1306                 const long long displayWidth = vtrack->GetDisplayWidth();
1307                 const long long displayHeight = vtrack->GetDisplayHeight();
1308                 if (displayWidth > 0 && displayWidth <= INT32_MAX
1309                         && displayHeight > 0 && displayHeight <= INT32_MAX) {
1310                     switch (displayUnit) {
1311                     case 0: // pixels
1312                         meta->setInt32(kKeyDisplayWidth, (int32_t)displayWidth);
1313                         meta->setInt32(kKeyDisplayHeight, (int32_t)displayHeight);
1314                         break;
1315                     case 1: // centimeters
1316                     case 2: // inches
1317                     case 3: // aspect ratio
1318                     {
1319                         // Physical layout size is treated the same as aspect ratio.
1320                         // Note: displayWidth and displayHeight are never zero as they are
1321                         // checked in the if above.
1322                         const long long computedWidth =
1323                                 std::max(width, height * displayWidth / displayHeight);
1324                         const long long computedHeight =
1325                                 std::max(height, width * displayHeight / displayWidth);
1326                         if (computedWidth <= INT32_MAX && computedHeight <= INT32_MAX) {
1327                             meta->setInt32(kKeyDisplayWidth, (int32_t)computedWidth);
1328                             meta->setInt32(kKeyDisplayHeight, (int32_t)computedHeight);
1329                         }
1330                         break;
1331                     }
1332                     default: // unknown display units, perhaps future version of spec.
1333                         break;
1334                     }
1335                 }
1336 
1337                 getColorInformation(vtrack, meta);
1338 
1339                 break;
1340             }
1341 
1342             case AUDIO_TRACK:
1343             {
1344                 const mkvparser::AudioTrack *atrack =
1345                     static_cast<const mkvparser::AudioTrack *>(track);
1346 
1347                 if (!strcmp("A_AAC", codecID)) {
1348                     meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
1349                     CHECK(codecPrivateSize >= 2);
1350 
1351                     addESDSFromCodecPrivate(
1352                             meta, true, codecPrivate, codecPrivateSize);
1353                 } else if (!strcmp("A_VORBIS", codecID)) {
1354                     meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS);
1355 
1356                     err = addVorbisCodecInfo(
1357                             meta, codecPrivate, codecPrivateSize);
1358                 } else if (!strcmp("A_OPUS", codecID)) {
1359                     meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_OPUS);
1360                     meta->setData(kKeyOpusHeader, 0, codecPrivate, codecPrivateSize);
1361                     meta->setInt64(kKeyOpusCodecDelay, track->GetCodecDelay());
1362                     meta->setInt64(kKeyOpusSeekPreRoll, track->GetSeekPreRoll());
1363                     mSeekPreRollNs = track->GetSeekPreRoll();
1364                 } else if (!strcmp("A_MPEG/L3", codecID)) {
1365                     meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
1366                 } else {
1367                     ALOGW("%s is not supported.", codecID);
1368                     continue;
1369                 }
1370 
1371                 meta->setInt32(kKeySampleRate, atrack->GetSamplingRate());
1372                 meta->setInt32(kKeyChannelCount, atrack->GetChannels());
1373                 break;
1374             }
1375 
1376             default:
1377                 continue;
1378         }
1379 
1380         if (err != OK) {
1381             ALOGE("skipping track, codec specific data was malformed.");
1382             continue;
1383         }
1384 
1385         long long durationNs = mSegment->GetDuration();
1386         meta->setInt64(kKeyDuration, (durationNs + 500) / 1000);
1387 
1388         mTracks.push();
1389         size_t n = mTracks.size() - 1;
1390         TrackInfo *trackInfo = &mTracks.editItemAt(n);
1391         initTrackInfo(track, meta, trackInfo);
1392 
1393         if (!strcmp("V_MPEG4/ISO/AVC", codecID) && codecPrivateSize == 0) {
1394             // Attempt to recover from AVC track without codec private data
1395             err = synthesizeAVCC(trackInfo, n);
1396             if (err != OK) {
1397                 mTracks.pop();
1398             }
1399         }
1400     }
1401 }
1402 
findThumbnails()1403 void MatroskaExtractor::findThumbnails() {
1404     for (size_t i = 0; i < mTracks.size(); ++i) {
1405         TrackInfo *info = &mTracks.editItemAt(i);
1406 
1407         const char *mime;
1408         CHECK(info->mMeta->findCString(kKeyMIMEType, &mime));
1409 
1410         if (strncasecmp(mime, "video/", 6)) {
1411             continue;
1412         }
1413 
1414         BlockIterator iter(this, info->mTrackNum, i);
1415         int32_t j = 0;
1416         int64_t thumbnailTimeUs = 0;
1417         size_t maxBlockSize = 0;
1418         while (!iter.eos() && j < 20) {
1419             if (iter.block()->IsKey()) {
1420                 ++j;
1421 
1422                 size_t blockSize = 0;
1423                 for (int k = 0; k < iter.block()->GetFrameCount(); ++k) {
1424                     blockSize += iter.block()->GetFrame(k).len;
1425                 }
1426 
1427                 if (blockSize > maxBlockSize) {
1428                     maxBlockSize = blockSize;
1429                     thumbnailTimeUs = iter.blockTimeUs();
1430                 }
1431             }
1432             iter.advance();
1433         }
1434         info->mMeta->setInt64(kKeyThumbnailTime, thumbnailTimeUs);
1435     }
1436 }
1437 
getMetaData()1438 sp<MetaData> MatroskaExtractor::getMetaData() {
1439     sp<MetaData> meta = new MetaData;
1440 
1441     meta->setCString(
1442             kKeyMIMEType,
1443             mIsWebm ? "video/webm" : MEDIA_MIMETYPE_CONTAINER_MATROSKA);
1444 
1445     return meta;
1446 }
1447 
flags() const1448 uint32_t MatroskaExtractor::flags() const {
1449     uint32_t x = CAN_PAUSE;
1450     if (!isLiveStreaming()) {
1451         x |= CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK;
1452     }
1453 
1454     return x;
1455 }
1456 
SniffMatroska(const sp<DataSource> & source,String8 * mimeType,float * confidence,sp<AMessage> *)1457 bool SniffMatroska(
1458         const sp<DataSource> &source, String8 *mimeType, float *confidence,
1459         sp<AMessage> *) {
1460     DataSourceReader reader(source);
1461     mkvparser::EBMLHeader ebmlHeader;
1462     long long pos;
1463     if (ebmlHeader.Parse(&reader, pos) < 0) {
1464         return false;
1465     }
1466 
1467     mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_MATROSKA);
1468     *confidence = 0.6;
1469 
1470     return true;
1471 }
1472 
1473 }  // namespace android
1474