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