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 "FLACDecoder.h"
22 #include "MatroskaExtractor.h"
23 #include "common/webmids.h"
24
25 #include <media/DataSourceBase.h>
26 #include <media/ExtractorUtils.h>
27 #include <media/stagefright/foundation/ADebug.h>
28 #include <media/stagefright/foundation/AUtils.h>
29 #include <media/stagefright/foundation/ABuffer.h>
30 #include <media/stagefright/foundation/ByteUtils.h>
31 #include <media/stagefright/foundation/ColorUtils.h>
32 #include <media/stagefright/foundation/hexdump.h>
33 #include <media/stagefright/MediaDefs.h>
34 #include <media/stagefright/MediaErrors.h>
35 #include <media/stagefright/MetaDataUtils.h>
36 #include <media/stagefright/foundation/avc_utils.h>
37 #include <utils/String8.h>
38
39 #include <arpa/inet.h>
40 #include <inttypes.h>
41 #include <vector>
42
43 namespace android {
44
45 struct DataSourceBaseReader : public mkvparser::IMkvReader {
DataSourceBaseReaderandroid::DataSourceBaseReader46 explicit DataSourceBaseReader(DataSourceHelper *source)
47 : mSource(source) {
48 }
49
Readandroid::DataSourceBaseReader50 virtual int Read(long long position, long length, unsigned char* buffer) {
51 CHECK(position >= 0);
52 CHECK(length >= 0);
53
54 if (length == 0) {
55 return 0;
56 }
57
58 ssize_t n = mSource->readAt(position, buffer, length);
59
60 if (n <= 0) {
61 return -1;
62 }
63
64 return 0;
65 }
66
Lengthandroid::DataSourceBaseReader67 virtual int Length(long long* total, long long* available) {
68 off64_t size;
69 if (mSource->getSize(&size) != OK) {
70 if (total) {
71 *total = -1;
72 }
73 if (available) {
74 *available = (long long)((1ull << 63) - 1);
75 }
76
77 return 0;
78 }
79
80 if (total) {
81 *total = size;
82 }
83
84 if (available) {
85 *available = size;
86 }
87
88 return 0;
89 }
90
91 private:
92 DataSourceHelper *mSource;
93
94 DataSourceBaseReader(const DataSourceBaseReader &);
95 DataSourceBaseReader &operator=(const DataSourceBaseReader &);
96 };
97
98 ////////////////////////////////////////////////////////////////////////////////
99
100 struct BlockIterator {
101 BlockIterator(MatroskaExtractor *extractor, unsigned long trackNum, unsigned long index);
102
103 bool eos() const;
104
105 void advance();
106 void reset();
107
108 void seek(
109 int64_t seekTimeUs, bool isAudio,
110 int64_t *actualFrameTimeUs);
111
112 const mkvparser::Block *block() const;
113 int64_t blockTimeUs() const;
114
115 private:
116 MatroskaExtractor *mExtractor;
117 long long mTrackNum;
118 unsigned long mIndex;
119
120 const mkvparser::Cluster *mCluster;
121 const mkvparser::BlockEntry *mBlockEntry;
122 long mBlockEntryIndex;
123
124 unsigned long mTrackType;
125 void seekwithoutcue_l(int64_t seekTimeUs, int64_t *actualFrameTimeUs);
126
127 void advance_l();
128
129 BlockIterator(const BlockIterator &);
130 BlockIterator &operator=(const BlockIterator &);
131 };
132
133 struct MatroskaSource : public MediaTrackHelper {
134 MatroskaSource(MatroskaExtractor *extractor, size_t index);
135
136 virtual media_status_t start();
137 virtual media_status_t stop();
138
139 virtual media_status_t getFormat(AMediaFormat *);
140
141 virtual media_status_t read(
142 MediaBufferHelper **buffer, const ReadOptions *options);
143
144 protected:
145 virtual ~MatroskaSource();
146
147 private:
148 enum Type {
149 AVC,
150 AAC,
151 HEVC,
152 MP3,
153 PCM,
154 VORBIS,
155 OTHER
156 };
157
158 MatroskaExtractor *mExtractor;
159 size_t mTrackIndex;
160 Type mType;
161 bool mIsAudio;
162 BlockIterator mBlockIter;
163 ssize_t mNALSizeLen; // for type AVC or HEVC
164
165 List<MediaBufferHelper *> mPendingFrames;
166
167 int64_t mCurrentTS; // add for mp3
168 uint32_t mMP3Header;
169
170 media_status_t findMP3Header(uint32_t * header,
171 const uint8_t *dataSource, int length, int *outStartPos);
172 media_status_t mp3FrameRead(
173 MediaBufferHelper **out, const ReadOptions *options,
174 int64_t targetSampleTimeUs);
175
176 status_t advance();
177
178 status_t setWebmBlockCryptoInfo(MediaBufferHelper *mbuf);
179 media_status_t readBlock();
180 void clearPendingFrames();
181
182 MatroskaSource(const MatroskaSource &);
183 MatroskaSource &operator=(const MatroskaSource &);
184 };
185
getTrack() const186 const mkvparser::Track* MatroskaExtractor::TrackInfo::getTrack() const {
187 return mExtractor->mSegment->GetTracks()->GetTrackByNumber(mTrackNum);
188 }
189
190 // This function does exactly the same as mkvparser::Cues::Find, except that it
191 // searches in our own track based vectors. We should not need this once mkvparser
192 // adds the same functionality.
find(long long timeNs) const193 const mkvparser::CuePoint::TrackPosition *MatroskaExtractor::TrackInfo::find(
194 long long timeNs) const {
195 ALOGV("mCuePoints.size %zu", mCuePoints.size());
196 if (mCuePoints.empty()) {
197 return NULL;
198 }
199
200 const mkvparser::CuePoint* cp = mCuePoints.itemAt(0);
201 const mkvparser::Track* track = getTrack();
202 if (timeNs <= cp->GetTime(mExtractor->mSegment)) {
203 return cp->Find(track);
204 }
205
206 // Binary searches through relevant cues; assumes cues are ordered by timecode.
207 // If we do detect out-of-order cues, return NULL.
208 size_t lo = 0;
209 size_t hi = mCuePoints.size();
210 while (lo < hi) {
211 const size_t mid = lo + (hi - lo) / 2;
212 const mkvparser::CuePoint* const midCp = mCuePoints.itemAt(mid);
213 const long long cueTimeNs = midCp->GetTime(mExtractor->mSegment);
214 if (cueTimeNs <= timeNs) {
215 lo = mid + 1;
216 } else {
217 hi = mid;
218 }
219 }
220
221 if (lo == 0) {
222 return NULL;
223 }
224
225 cp = mCuePoints.itemAt(lo - 1);
226 if (cp->GetTime(mExtractor->mSegment) > timeNs) {
227 return NULL;
228 }
229
230 return cp->Find(track);
231 }
232
MatroskaSource(MatroskaExtractor * extractor,size_t index)233 MatroskaSource::MatroskaSource(
234 MatroskaExtractor *extractor, size_t index)
235 : mExtractor(extractor),
236 mTrackIndex(index),
237 mType(OTHER),
238 mIsAudio(false),
239 mBlockIter(mExtractor,
240 mExtractor->mTracks.itemAt(index).mTrackNum,
241 index),
242 mNALSizeLen(-1),
243 mCurrentTS(0),
244 mMP3Header(0) {
245 MatroskaExtractor::TrackInfo &trackInfo = mExtractor->mTracks.editItemAt(index);
246 AMediaFormat *meta = trackInfo.mMeta;
247
248 const char *mime;
249 CHECK(AMediaFormat_getString(meta, AMEDIAFORMAT_KEY_MIME, &mime));
250
251 mIsAudio = !strncasecmp("audio/", mime, 6);
252
253 if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
254 mType = AVC;
255
256 int32_t nalSizeLen = trackInfo.mNalLengthSize;
257 if (nalSizeLen >= 0 && nalSizeLen <= 4) {
258 mNALSizeLen = nalSizeLen;
259 } else {
260 ALOGE("No AVC mNALSizeLen");
261 }
262 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC)) {
263 mType = HEVC;
264
265 int32_t nalSizeLen = trackInfo.mNalLengthSize;
266 if (nalSizeLen >= 0 && nalSizeLen <= 4) {
267 mNALSizeLen = nalSizeLen;
268 } else {
269 ALOGE("No HEVC mNALSizeLen");
270 }
271 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
272 mType = AAC;
273 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
274 mType = MP3;
275 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
276 mType = PCM;
277 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
278 mType = VORBIS;
279 }
280 }
281
~MatroskaSource()282 MatroskaSource::~MatroskaSource() {
283 clearPendingFrames();
284 }
285
start()286 media_status_t MatroskaSource::start() {
287 if (mType == AVC && mNALSizeLen < 0) {
288 return AMEDIA_ERROR_MALFORMED;
289 }
290
291 // allocate one small initial buffer, but leave plenty of room to grow
292 mBufferGroup->init(1 /* number of buffers */, 1024 /* buffer size */, 64 /* growth limit */);
293 mBlockIter.reset();
294
295 if (mType == MP3 && mMP3Header == 0) {
296 int start = -1;
297 media_status_t err = findMP3Header(&mMP3Header, NULL, 0, &start);
298 if (err != OK) {
299 ALOGE("No mp3 header found");
300 clearPendingFrames();
301 return err;
302 }
303 }
304
305 return AMEDIA_OK;
306 }
307
stop()308 media_status_t MatroskaSource::stop() {
309 clearPendingFrames();
310
311 return AMEDIA_OK;
312 }
313
getFormat(AMediaFormat * meta)314 media_status_t MatroskaSource::getFormat(AMediaFormat *meta) {
315 return AMediaFormat_copy(meta, mExtractor->mTracks.itemAt(mTrackIndex).mMeta);
316 }
317
318 ////////////////////////////////////////////////////////////////////////////////
319
BlockIterator(MatroskaExtractor * extractor,unsigned long trackNum,unsigned long index)320 BlockIterator::BlockIterator(
321 MatroskaExtractor *extractor, unsigned long trackNum, unsigned long index)
322 : mExtractor(extractor),
323 mTrackNum(trackNum),
324 mIndex(index),
325 mCluster(NULL),
326 mBlockEntry(NULL),
327 mBlockEntryIndex(0) {
328 mTrackType = mExtractor->mSegment->GetTracks()->GetTrackByNumber(trackNum)->GetType();
329 reset();
330 }
331
eos() const332 bool BlockIterator::eos() const {
333 return mCluster == NULL || mCluster->EOS();
334 }
335
advance()336 void BlockIterator::advance() {
337 Mutex::Autolock autoLock(mExtractor->mLock);
338 advance_l();
339 }
340
advance_l()341 void BlockIterator::advance_l() {
342 for (;;) {
343 long res = mCluster->GetEntry(mBlockEntryIndex, mBlockEntry);
344 ALOGV("GetEntry returned %ld", res);
345
346 long long pos;
347 long len;
348 if (res < 0) {
349 // Need to parse this cluster some more
350
351 CHECK_EQ(res, mkvparser::E_BUFFER_NOT_FULL);
352
353 res = mCluster->Parse(pos, len);
354 ALOGV("Parse returned %ld", res);
355
356 if (res < 0) {
357 // I/O error
358
359 ALOGE("Cluster::Parse returned result %ld", res);
360
361 mCluster = NULL;
362 break;
363 }
364
365 continue;
366 } else if (res == 0) {
367 // We're done with this cluster
368
369 const mkvparser::Cluster *nextCluster;
370 res = mExtractor->mSegment->ParseNext(
371 mCluster, nextCluster, pos, len);
372 ALOGV("ParseNext returned %ld", res);
373
374 if (res != 0) {
375 // EOF or error
376
377 mCluster = NULL;
378 break;
379 }
380
381 CHECK_EQ(res, 0);
382 CHECK(nextCluster != NULL);
383 CHECK(!nextCluster->EOS());
384
385 mCluster = nextCluster;
386
387 res = mCluster->Parse(pos, len);
388 ALOGV("Parse (2) returned %ld", res);
389
390 if (res < 0) {
391 // I/O error
392
393 ALOGE("Cluster::Parse returned result %ld", res);
394
395 mCluster = NULL;
396 break;
397 }
398
399 mBlockEntryIndex = 0;
400 continue;
401 }
402
403 CHECK(mBlockEntry != NULL);
404 CHECK(mBlockEntry->GetBlock() != NULL);
405 ++mBlockEntryIndex;
406
407 if (mBlockEntry->GetBlock()->GetTrackNumber() == mTrackNum) {
408 break;
409 }
410 }
411 }
412
reset()413 void BlockIterator::reset() {
414 Mutex::Autolock autoLock(mExtractor->mLock);
415
416 mCluster = mExtractor->mSegment->GetFirst();
417 mBlockEntry = NULL;
418 mBlockEntryIndex = 0;
419
420 do {
421 advance_l();
422 } while (!eos() && block()->GetTrackNumber() != mTrackNum);
423 }
424
seek(int64_t seekTimeUs,bool isAudio,int64_t * actualFrameTimeUs)425 void BlockIterator::seek(
426 int64_t seekTimeUs, bool isAudio,
427 int64_t *actualFrameTimeUs) {
428 Mutex::Autolock autoLock(mExtractor->mLock);
429
430 *actualFrameTimeUs = -1ll;
431
432 if (seekTimeUs > INT64_MAX / 1000ll ||
433 seekTimeUs < INT64_MIN / 1000ll ||
434 (mExtractor->mSeekPreRollNs > 0 &&
435 (seekTimeUs * 1000ll) < INT64_MIN + mExtractor->mSeekPreRollNs) ||
436 (mExtractor->mSeekPreRollNs < 0 &&
437 (seekTimeUs * 1000ll) > INT64_MAX + mExtractor->mSeekPreRollNs)) {
438 ALOGE("cannot seek to %lld", (long long) seekTimeUs);
439 return;
440 }
441
442 const int64_t seekTimeNs = seekTimeUs * 1000ll - mExtractor->mSeekPreRollNs;
443
444 mkvparser::Segment* const pSegment = mExtractor->mSegment;
445
446 // Special case the 0 seek to avoid loading Cues when the application
447 // extraneously seeks to 0 before playing.
448 if (seekTimeNs <= 0) {
449 ALOGV("Seek to beginning: %" PRId64, seekTimeUs);
450 mCluster = pSegment->GetFirst();
451 mBlockEntryIndex = 0;
452 do {
453 advance_l();
454 } while (!eos() && block()->GetTrackNumber() != mTrackNum);
455 return;
456 }
457
458 ALOGV("Seeking to: %" PRId64, seekTimeUs);
459
460 // If the Cues have not been located then find them.
461 const mkvparser::Cues* pCues = pSegment->GetCues();
462 const mkvparser::SeekHead* pSH = pSegment->GetSeekHead();
463 if (!pCues && pSH) {
464 const size_t count = pSH->GetCount();
465 const mkvparser::SeekHead::Entry* pEntry;
466 ALOGV("No Cues yet");
467
468 for (size_t index = 0; index < count; index++) {
469 pEntry = pSH->GetEntry(index);
470
471 if (pEntry->id == libwebm::kMkvCues) { // Cues ID
472 long len; long long pos;
473 pSegment->ParseCues(pEntry->pos, pos, len);
474 pCues = pSegment->GetCues();
475 ALOGV("Cues found");
476 break;
477 }
478 }
479
480 if (!pCues) {
481 ALOGV("No Cues in file,seek without cue data");
482 seekwithoutcue_l(seekTimeUs, actualFrameTimeUs);
483 return;
484 }
485 }
486 else if (!pSH) {
487 ALOGV("No SeekHead, seek without cue data");
488 seekwithoutcue_l(seekTimeUs, actualFrameTimeUs);
489 return;
490 }
491
492 const mkvparser::CuePoint* pCP;
493 mkvparser::Tracks const *pTracks = pSegment->GetTracks();
494 while (!pCues->DoneParsing()) {
495 pCues->LoadCuePoint();
496 pCP = pCues->GetLast();
497 ALOGV("pCP = %s", pCP == NULL ? "NULL" : "not NULL");
498 if (pCP == NULL)
499 continue;
500
501 size_t trackCount = mExtractor->mTracks.size();
502 for (size_t index = 0; index < trackCount; ++index) {
503 MatroskaExtractor::TrackInfo& track = mExtractor->mTracks.editItemAt(index);
504 const mkvparser::Track *pTrack = pTracks->GetTrackByNumber(track.mTrackNum);
505 if (pTrack && pTrack->GetType() == 1 && pCP->Find(pTrack)) { // VIDEO_TRACK
506 track.mCuePoints.push_back(pCP);
507 }
508 }
509
510 if (pCP->GetTime(pSegment) >= seekTimeNs) {
511 ALOGV("Parsed past relevant Cue");
512 break;
513 }
514 }
515
516 const mkvparser::CuePoint::TrackPosition *pTP = NULL;
517 const mkvparser::Track *thisTrack = pTracks->GetTrackByNumber(mTrackNum);
518 if (thisTrack->GetType() == 1) { // video
519 MatroskaExtractor::TrackInfo& track = mExtractor->mTracks.editItemAt(mIndex);
520 pTP = track.find(seekTimeNs);
521 } else {
522 // The Cue index is built around video keyframes
523 unsigned long int trackCount = pTracks->GetTracksCount();
524 for (size_t index = 0; index < trackCount; ++index) {
525 const mkvparser::Track *pTrack = pTracks->GetTrackByIndex(index);
526 if (pTrack && pTrack->GetType() == 1 && pCues->Find(seekTimeNs, pTrack, pCP, pTP)) {
527 ALOGV("Video track located at %zu", index);
528 break;
529 }
530 }
531 }
532
533
534 // Always *search* based on the video track, but finalize based on mTrackNum
535 if (!pTP) {
536 ALOGE("Did not locate the video track for seeking");
537 seekwithoutcue_l(seekTimeUs, actualFrameTimeUs);
538 return;
539 }
540
541 mCluster = pSegment->FindOrPreloadCluster(pTP->m_pos);
542
543 CHECK(mCluster);
544 CHECK(!mCluster->EOS());
545
546 // mBlockEntryIndex starts at 0 but m_block starts at 1
547 CHECK_GT(pTP->m_block, 0);
548 mBlockEntryIndex = pTP->m_block - 1;
549
550 for (;;) {
551 advance_l();
552
553 if (eos()) break;
554
555 if (isAudio || block()->IsKey()) {
556 // Accept the first key frame
557 int64_t frameTimeUs = (block()->GetTime(mCluster) + 500LL) / 1000LL;
558 if (thisTrack->GetType() == 1 || frameTimeUs >= seekTimeUs) {
559 *actualFrameTimeUs = frameTimeUs;
560 ALOGV("Requested seek point: %" PRId64 " actual: %" PRId64,
561 seekTimeUs, *actualFrameTimeUs);
562 break;
563 }
564 }
565 }
566 }
567
block() const568 const mkvparser::Block *BlockIterator::block() const {
569 CHECK(!eos());
570
571 return mBlockEntry->GetBlock();
572 }
573
blockTimeUs() const574 int64_t BlockIterator::blockTimeUs() const {
575 if (mCluster == NULL || mBlockEntry == NULL) {
576 return -1;
577 }
578 return (mBlockEntry->GetBlock()->GetTime(mCluster) + 500ll) / 1000ll;
579 }
580
seekwithoutcue_l(int64_t seekTimeUs,int64_t * actualFrameTimeUs)581 void BlockIterator::seekwithoutcue_l(int64_t seekTimeUs, int64_t *actualFrameTimeUs) {
582 mCluster = mExtractor->mSegment->FindCluster(seekTimeUs * 1000ll);
583 const long status = mCluster->GetFirst(mBlockEntry);
584 if (status < 0) { // error
585 ALOGE("get last blockenry failed!");
586 mCluster = NULL;
587 return;
588 }
589 mBlockEntryIndex = 0;
590 while (!eos() && ((block()->GetTrackNumber() != mTrackNum) || (blockTimeUs() < seekTimeUs))) {
591 advance_l();
592 }
593
594 // video track will seek to the next key frame.
595 if (mTrackType == 1) {
596 while (!eos() && ((block()->GetTrackNumber() != mTrackNum) ||
597 !mBlockEntry->GetBlock()->IsKey())) {
598 advance_l();
599 }
600 }
601 *actualFrameTimeUs = blockTimeUs();
602 ALOGV("seekTimeUs:%lld, actualFrameTimeUs:%lld, tracknum:%lld",
603 (long long)seekTimeUs, (long long)*actualFrameTimeUs, (long long)mTrackNum);
604 }
605
606 ////////////////////////////////////////////////////////////////////////////////
607
U24_AT(const uint8_t * ptr)608 static unsigned U24_AT(const uint8_t *ptr) {
609 return ptr[0] << 16 | ptr[1] << 8 | ptr[2];
610 }
611
uriDebugString(const char * uri)612 static AString uriDebugString(const char *uri) {
613 // find scheme
614 AString scheme;
615 for (size_t i = 0; i < strlen(uri); i++) {
616 const char c = uri[i];
617 if (!isascii(c)) {
618 break;
619 } else if (isalpha(c)) {
620 continue;
621 } else if (i == 0) {
622 // first character must be a letter
623 break;
624 } else if (isdigit(c) || c == '+' || c == '.' || c =='-') {
625 continue;
626 } else if (c != ':') {
627 break;
628 }
629 scheme = AString(uri, 0, i);
630 scheme.append("://<suppressed>");
631 return scheme;
632 }
633 return AString("<no-scheme URI suppressed>");
634 }
635
clearPendingFrames()636 void MatroskaSource::clearPendingFrames() {
637 while (!mPendingFrames.empty()) {
638 MediaBufferHelper *frame = *mPendingFrames.begin();
639 mPendingFrames.erase(mPendingFrames.begin());
640
641 frame->release();
642 frame = NULL;
643 }
644 }
645
setWebmBlockCryptoInfo(MediaBufferHelper * mbuf)646 status_t MatroskaSource::setWebmBlockCryptoInfo(MediaBufferHelper *mbuf) {
647 if (mbuf->range_length() < 1 || mbuf->range_length() - 1 > INT32_MAX) {
648 // 1-byte signal
649 return ERROR_MALFORMED;
650 }
651
652 const uint8_t *data = (const uint8_t *)mbuf->data() + mbuf->range_offset();
653 bool encrypted = data[0] & 0x1;
654 bool partitioned = data[0] & 0x2;
655 if (encrypted && mbuf->range_length() < 9) {
656 // 1-byte signal + 8-byte IV
657 return ERROR_MALFORMED;
658 }
659
660 AMediaFormat *meta = mbuf->meta_data();
661 if (encrypted) {
662 uint8_t ctrCounter[16] = { 0 };
663 const uint8_t *keyId;
664 size_t keyIdSize;
665 AMediaFormat *trackMeta = mExtractor->mTracks.itemAt(mTrackIndex).mMeta;
666 AMediaFormat_getBuffer(trackMeta, AMEDIAFORMAT_KEY_CRYPTO_KEY,
667 (void**)&keyId, &keyIdSize);
668 AMediaFormat_setBuffer(meta, AMEDIAFORMAT_KEY_CRYPTO_KEY, keyId, keyIdSize);
669 memcpy(ctrCounter, data + 1, 8);
670 AMediaFormat_setBuffer(meta, AMEDIAFORMAT_KEY_CRYPTO_IV, ctrCounter, 16);
671 if (partitioned) {
672 /* 0 1 2 3
673 * 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
674 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
675 * | Signal Byte | |
676 * +-+-+-+-+-+-+-+-+ IV |
677 * | |
678 * | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
679 * | | num_partition | Partition 0 offset -> |
680 * |-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
681 * | -> Partition 0 offset | ... |
682 * |-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
683 * | ... | Partition n-1 offset -> |
684 * |-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
685 * | -> Partition n-1 offset | |
686 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
687 * | Clear/encrypted sample data |
688 * | |
689 * | |
690 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
691 */
692 if (mbuf->range_length() < 10) {
693 return ERROR_MALFORMED;
694 }
695 uint8_t numPartitions = data[9];
696 if (mbuf->range_length() - 10 < numPartitions * sizeof(uint32_t)) {
697 return ERROR_MALFORMED;
698 }
699 std::vector<uint32_t> plainSizes, encryptedSizes;
700 uint32_t prev = 0;
701 uint32_t frameOffset = 10 + numPartitions * sizeof(uint32_t);
702 const uint32_t *partitions = reinterpret_cast<const uint32_t*>(data + 10);
703 for (uint32_t i = 0; i <= numPartitions; ++i) {
704 uint32_t p_i = i < numPartitions
705 ? ntohl(partitions[i])
706 : (mbuf->range_length() - frameOffset);
707 if (p_i < prev) {
708 return ERROR_MALFORMED;
709 }
710 uint32_t size = p_i - prev;
711 prev = p_i;
712 if (i % 2) {
713 encryptedSizes.push_back(size);
714 } else {
715 plainSizes.push_back(size);
716 }
717 }
718 if (plainSizes.size() > encryptedSizes.size()) {
719 encryptedSizes.push_back(0);
720 }
721 uint32_t sizeofPlainSizes = sizeof(uint32_t) * plainSizes.size();
722 uint32_t sizeofEncryptedSizes = sizeof(uint32_t) * encryptedSizes.size();
723 AMediaFormat_setBuffer(meta, AMEDIAFORMAT_KEY_CRYPTO_PLAIN_SIZES,
724 plainSizes.data(), sizeofPlainSizes);
725 AMediaFormat_setBuffer(meta, AMEDIAFORMAT_KEY_CRYPTO_ENCRYPTED_SIZES,
726 encryptedSizes.data(), sizeofEncryptedSizes);
727 mbuf->set_range(frameOffset, mbuf->range_length() - frameOffset);
728 } else {
729 /*
730 * 0 1 2 3
731 * 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
732 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
733 * | Signal Byte | |
734 * +-+-+-+-+-+-+-+-+ IV |
735 * | |
736 * | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
737 * | | |
738 * |-+-+-+-+-+-+-+-+ |
739 * : Bytes 1..N of encrypted frame :
740 * | |
741 * | |
742 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
743 */
744 int32_t plainSizes[] = { 0 };
745 int32_t encryptedSizes[] = { static_cast<int32_t>(mbuf->range_length() - 9) };
746 AMediaFormat_setBuffer(meta, AMEDIAFORMAT_KEY_CRYPTO_PLAIN_SIZES,
747 plainSizes, sizeof(plainSizes));
748 AMediaFormat_setBuffer(meta, AMEDIAFORMAT_KEY_CRYPTO_ENCRYPTED_SIZES,
749 encryptedSizes, sizeof(encryptedSizes));
750 mbuf->set_range(9, mbuf->range_length() - 9);
751 }
752 } else {
753 /*
754 * 0 1 2 3
755 * 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
756 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
757 * | Signal Byte | |
758 * +-+-+-+-+-+-+-+-+ |
759 * : Bytes 1..N of unencrypted frame :
760 * | |
761 * | |
762 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
763 */
764 int32_t plainSizes[] = { static_cast<int32_t>(mbuf->range_length() - 1) };
765 int32_t encryptedSizes[] = { 0 };
766 AMediaFormat_setBuffer(meta, AMEDIAFORMAT_KEY_CRYPTO_PLAIN_SIZES,
767 plainSizes, sizeof(plainSizes));
768 AMediaFormat_setBuffer(meta, AMEDIAFORMAT_KEY_CRYPTO_ENCRYPTED_SIZES,
769 encryptedSizes, sizeof(encryptedSizes));
770 mbuf->set_range(1, mbuf->range_length() - 1);
771 }
772
773 return OK;
774 }
775
readBlock()776 media_status_t MatroskaSource::readBlock() {
777 CHECK(mPendingFrames.empty());
778
779 if (mBlockIter.eos()) {
780 return AMEDIA_ERROR_END_OF_STREAM;
781 }
782
783 const mkvparser::Block *block = mBlockIter.block();
784
785 int64_t timeUs = mBlockIter.blockTimeUs();
786
787 for (int i = 0; i < block->GetFrameCount(); ++i) {
788 MatroskaExtractor::TrackInfo *trackInfo = &mExtractor->mTracks.editItemAt(mTrackIndex);
789 const mkvparser::Block::Frame &frame = block->GetFrame(i);
790 size_t len = frame.len;
791 if (SIZE_MAX - len < trackInfo->mHeaderLen) {
792 return AMEDIA_ERROR_MALFORMED;
793 }
794
795 len += trackInfo->mHeaderLen;
796 MediaBufferHelper *mbuf;
797 mBufferGroup->acquire_buffer(&mbuf, false /* nonblocking */, len /* requested size */);
798 mbuf->set_range(0, len);
799 uint8_t *data = static_cast<uint8_t *>(mbuf->data());
800 if (trackInfo->mHeader) {
801 memcpy(data, trackInfo->mHeader, trackInfo->mHeaderLen);
802 }
803
804 AMediaFormat *meta = mbuf->meta_data();
805 AMediaFormat_setInt64(meta, AMEDIAFORMAT_KEY_TIME_US, timeUs);
806 AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_IS_SYNC_FRAME, block->IsKey());
807
808 if (mType == VORBIS) {
809 int32_t sampleRate;
810 if (!AMediaFormat_getInt32(trackInfo->mMeta, AMEDIAFORMAT_KEY_SAMPLE_RATE,
811 &sampleRate)) {
812 return AMEDIA_ERROR_MALFORMED;
813 }
814 int64_t durationUs;
815 if (!AMediaFormat_getInt64(trackInfo->mMeta, AMEDIAFORMAT_KEY_DURATION,
816 &durationUs)) {
817 return AMEDIA_ERROR_MALFORMED;
818 }
819 // TODO: Explore if this can be handled similar to MPEG4 extractor where padding is
820 // signalled instead of VALID_SAMPLES
821 // Remaining valid samples in Vorbis track
822 if (durationUs > timeUs) {
823 int32_t validSamples = ((durationUs - timeUs) * sampleRate) / 1000000ll;
824 AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_VALID_SAMPLES, validSamples);
825 }
826 }
827
828 status_t err = frame.Read(mExtractor->mReader, data + trackInfo->mHeaderLen);
829 if (err == OK
830 && mExtractor->mIsWebm
831 && trackInfo->mEncrypted) {
832 err = setWebmBlockCryptoInfo(mbuf);
833 }
834
835 if (err != OK) {
836 mPendingFrames.clear();
837
838 mBlockIter.advance();
839 mbuf->release();
840 return AMEDIA_ERROR_UNKNOWN;
841 }
842
843 mPendingFrames.push_back(mbuf);
844 }
845
846 mBlockIter.advance();
847
848 return AMEDIA_OK;
849 }
850
851 //the value of kMP3HeaderMask is from MP3Extractor
852 static const uint32_t kMP3HeaderMask = 0xfffe0c00;
853
findMP3Header(uint32_t * header,const uint8_t * dataSource,int length,int * outStartPos)854 media_status_t MatroskaSource::findMP3Header(uint32_t * header,
855 const uint8_t *dataSource, int length, int *outStartPos) {
856 if (NULL == header) {
857 ALOGE("header is null!");
858 return AMEDIA_ERROR_END_OF_STREAM;
859 }
860
861 //to find header start position
862 if (0 != *header) {
863 if (NULL == dataSource) {
864 *outStartPos = -1;
865 return AMEDIA_OK;
866 }
867 uint32_t tmpCode = 0;
868 for (int i = 0; i < length; i++) {
869 tmpCode = (tmpCode << 8) + dataSource[i];
870 if ((tmpCode & kMP3HeaderMask) == (*header & kMP3HeaderMask)) {
871 *outStartPos = i - 3;
872 return AMEDIA_OK;
873 }
874 }
875 *outStartPos = -1;
876 return AMEDIA_OK;
877 }
878
879 //to find mp3 header
880 uint32_t code = 0;
881 while (0 == *header) {
882 while (mPendingFrames.empty()) {
883 media_status_t err = readBlock();
884 if (err != OK) {
885 clearPendingFrames();
886 return err;
887 }
888 }
889 MediaBufferHelper *frame = *mPendingFrames.begin();
890 size_t size = frame->range_length();
891 size_t offset = frame->range_offset();
892 size_t i;
893 size_t frame_size;
894 for (i = 0; i < size; i++) {
895 ALOGV("data[%zu]=%x", i, *((uint8_t*)frame->data() + offset + i));
896 code = (code << 8) + *((uint8_t*)frame->data() + offset + i);
897 if (GetMPEGAudioFrameSize(code, &frame_size, NULL, NULL, NULL)) {
898 *header = code;
899 mBlockIter.reset();
900 clearPendingFrames();
901 return AMEDIA_OK;
902 }
903 }
904 }
905
906 return AMEDIA_ERROR_END_OF_STREAM;
907 }
908
mp3FrameRead(MediaBufferHelper ** out,const ReadOptions * options,int64_t targetSampleTimeUs)909 media_status_t MatroskaSource::mp3FrameRead(
910 MediaBufferHelper **out, const ReadOptions *options,
911 int64_t targetSampleTimeUs) {
912 MediaBufferHelper *frame = *mPendingFrames.begin();
913 int64_t seekTimeUs;
914 ReadOptions::SeekMode mode;
915 if (options && options->getSeekTo(&seekTimeUs, &mode)) {
916 CHECK(AMediaFormat_getInt64(frame->meta_data(),
917 AMEDIAFORMAT_KEY_TIME_US, &mCurrentTS));
918 if (mCurrentTS < 0) {
919 mCurrentTS = 0;
920 AMediaFormat_setInt64(frame->meta_data(),
921 AMEDIAFORMAT_KEY_TIME_US, mCurrentTS);
922 }
923 }
924
925 int32_t start = -1;
926 while (start < 0) {
927 //find header start position
928 findMP3Header(&mMP3Header,
929 (const uint8_t*)frame->data() + frame->range_offset(),
930 frame->range_length(), &start);
931 ALOGV("start=%d, frame->range_length() = %zu, frame->range_offset() =%zu",
932 start, frame->range_length(), frame->range_offset());
933 if (start >= 0)
934 break;
935 frame->release();
936 mPendingFrames.erase(mPendingFrames.begin());
937 while (mPendingFrames.empty()) {
938 media_status_t err = readBlock();
939 if (err != OK) {
940 clearPendingFrames();
941 return err;
942 }
943 }
944 frame = *mPendingFrames.begin();
945 }
946
947 frame->set_range(frame->range_offset() + start, frame->range_length() - start);
948
949 uint32_t header = *(uint32_t*)((uint8_t*)frame->data() + frame->range_offset());
950 header = ((header >> 24) & 0xff) | ((header >> 8) & 0xff00) |
951 ((header << 8) & 0xff0000) | ((header << 24) & 0xff000000);
952 size_t frame_size;
953 int out_sampling_rate;
954 int out_channels;
955 int out_bitrate;
956 if (!GetMPEGAudioFrameSize(header, &frame_size,
957 &out_sampling_rate, &out_channels, &out_bitrate)) {
958 ALOGE("MP3 Header read fail!!");
959 return AMEDIA_ERROR_UNSUPPORTED;
960 }
961
962 MediaBufferHelper *buffer;
963 mBufferGroup->acquire_buffer(&buffer, false /* nonblocking */, frame_size /* requested size */);
964 buffer->set_range(0, frame_size);
965
966 uint8_t *data = static_cast<uint8_t *>(buffer->data());
967 ALOGV("MP3 frame %zu frame->range_length() %zu", frame_size, frame->range_length());
968
969 if (frame_size > frame->range_length()) {
970 memcpy(data, (uint8_t*)(frame->data()) + frame->range_offset(), frame->range_length());
971 size_t sumSize = 0;
972 sumSize += frame->range_length();
973 size_t needSize = frame_size - frame->range_length();
974 frame->release();
975 mPendingFrames.erase(mPendingFrames.begin());
976 while (mPendingFrames.empty()) {
977 media_status_t err = readBlock();
978 if (err != OK) {
979 clearPendingFrames();
980 return err;
981 }
982 }
983 frame = *mPendingFrames.begin();
984 size_t offset = frame->range_offset();
985 size_t size = frame->range_length();
986
987 // the next buffer frame is not enough to fullfill mp3 frame,
988 // we have to read until mp3 frame is completed.
989 while (size < needSize) {
990 memcpy(data + sumSize, (uint8_t*)(frame->data()) + offset, size);
991 needSize -= size;
992 sumSize += size;
993 frame->release();
994 mPendingFrames.erase(mPendingFrames.begin());
995 while (mPendingFrames.empty()) {
996 media_status_t err = readBlock();
997 if (err != OK) {
998 clearPendingFrames();
999 return err;
1000 }
1001 }
1002 frame = *mPendingFrames.begin();
1003 offset = frame->range_offset();
1004 size = frame->range_length();
1005 }
1006 memcpy(data + sumSize, (uint8_t*)(frame->data()) + offset, needSize);
1007 frame->set_range(offset + needSize, size - needSize);
1008 } else {
1009 size_t offset = frame->range_offset();
1010 size_t size = frame->range_length();
1011 memcpy(data, (uint8_t*)(frame->data()) + offset, frame_size);
1012 frame->set_range(offset + frame_size, size - frame_size);
1013 }
1014 if (frame->range_length() < 4) {
1015 frame->release();
1016 frame = NULL;
1017 mPendingFrames.erase(mPendingFrames.begin());
1018 }
1019 ALOGV("MatroskaSource::read MP3 frame kKeyTime=%lld,kKeyTargetTime=%lld",
1020 (long long)mCurrentTS, (long long)targetSampleTimeUs);
1021 AMediaFormat_setInt64(buffer->meta_data(),
1022 AMEDIAFORMAT_KEY_TIME_US, mCurrentTS);
1023 mCurrentTS += (int64_t)frame_size * 8000ll / out_bitrate;
1024
1025 if (targetSampleTimeUs >= 0ll)
1026 AMediaFormat_setInt64(buffer->meta_data(),
1027 AMEDIAFORMAT_KEY_TARGET_TIME, targetSampleTimeUs);
1028 *out = buffer;
1029 ALOGV("MatroskaSource::read MP3, keyTime=%lld for next frame", (long long)mCurrentTS);
1030 return AMEDIA_OK;
1031 }
1032
read(MediaBufferHelper ** out,const ReadOptions * options)1033 media_status_t MatroskaSource::read(
1034 MediaBufferHelper **out, const ReadOptions *options) {
1035 *out = NULL;
1036
1037 int64_t targetSampleTimeUs = -1ll;
1038
1039 int64_t seekTimeUs;
1040 ReadOptions::SeekMode mode;
1041 if (options && options->getSeekTo(&seekTimeUs, &mode)) {
1042 if (mode == ReadOptions::SEEK_FRAME_INDEX) {
1043 return AMEDIA_ERROR_UNSUPPORTED;
1044 }
1045
1046 if (!mExtractor->isLiveStreaming()) {
1047 clearPendingFrames();
1048
1049 // The audio we want is located by using the Cues to seek the video
1050 // stream to find the target Cluster then iterating to finalize for
1051 // audio.
1052 int64_t actualFrameTimeUs;
1053 mBlockIter.seek(seekTimeUs, mIsAudio, &actualFrameTimeUs);
1054 if (mode == ReadOptions::SEEK_CLOSEST) {
1055 targetSampleTimeUs = actualFrameTimeUs;
1056 }
1057 }
1058 }
1059
1060 while (mPendingFrames.empty()) {
1061 media_status_t err = readBlock();
1062
1063 if (err != OK) {
1064 clearPendingFrames();
1065
1066 return err;
1067 }
1068 }
1069
1070 if (mType == MP3) {
1071 return mp3FrameRead(out, options, targetSampleTimeUs);
1072 }
1073
1074 MediaBufferHelper *frame = *mPendingFrames.begin();
1075 mPendingFrames.erase(mPendingFrames.begin());
1076
1077 if ((mType != AVC && mType != HEVC) || mNALSizeLen == 0) {
1078 if (targetSampleTimeUs >= 0ll) {
1079 AMediaFormat_setInt64(frame->meta_data(),
1080 AMEDIAFORMAT_KEY_TARGET_TIME, targetSampleTimeUs);
1081 }
1082
1083 if (mType == PCM) {
1084 int32_t bitPerFrame = 16;
1085 int32_t bigEndian = 0;
1086 AMediaFormat *meta = AMediaFormat_new();
1087 if (getFormat(meta) == AMEDIA_OK && meta != NULL) {
1088 AMediaFormat_getInt32(meta,
1089 AMEDIAFORMAT_KEY_BITS_PER_SAMPLE, &bitPerFrame);
1090 AMediaFormat_getInt32(meta,
1091 AMEDIAFORMAT_KEY_PCM_BIG_ENDIAN, &bigEndian);
1092 }
1093 AMediaFormat_delete(meta);
1094 if (bigEndian == 1 && bitPerFrame == 16) {
1095 // Big-endian -> little-endian
1096 uint16_t *dstData = (uint16_t *)frame->data() + frame->range_offset();
1097 uint16_t *srcData = (uint16_t *)frame->data() + frame->range_offset();
1098 for (size_t i = 0; i < frame->range_length() / 2; i++) {
1099 dstData[i] = ntohs(srcData[i]);
1100 }
1101 }
1102 }
1103
1104 *out = frame;
1105
1106 return AMEDIA_OK;
1107 }
1108
1109 // Each input frame contains one or more NAL fragments, each fragment
1110 // is prefixed by mNALSizeLen bytes giving the fragment length,
1111 // followed by a corresponding number of bytes containing the fragment.
1112 // We output all these fragments into a single large buffer separated
1113 // by startcodes (0x00 0x00 0x00 0x01).
1114 //
1115 // When mNALSizeLen is 0, we assume the data is already in the format
1116 // desired.
1117
1118 const uint8_t *srcPtr =
1119 (const uint8_t *)frame->data() + frame->range_offset();
1120
1121 size_t srcSize = frame->range_length();
1122
1123 size_t dstSize = 0;
1124 MediaBufferHelper *buffer = NULL;
1125 uint8_t *dstPtr = NULL;
1126
1127 for (int32_t pass = 0; pass < 2; ++pass) {
1128 size_t srcOffset = 0;
1129 size_t dstOffset = 0;
1130 while (srcOffset + mNALSizeLen <= srcSize) {
1131 size_t NALsize;
1132 switch (mNALSizeLen) {
1133 case 1: NALsize = srcPtr[srcOffset]; break;
1134 case 2: NALsize = U16_AT(srcPtr + srcOffset); break;
1135 case 3: NALsize = U24_AT(srcPtr + srcOffset); break;
1136 case 4: NALsize = U32_AT(srcPtr + srcOffset); break;
1137 default:
1138 TRESPASS();
1139 }
1140
1141 if (srcOffset + mNALSizeLen + NALsize <= srcOffset + mNALSizeLen) {
1142 frame->release();
1143 frame = NULL;
1144
1145 return AMEDIA_ERROR_MALFORMED;
1146 } else if (srcOffset + mNALSizeLen + NALsize > srcSize) {
1147 break;
1148 }
1149
1150 if (pass == 1) {
1151 memcpy(&dstPtr[dstOffset], "\x00\x00\x00\x01", 4);
1152
1153 if (frame != buffer) {
1154 memcpy(&dstPtr[dstOffset + 4],
1155 &srcPtr[srcOffset + mNALSizeLen],
1156 NALsize);
1157 }
1158 }
1159
1160 dstOffset += 4; // 0x00 00 00 01
1161 dstOffset += NALsize;
1162
1163 srcOffset += mNALSizeLen + NALsize;
1164 }
1165
1166 if (srcOffset < srcSize) {
1167 // There were trailing bytes or not enough data to complete
1168 // a fragment.
1169
1170 frame->release();
1171 frame = NULL;
1172
1173 return AMEDIA_ERROR_MALFORMED;
1174 }
1175
1176 if (pass == 0) {
1177 dstSize = dstOffset;
1178
1179 if (dstSize == srcSize && mNALSizeLen == 4) {
1180 // In this special case we can re-use the input buffer by substituting
1181 // each 4-byte nal size with a 4-byte start code
1182 buffer = frame;
1183 } else {
1184 mBufferGroup->acquire_buffer(
1185 &buffer, false /* nonblocking */, dstSize /* requested size */);
1186 buffer->set_range(0, dstSize);
1187 }
1188
1189 AMediaFormat *frameMeta = frame->meta_data();
1190 int64_t timeUs;
1191 CHECK(AMediaFormat_getInt64(frameMeta, AMEDIAFORMAT_KEY_TIME_US, &timeUs));
1192 int32_t isSync;
1193 CHECK(AMediaFormat_getInt32(frameMeta, AMEDIAFORMAT_KEY_IS_SYNC_FRAME, &isSync));
1194
1195 AMediaFormat *bufMeta = buffer->meta_data();
1196 AMediaFormat_setInt64(bufMeta, AMEDIAFORMAT_KEY_TIME_US, timeUs);
1197 AMediaFormat_setInt32(bufMeta, AMEDIAFORMAT_KEY_IS_SYNC_FRAME, isSync);
1198
1199 dstPtr = (uint8_t *)buffer->data();
1200 }
1201 }
1202
1203 if (frame != buffer) {
1204 frame->release();
1205 frame = NULL;
1206 }
1207
1208 if (targetSampleTimeUs >= 0ll) {
1209 AMediaFormat_setInt64(buffer->meta_data(),
1210 AMEDIAFORMAT_KEY_TARGET_TIME, targetSampleTimeUs);
1211 }
1212
1213 *out = buffer;
1214
1215 return AMEDIA_OK;
1216 }
1217
1218 ////////////////////////////////////////////////////////////////////////////////
1219
1220 enum WaveID {
1221 MKV_RIFF_WAVE_FORMAT_PCM = 0x0001,
1222 MKV_RIFF_WAVE_FORMAT_ADPCM_ms = 0x0002,
1223 MKV_RIFF_WAVE_FORMAT_ADPCM_ima_wav = 0x0011,
1224 MKV_RIFF_WAVE_FORMAT_MPEGL12 = 0x0050,
1225 MKV_RIFF_WAVE_FORMAT_MPEGL3 = 0x0055,
1226 MKV_RIFF_WAVE_FORMAT_WMAV1 = 0x0160,
1227 MKV_RIFF_WAVE_FORMAT_WMAV2 = 0x0161,
1228 };
1229
MKVWave2MIME(uint16_t id)1230 static const char *MKVWave2MIME(uint16_t id) {
1231 switch (id) {
1232 case MKV_RIFF_WAVE_FORMAT_MPEGL12:
1233 return MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II;
1234
1235 case MKV_RIFF_WAVE_FORMAT_MPEGL3:
1236 return MEDIA_MIMETYPE_AUDIO_MPEG;
1237
1238 case MKV_RIFF_WAVE_FORMAT_PCM:
1239 return MEDIA_MIMETYPE_AUDIO_RAW;
1240
1241 case MKV_RIFF_WAVE_FORMAT_ADPCM_ms:
1242 return MEDIA_MIMETYPE_AUDIO_MS_ADPCM;
1243 case MKV_RIFF_WAVE_FORMAT_ADPCM_ima_wav:
1244 return MEDIA_MIMETYPE_AUDIO_DVI_IMA_ADPCM;
1245
1246 case MKV_RIFF_WAVE_FORMAT_WMAV1:
1247 case MKV_RIFF_WAVE_FORMAT_WMAV2:
1248 return MEDIA_MIMETYPE_AUDIO_WMA;
1249 default:
1250 ALOGW("unknown wave %x", id);
1251 return "";
1252 };
1253 }
1254
isMkvAudioCsdSizeOK(const char * mime,size_t csdSize)1255 static bool isMkvAudioCsdSizeOK(const char* mime, size_t csdSize) {
1256 if ((!strcmp(mime, MEDIA_MIMETYPE_AUDIO_MS_ADPCM) && csdSize < 50) ||
1257 (!strcmp(mime, MEDIA_MIMETYPE_AUDIO_DVI_IMA_ADPCM) && csdSize < 20) ||
1258 (!strcmp(mime, MEDIA_MIMETYPE_AUDIO_WMA) && csdSize < 28) ||
1259 (!strcmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG) && csdSize < 30)) {
1260 return false;
1261 }
1262 return true;
1263 }
1264
1265 // trans all FOURCC to lower char
FourCCtoLower(uint32_t fourcc)1266 static uint32_t FourCCtoLower(uint32_t fourcc) {
1267 uint8_t ch_1 = tolower((fourcc >> 24) & 0xff);
1268 uint8_t ch_2 = tolower((fourcc >> 16) & 0xff);
1269 uint8_t ch_3 = tolower((fourcc >> 8) & 0xff);
1270 uint8_t ch_4 = tolower((fourcc) & 0xff);
1271 uint32_t fourcc_out = ch_1 << 24 | ch_2 << 16 | ch_3 << 8 | ch_4;
1272
1273 return fourcc_out;
1274 }
1275
MKVFourCC2MIME(uint32_t fourcc)1276 static const char *MKVFourCC2MIME(uint32_t fourcc) {
1277 ALOGV("MKVFourCC2MIME fourcc 0x%8.8x", fourcc);
1278 uint32_t lowerFourcc = FourCCtoLower(fourcc);
1279 switch (lowerFourcc) {
1280 case FOURCC("mp4v"):
1281 return MEDIA_MIMETYPE_VIDEO_MPEG4;
1282
1283 case FOURCC("s263"):
1284 case FOURCC("h263"):
1285 return MEDIA_MIMETYPE_VIDEO_H263;
1286
1287 case FOURCC("avc1"):
1288 case FOURCC("h264"):
1289 return MEDIA_MIMETYPE_VIDEO_AVC;
1290
1291 case FOURCC("mpg2"):
1292 return MEDIA_MIMETYPE_VIDEO_MPEG2;
1293
1294 case FOURCC("xvid"):
1295 return MEDIA_MIMETYPE_VIDEO_XVID;
1296
1297 case FOURCC("divx"):
1298 case FOURCC("dx50"):
1299 return MEDIA_MIMETYPE_VIDEO_DIVX;
1300
1301 case FOURCC("div3"):
1302 case FOURCC("div4"):
1303 return MEDIA_MIMETYPE_VIDEO_DIVX3;
1304
1305 case FOURCC("mjpg"):
1306 case FOURCC("mppg"):
1307 return MEDIA_MIMETYPE_VIDEO_MJPEG;
1308
1309 default:
1310 char fourccString[5];
1311 MakeFourCCString(fourcc, fourccString);
1312 ALOGW("mkv unsupport fourcc %s", fourccString);
1313 return "";
1314 }
1315 }
1316
1317
MatroskaExtractor(DataSourceHelper * source)1318 MatroskaExtractor::MatroskaExtractor(DataSourceHelper *source)
1319 : mDataSource(source),
1320 mReader(new DataSourceBaseReader(mDataSource)),
1321 mSegment(NULL),
1322 mExtractedThumbnails(false),
1323 mIsWebm(false),
1324 mSeekPreRollNs(0) {
1325 off64_t size;
1326 mIsLiveStreaming =
1327 (mDataSource->flags()
1328 & (DataSourceBase::kWantsPrefetching
1329 | DataSourceBase::kIsCachingDataSource))
1330 && mDataSource->getSize(&size) != OK;
1331
1332 mkvparser::EBMLHeader ebmlHeader;
1333 long long pos;
1334 if (ebmlHeader.Parse(mReader, pos) < 0) {
1335 return;
1336 }
1337
1338 if (ebmlHeader.m_docType && !strcmp("webm", ebmlHeader.m_docType)) {
1339 mIsWebm = true;
1340 }
1341
1342 long long ret =
1343 mkvparser::Segment::CreateInstance(mReader, pos, mSegment);
1344
1345 if (ret) {
1346 CHECK(mSegment == NULL);
1347 return;
1348 }
1349
1350 if (mIsLiveStreaming) {
1351 // from mkvparser::Segment::Load(), but stop at first cluster
1352 ret = mSegment->ParseHeaders();
1353 if (ret == 0) {
1354 long len;
1355 ret = mSegment->LoadCluster(pos, len);
1356 if (ret >= 1) {
1357 // no more clusters
1358 ret = 0;
1359 }
1360 } else if (ret > 0) {
1361 ret = mkvparser::E_BUFFER_NOT_FULL;
1362 }
1363 } else {
1364 ret = mSegment->ParseHeaders();
1365 if (ret < 0) {
1366 ALOGE("Segment parse header return fail %lld", ret);
1367 delete mSegment;
1368 mSegment = NULL;
1369 return;
1370 } else if (ret == 0) {
1371 const mkvparser::Cues* mCues = mSegment->GetCues();
1372 const mkvparser::SeekHead* mSH = mSegment->GetSeekHead();
1373 if ((mCues == NULL) && (mSH != NULL)) {
1374 size_t count = mSH->GetCount();
1375 const mkvparser::SeekHead::Entry* mEntry;
1376 for (size_t index = 0; index < count; index++) {
1377 mEntry = mSH->GetEntry(index);
1378 if (mEntry->id == libwebm::kMkvCues) { // Cues ID
1379 long len;
1380 long long pos;
1381 mSegment->ParseCues(mEntry->pos, pos, len);
1382 mCues = mSegment->GetCues();
1383 ALOGV("find cue data by seekhead");
1384 break;
1385 }
1386 }
1387 }
1388
1389 if (mCues) {
1390 long len;
1391 ret = mSegment->LoadCluster(pos, len);
1392 ALOGV("has Cue data, Cluster num=%ld", mSegment->GetCount());
1393 } else {
1394 long status_Load = mSegment->Load();
1395 ALOGW("no Cue data,Segment Load status:%ld",status_Load);
1396 }
1397 } else if (ret > 0) {
1398 ret = mkvparser::E_BUFFER_NOT_FULL;
1399 }
1400 }
1401
1402 if (ret < 0) {
1403 char uri[1024];
1404 if(!mDataSource->getUri(uri, sizeof(uri))) {
1405 uri[0] = '\0';
1406 }
1407 ALOGW("Corrupt %s source: %s", mIsWebm ? "webm" : "matroska",
1408 uriDebugString(uri).c_str());
1409 delete mSegment;
1410 mSegment = NULL;
1411 return;
1412 }
1413
1414 #if 0
1415 const mkvparser::SegmentInfo *info = mSegment->GetInfo();
1416 ALOGI("muxing app: %s, writing app: %s",
1417 info->GetMuxingAppAsUTF8(),
1418 info->GetWritingAppAsUTF8());
1419 #endif
1420
1421 addTracks();
1422 }
1423
~MatroskaExtractor()1424 MatroskaExtractor::~MatroskaExtractor() {
1425 delete mSegment;
1426 mSegment = NULL;
1427
1428 delete mReader;
1429 mReader = NULL;
1430
1431 delete mDataSource;
1432
1433 for (size_t i = 0; i < mTracks.size(); ++i) {
1434 TrackInfo *info = &mTracks.editItemAt(i);
1435 if (info->mMeta) {
1436 AMediaFormat_delete(info->mMeta);
1437 }
1438 }
1439 }
1440
countTracks()1441 size_t MatroskaExtractor::countTracks() {
1442 return mTracks.size();
1443 }
1444
getTrack(size_t index)1445 MediaTrackHelper *MatroskaExtractor::getTrack(size_t index) {
1446 if (index >= mTracks.size()) {
1447 return NULL;
1448 }
1449
1450 return new MatroskaSource(this, index);
1451 }
1452
getTrackMetaData(AMediaFormat * meta,size_t index,uint32_t flags)1453 media_status_t MatroskaExtractor::getTrackMetaData(
1454 AMediaFormat *meta,
1455 size_t index, uint32_t flags) {
1456 if (index >= mTracks.size()) {
1457 return AMEDIA_ERROR_UNKNOWN;
1458 }
1459
1460 if ((flags & kIncludeExtensiveMetaData) && !mExtractedThumbnails
1461 && !isLiveStreaming()) {
1462 findThumbnails();
1463 mExtractedThumbnails = true;
1464 }
1465
1466 return AMediaFormat_copy(meta, mTracks.itemAt(index).mMeta);
1467 }
1468
isLiveStreaming() const1469 bool MatroskaExtractor::isLiveStreaming() const {
1470 return mIsLiveStreaming;
1471 }
1472
bytesForSize(size_t size)1473 static int bytesForSize(size_t size) {
1474 // use at most 28 bits (4 times 7)
1475 CHECK(size <= 0xfffffff);
1476
1477 if (size > 0x1fffff) {
1478 return 4;
1479 } else if (size > 0x3fff) {
1480 return 3;
1481 } else if (size > 0x7f) {
1482 return 2;
1483 }
1484 return 1;
1485 }
1486
storeSize(uint8_t * data,size_t & idx,size_t size)1487 static void storeSize(uint8_t *data, size_t &idx, size_t size) {
1488 int numBytes = bytesForSize(size);
1489 idx += numBytes;
1490
1491 data += idx;
1492 size_t next = 0;
1493 while (numBytes--) {
1494 *--data = (size & 0x7f) | next;
1495 size >>= 7;
1496 next = 0x80;
1497 }
1498 }
1499
addESDSFromCodecPrivate(AMediaFormat * meta,bool isAudio,const void * priv,size_t privSize)1500 static void addESDSFromCodecPrivate(
1501 AMediaFormat *meta,
1502 bool isAudio, const void *priv, size_t privSize) {
1503
1504 int privSizeBytesRequired = bytesForSize(privSize);
1505 int esdsSize2 = 14 + privSizeBytesRequired + privSize;
1506 int esdsSize2BytesRequired = bytesForSize(esdsSize2);
1507 int esdsSize1 = 4 + esdsSize2BytesRequired + esdsSize2;
1508 int esdsSize1BytesRequired = bytesForSize(esdsSize1);
1509 size_t esdsSize = 1 + esdsSize1BytesRequired + esdsSize1;
1510 uint8_t *esds = new uint8_t[esdsSize];
1511
1512 size_t idx = 0;
1513 esds[idx++] = 0x03;
1514 storeSize(esds, idx, esdsSize1);
1515 esds[idx++] = 0x00; // ES_ID
1516 esds[idx++] = 0x00; // ES_ID
1517 esds[idx++] = 0x00; // streamDependenceFlag, URL_Flag, OCRstreamFlag
1518 esds[idx++] = 0x04;
1519 storeSize(esds, idx, esdsSize2);
1520 esds[idx++] = isAudio ? 0x40 // Audio ISO/IEC 14496-3
1521 : 0x20; // Visual ISO/IEC 14496-2
1522 for (int i = 0; i < 12; i++) {
1523 esds[idx++] = 0x00;
1524 }
1525 esds[idx++] = 0x05;
1526 storeSize(esds, idx, privSize);
1527 memcpy(esds + idx, priv, privSize);
1528
1529 AMediaFormat_setBuffer(meta, AMEDIAFORMAT_KEY_CSD_0, priv, privSize);
1530
1531 delete[] esds;
1532 esds = NULL;
1533 }
1534
addVorbisCodecInfo(AMediaFormat * meta,const void * _codecPrivate,size_t codecPrivateSize)1535 status_t addVorbisCodecInfo(
1536 AMediaFormat *meta,
1537 const void *_codecPrivate, size_t codecPrivateSize) {
1538 // hexdump(_codecPrivate, codecPrivateSize);
1539
1540 if (codecPrivateSize < 1) {
1541 return ERROR_MALFORMED;
1542 }
1543
1544 const uint8_t *codecPrivate = (const uint8_t *)_codecPrivate;
1545
1546 if (codecPrivate[0] != 0x02) {
1547 return ERROR_MALFORMED;
1548 }
1549
1550 // codecInfo starts with two lengths, len1 and len2, that are
1551 // "Xiph-style-lacing encoded"...
1552
1553 size_t offset = 1;
1554 size_t len1 = 0;
1555 while (offset < codecPrivateSize && codecPrivate[offset] == 0xff) {
1556 if (len1 > (SIZE_MAX - 0xff)) {
1557 return ERROR_MALFORMED; // would overflow
1558 }
1559 len1 += 0xff;
1560 ++offset;
1561 }
1562 if (offset >= codecPrivateSize) {
1563 return ERROR_MALFORMED;
1564 }
1565 if (len1 > (SIZE_MAX - codecPrivate[offset])) {
1566 return ERROR_MALFORMED; // would overflow
1567 }
1568 len1 += codecPrivate[offset++];
1569
1570 size_t len2 = 0;
1571 while (offset < codecPrivateSize && codecPrivate[offset] == 0xff) {
1572 if (len2 > (SIZE_MAX - 0xff)) {
1573 return ERROR_MALFORMED; // would overflow
1574 }
1575 len2 += 0xff;
1576 ++offset;
1577 }
1578 if (offset >= codecPrivateSize) {
1579 return ERROR_MALFORMED;
1580 }
1581 if (len2 > (SIZE_MAX - codecPrivate[offset])) {
1582 return ERROR_MALFORMED; // would overflow
1583 }
1584 len2 += codecPrivate[offset++];
1585
1586 if (len1 > SIZE_MAX - len2 || offset > SIZE_MAX - (len1 + len2) ||
1587 codecPrivateSize < offset + len1 + len2) {
1588 return ERROR_MALFORMED;
1589 }
1590
1591 if (codecPrivate[offset] != 0x01) {
1592 return ERROR_MALFORMED;
1593 }
1594 // formerly kKeyVorbisInfo
1595 AMediaFormat_setBuffer(meta, AMEDIAFORMAT_KEY_CSD_0, &codecPrivate[offset], len1);
1596
1597 offset += len1;
1598 if (codecPrivate[offset] != 0x03) {
1599 return ERROR_MALFORMED;
1600 }
1601
1602 offset += len2;
1603 if (codecPrivate[offset] != 0x05) {
1604 return ERROR_MALFORMED;
1605 }
1606
1607 // formerly kKeyVorbisBooks
1608 AMediaFormat_setBuffer(meta, AMEDIAFORMAT_KEY_CSD_1,
1609 &codecPrivate[offset], codecPrivateSize - offset);
1610
1611 return OK;
1612 }
1613
addFlacMetadata(AMediaFormat * meta,const void * codecPrivate,size_t codecPrivateSize)1614 static status_t addFlacMetadata(
1615 AMediaFormat *meta,
1616 const void *codecPrivate, size_t codecPrivateSize) {
1617 // hexdump(codecPrivate, codecPrivateSize);
1618
1619 // formerly kKeyFlacMetadata
1620 AMediaFormat_setBuffer(meta, AMEDIAFORMAT_KEY_CSD_0, codecPrivate, codecPrivateSize);
1621
1622 int32_t maxInputSize = 64 << 10;
1623 FLACDecoder *flacDecoder = FLACDecoder::Create();
1624 if (flacDecoder != NULL
1625 && flacDecoder->parseMetadata((const uint8_t*)codecPrivate, codecPrivateSize) == OK) {
1626 FLAC__StreamMetadata_StreamInfo streamInfo = flacDecoder->getStreamInfo();
1627 maxInputSize = streamInfo.max_framesize;
1628 if (maxInputSize == 0) {
1629 // In case max framesize is not available, use raw data size as max framesize,
1630 // assuming there is no expansion.
1631 if (streamInfo.max_blocksize != 0
1632 && streamInfo.channels != 0
1633 && ((streamInfo.bits_per_sample + 7) / 8) >
1634 INT32_MAX / streamInfo.max_blocksize / streamInfo.channels) {
1635 delete flacDecoder;
1636 return ERROR_MALFORMED;
1637 }
1638 maxInputSize = ((streamInfo.bits_per_sample + 7) / 8)
1639 * streamInfo.max_blocksize * streamInfo.channels;
1640 }
1641 }
1642 AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_MAX_INPUT_SIZE, maxInputSize);
1643
1644 delete flacDecoder;
1645 return OK;
1646 }
1647
synthesizeAVCC(TrackInfo * trackInfo,size_t index)1648 status_t MatroskaExtractor::synthesizeAVCC(TrackInfo *trackInfo, size_t index) {
1649 BlockIterator iter(this, trackInfo->mTrackNum, index);
1650 if (iter.eos()) {
1651 return ERROR_MALFORMED;
1652 }
1653
1654 const mkvparser::Block *block = iter.block();
1655 if (block->GetFrameCount() <= 0) {
1656 return ERROR_MALFORMED;
1657 }
1658
1659 const mkvparser::Block::Frame &frame = block->GetFrame(0);
1660 auto tmpData = heapbuffer<unsigned char>(frame.len);
1661 long n = frame.Read(mReader, tmpData.get());
1662 if (n != 0) {
1663 return ERROR_MALFORMED;
1664 }
1665
1666 if (!MakeAVCCodecSpecificData(trackInfo->mMeta, tmpData.get(), frame.len)) {
1667 return ERROR_MALFORMED;
1668 }
1669
1670 // Override the synthesized nal length size, which is arbitrary
1671 trackInfo->mNalLengthSize = 0;
1672 return OK;
1673 }
1674
synthesizeMPEG2(TrackInfo * trackInfo,size_t index)1675 status_t MatroskaExtractor::synthesizeMPEG2(TrackInfo *trackInfo, size_t index) {
1676 ALOGV("synthesizeMPEG2");
1677 BlockIterator iter(this, trackInfo->mTrackNum, index);
1678 if (iter.eos()) {
1679 return ERROR_MALFORMED;
1680 }
1681
1682 const mkvparser::Block *block = iter.block();
1683 if (block->GetFrameCount() <= 0) {
1684 return ERROR_MALFORMED;
1685 }
1686
1687 const mkvparser::Block::Frame &frame = block->GetFrame(0);
1688 auto tmpData = heapbuffer<unsigned char>(frame.len);
1689 long n = frame.Read(mReader, tmpData.get());
1690 if (n != 0) {
1691 return ERROR_MALFORMED;
1692 }
1693
1694 size_t header_start = 0;
1695 size_t header_lenth = 0;
1696 for (header_start = 0; header_start < frame.len - 4; header_start++) {
1697 if (ntohl(0x000001b3) == *(uint32_t*)((uint8_t*)tmpData.get() + header_start)) {
1698 break;
1699 }
1700 }
1701 bool isComplete_csd = false;
1702 for (header_lenth = 0; header_lenth < frame.len - 4 - header_start; header_lenth++) {
1703 if (ntohl(0x000001b8) == *(uint32_t*)((uint8_t*)tmpData.get()
1704 + header_start + header_lenth)) {
1705 isComplete_csd = true;
1706 break;
1707 }
1708 }
1709 if (!isComplete_csd) {
1710 ALOGE("can't parse complete csd for MPEG2!");
1711 return ERROR_MALFORMED;
1712 }
1713 addESDSFromCodecPrivate(trackInfo->mMeta, false,
1714 (uint8_t*)(tmpData.get()) + header_start, header_lenth);
1715
1716 return OK;
1717
1718 }
1719
synthesizeMPEG4(TrackInfo * trackInfo,size_t index)1720 status_t MatroskaExtractor::synthesizeMPEG4(TrackInfo *trackInfo, size_t index) {
1721 ALOGV("synthesizeMPEG4");
1722 BlockIterator iter(this, trackInfo->mTrackNum, index);
1723 if (iter.eos()) {
1724 return ERROR_MALFORMED;
1725 }
1726
1727 const mkvparser::Block *block = iter.block();
1728 if (block->GetFrameCount() <= 0) {
1729 return ERROR_MALFORMED;
1730 }
1731
1732 const mkvparser::Block::Frame &frame = block->GetFrame(0);
1733 auto tmpData = heapbuffer<unsigned char>(frame.len);
1734 long n = frame.Read(mReader, tmpData.get());
1735 if (n != 0) {
1736 return ERROR_MALFORMED;
1737 }
1738
1739 size_t vosend;
1740 bool isComplete_csd = false;
1741 for (vosend = 0; (long)vosend < frame.len - 4; vosend++) {
1742 if (ntohl(0x000001b6) == *(uint32_t*)((uint8_t*)tmpData.get() + vosend)) {
1743 isComplete_csd = true;
1744 break; // Send VOS until VOP
1745 }
1746 }
1747 if (!isComplete_csd) {
1748 ALOGE("can't parse complete csd for MPEG4!");
1749 return ERROR_MALFORMED;
1750 }
1751 addESDSFromCodecPrivate(trackInfo->mMeta, false, tmpData.get(), vosend);
1752
1753 return OK;
1754
1755 }
1756
1757
isValidInt32ColourValue(long long value)1758 static inline bool isValidInt32ColourValue(long long value) {
1759 return value != mkvparser::Colour::kValueNotPresent
1760 && value >= INT32_MIN
1761 && value <= INT32_MAX;
1762 }
1763
isValidUint16ColourValue(long long value)1764 static inline bool isValidUint16ColourValue(long long value) {
1765 return value != mkvparser::Colour::kValueNotPresent
1766 && value >= 0
1767 && value <= UINT16_MAX;
1768 }
1769
isValidPrimary(const mkvparser::PrimaryChromaticity * primary)1770 static inline bool isValidPrimary(const mkvparser::PrimaryChromaticity *primary) {
1771 return primary != NULL && primary->x >= 0 && primary->x <= 1
1772 && primary->y >= 0 && primary->y <= 1;
1773 }
1774
getColorInformation(const mkvparser::VideoTrack * vtrack,AMediaFormat * meta)1775 void MatroskaExtractor::getColorInformation(
1776 const mkvparser::VideoTrack *vtrack, AMediaFormat *meta) {
1777 const mkvparser::Colour *color = vtrack->GetColour();
1778 if (color == NULL) {
1779 return;
1780 }
1781
1782 // Color Aspects
1783 {
1784 int32_t primaries = 2; // ISO unspecified
1785 int32_t isotransfer = 2; // ISO unspecified
1786 int32_t coeffs = 2; // ISO unspecified
1787 bool fullRange = false; // default
1788 bool rangeSpecified = false;
1789
1790 if (isValidInt32ColourValue(color->primaries)) {
1791 primaries = color->primaries;
1792 }
1793 if (isValidInt32ColourValue(color->transfer_characteristics)) {
1794 isotransfer = color->transfer_characteristics;
1795 }
1796 if (isValidInt32ColourValue(color->matrix_coefficients)) {
1797 coeffs = color->matrix_coefficients;
1798 }
1799 if (color->range != mkvparser::Colour::kValueNotPresent
1800 && color->range != 0 /* MKV unspecified */) {
1801 // We only support MKV broadcast range (== limited) and full range.
1802 // We treat all other value as the default limited range.
1803 fullRange = color->range == 2 /* MKV fullRange */;
1804 rangeSpecified = true;
1805 }
1806
1807 int32_t range = 0;
1808 int32_t standard = 0;
1809 int32_t transfer = 0;
1810 ColorUtils::convertIsoColorAspectsToPlatformAspects(
1811 primaries, isotransfer, coeffs, fullRange,
1812 &range, &standard, &transfer);
1813 if (range != 0) {
1814 AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_COLOR_RANGE, range);
1815 }
1816 if (standard != 0) {
1817 AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_COLOR_STANDARD, standard);
1818 }
1819 if (transfer != 0) {
1820 AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_COLOR_TRANSFER, transfer);
1821 }
1822 }
1823
1824 // HDR Static Info
1825 {
1826 HDRStaticInfo info, nullInfo; // nullInfo is a fully unspecified static info
1827 memset(&info, 0, sizeof(info));
1828 memset(&nullInfo, 0, sizeof(nullInfo));
1829 if (isValidUint16ColourValue(color->max_cll)) {
1830 info.sType1.mMaxContentLightLevel = color->max_cll;
1831 }
1832 if (isValidUint16ColourValue(color->max_fall)) {
1833 info.sType1.mMaxFrameAverageLightLevel = color->max_fall;
1834 }
1835 const mkvparser::MasteringMetadata *mastering = color->mastering_metadata;
1836 if (mastering != NULL) {
1837 // Convert matroska values to HDRStaticInfo equivalent values for each fully specified
1838 // group. See CTA-681.3 section 3.2.1 for more info.
1839 if (mastering->luminance_max >= 0.5 && mastering->luminance_max < 65535.5) {
1840 info.sType1.mMaxDisplayLuminance = (uint16_t)(mastering->luminance_max + 0.5);
1841 }
1842 if (mastering->luminance_min >= 0.00005 && mastering->luminance_min < 6.55355) {
1843 // HDRStaticInfo Type1 stores min luminance scaled 10000:1
1844 info.sType1.mMinDisplayLuminance =
1845 (uint16_t)(10000 * mastering->luminance_min + 0.5);
1846 }
1847 // HDRStaticInfo Type1 stores primaries scaled 50000:1
1848 if (isValidPrimary(mastering->white_point)) {
1849 info.sType1.mW.x = (uint16_t)(50000 * mastering->white_point->x + 0.5);
1850 info.sType1.mW.y = (uint16_t)(50000 * mastering->white_point->y + 0.5);
1851 }
1852 if (isValidPrimary(mastering->r) && isValidPrimary(mastering->g)
1853 && isValidPrimary(mastering->b)) {
1854 info.sType1.mR.x = (uint16_t)(50000 * mastering->r->x + 0.5);
1855 info.sType1.mR.y = (uint16_t)(50000 * mastering->r->y + 0.5);
1856 info.sType1.mG.x = (uint16_t)(50000 * mastering->g->x + 0.5);
1857 info.sType1.mG.y = (uint16_t)(50000 * mastering->g->y + 0.5);
1858 info.sType1.mB.x = (uint16_t)(50000 * mastering->b->x + 0.5);
1859 info.sType1.mB.y = (uint16_t)(50000 * mastering->b->y + 0.5);
1860 }
1861 }
1862 // Only advertise static info if at least one of the groups have been specified.
1863 if (memcmp(&info, &nullInfo, sizeof(info)) != 0) {
1864 info.mID = HDRStaticInfo::kType1;
1865 ColorUtils::setHDRStaticInfoIntoAMediaFormat(info, meta);
1866 }
1867 }
1868 }
1869
initTrackInfo(const mkvparser::Track * track,AMediaFormat * meta,TrackInfo * trackInfo)1870 status_t MatroskaExtractor::initTrackInfo(
1871 const mkvparser::Track *track, AMediaFormat *meta, TrackInfo *trackInfo) {
1872 trackInfo->mTrackNum = track->GetNumber();
1873 trackInfo->mMeta = meta;
1874 trackInfo->mExtractor = this;
1875 trackInfo->mEncrypted = false;
1876 trackInfo->mHeader = NULL;
1877 trackInfo->mHeaderLen = 0;
1878 trackInfo->mNalLengthSize = -1;
1879
1880 for(size_t i = 0; i < track->GetContentEncodingCount(); i++) {
1881 const mkvparser::ContentEncoding *encoding = track->GetContentEncodingByIndex(i);
1882 if (encoding->GetEncryptionCount() > 0) {
1883 const mkvparser::ContentEncoding::ContentEncryption *encryption;
1884 encryption = encoding->GetEncryptionByIndex(0);
1885 AMediaFormat_setBuffer(trackInfo->mMeta,
1886 AMEDIAFORMAT_KEY_CRYPTO_KEY, encryption->key_id, encryption->key_id_len);
1887 trackInfo->mEncrypted = true;
1888 }
1889
1890 for(size_t j = 0; j < encoding->GetCompressionCount(); j++) {
1891 const mkvparser::ContentEncoding::ContentCompression *compression;
1892 compression = encoding->GetCompressionByIndex(j);
1893 ALOGV("compression algo %llu settings_len %lld",
1894 compression->algo, compression->settings_len);
1895 if (compression->algo == 3
1896 && compression->settings
1897 && compression->settings_len > 0) {
1898 trackInfo->mHeader = compression->settings;
1899 trackInfo->mHeaderLen = compression->settings_len;
1900 }
1901 }
1902 }
1903
1904 return OK;
1905 }
1906
addTracks()1907 void MatroskaExtractor::addTracks() {
1908 const mkvparser::Tracks *tracks = mSegment->GetTracks();
1909
1910 AMediaFormat *meta = nullptr;
1911
1912 for (size_t index = 0; index < tracks->GetTracksCount(); ++index) {
1913 const mkvparser::Track *track = tracks->GetTrackByIndex(index);
1914
1915 if (track == NULL) {
1916 // Apparently this is currently valid (if unexpected) behaviour
1917 // of the mkv parser lib.
1918 continue;
1919 }
1920
1921 const char *const codecID = track->GetCodecId();
1922 ALOGV("codec id = %s", codecID);
1923 ALOGV("codec name = %s", track->GetCodecNameAsUTF8());
1924
1925 if (codecID == NULL) {
1926 ALOGW("unknown codecID is not supported.");
1927 continue;
1928 }
1929
1930 size_t codecPrivateSize;
1931 const unsigned char *codecPrivate =
1932 track->GetCodecPrivate(codecPrivateSize);
1933
1934 enum { VIDEO_TRACK = 1, AUDIO_TRACK = 2 };
1935
1936 if (meta) {
1937 AMediaFormat_clear(meta);
1938 } else {
1939 meta = AMediaFormat_new();
1940 }
1941
1942 status_t err = OK;
1943 int32_t nalSize = -1;
1944
1945 bool isSetCsdFrom1stFrame = false;
1946
1947 switch (track->GetType()) {
1948 case VIDEO_TRACK:
1949 {
1950 const mkvparser::VideoTrack *vtrack =
1951 static_cast<const mkvparser::VideoTrack *>(track);
1952
1953 if (!strcmp("V_MPEG4/ISO/AVC", codecID)) {
1954 AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_VIDEO_AVC);
1955 AMediaFormat_setBuffer(meta,
1956 AMEDIAFORMAT_KEY_CSD_AVC, codecPrivate, codecPrivateSize);
1957 if (codecPrivateSize > 4) {
1958 nalSize = 1 + (codecPrivate[4] & 3);
1959 }
1960 } else if (!strcmp("V_MPEGH/ISO/HEVC", codecID)) {
1961 AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_VIDEO_HEVC);
1962 if (codecPrivateSize > 0) {
1963 AMediaFormat_setBuffer(meta,
1964 AMEDIAFORMAT_KEY_CSD_HEVC, codecPrivate, codecPrivateSize);
1965 if (codecPrivateSize > 14 + 7) {
1966 nalSize = 1 + (codecPrivate[14 + 7] & 3);
1967 }
1968 } else {
1969 ALOGW("HEVC is detected, but does not have configuration.");
1970 continue;
1971 }
1972 } else if (!strcmp("V_MPEG4/ISO/ASP", codecID)) {
1973 AMediaFormat_setString(meta,
1974 AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_VIDEO_MPEG4);
1975 if (codecPrivateSize > 0) {
1976 addESDSFromCodecPrivate(
1977 meta, false, codecPrivate, codecPrivateSize);
1978 } else {
1979 ALOGW("%s is detected, but does not have configuration.",
1980 codecID);
1981 isSetCsdFrom1stFrame = true;
1982 }
1983 } else if (!strcmp("V_VP8", codecID)) {
1984 AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_VIDEO_VP8);
1985 } else if (!strcmp("V_VP9", codecID)) {
1986 AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_VIDEO_VP9);
1987 if (codecPrivateSize > 0) {
1988 // 'csd-0' for VP9 is the Blob of Codec Private data as
1989 // specified in http://www.webmproject.org/vp9/profiles/.
1990 AMediaFormat_setBuffer(meta,
1991 AMEDIAFORMAT_KEY_CSD_0, codecPrivate, codecPrivateSize);
1992 }
1993 } else if (!strcmp("V_AV1", codecID)) {
1994 AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_VIDEO_AV1);
1995 if (codecPrivateSize > 0) {
1996 // 'csd-0' for AV1 is the Blob of Codec Private data as
1997 // specified in https://aomediacodec.github.io/av1-isobmff/.
1998 AMediaFormat_setBuffer(
1999 meta, AMEDIAFORMAT_KEY_CSD_0, codecPrivate, codecPrivateSize);
2000 }
2001 } else if (!strcmp("V_MPEG2", codecID) || !strcmp("V_MPEG1", codecID)) {
2002 AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME,
2003 MEDIA_MIMETYPE_VIDEO_MPEG2);
2004 if (codecPrivate != NULL) {
2005 addESDSFromCodecPrivate(meta, false, codecPrivate, codecPrivateSize);
2006 } else {
2007 ALOGW("No specific codec private data, find it from the first frame");
2008 isSetCsdFrom1stFrame = true;
2009 }
2010 } else if (!strcmp("V_MJPEG", codecID)) {
2011 AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME,
2012 MEDIA_MIMETYPE_VIDEO_MJPEG);
2013 } else if (!strcmp("V_MS/VFW/FOURCC", codecID)) {
2014 if (NULL == codecPrivate ||codecPrivateSize < 20) {
2015 ALOGE("V_MS/VFW/FOURCC has no valid private data(%p),codecPrivateSize:%zu",
2016 codecPrivate, codecPrivateSize);
2017 continue;
2018 } else {
2019 uint32_t fourcc = *(uint32_t *)(codecPrivate + 16);
2020 fourcc = ntohl(fourcc);
2021 const char* mime = MKVFourCC2MIME(fourcc);
2022 ALOGV("V_MS/VFW/FOURCC type is %s", mime);
2023 if (!strncasecmp("video/", mime, 6)) {
2024 AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, mime);
2025 } else {
2026 ALOGE("V_MS/VFW/FOURCC continue,unsupport video type=%s,fourcc=0x%08x.",
2027 mime, fourcc);
2028 continue;
2029 }
2030 if (!strcmp(mime, MEDIA_MIMETYPE_VIDEO_AVC) ||
2031 !strcmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
2032 !strcmp(mime, MEDIA_MIMETYPE_VIDEO_XVID) ||
2033 !strcmp(mime, MEDIA_MIMETYPE_VIDEO_DIVX) ||
2034 !strcmp(mime, MEDIA_MIMETYPE_VIDEO_DIVX3) ||
2035 !strcmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG2) ||
2036 !strcmp(mime, MEDIA_MIMETYPE_VIDEO_H263)) {
2037 isSetCsdFrom1stFrame = true;
2038 } else {
2039 ALOGW("FourCC have unsupport codec, type=%s,fourcc=0x%08x.",
2040 mime, fourcc);
2041 continue;
2042 }
2043 }
2044 } else {
2045 ALOGW("%s is not supported.", codecID);
2046 continue;
2047 }
2048
2049 const long long width = vtrack->GetWidth();
2050 const long long height = vtrack->GetHeight();
2051 if (width <= 0 || width > INT32_MAX) {
2052 ALOGW("track width exceeds int32_t, %lld", width);
2053 continue;
2054 }
2055 if (height <= 0 || height > INT32_MAX) {
2056 ALOGW("track height exceeds int32_t, %lld", height);
2057 continue;
2058 }
2059 AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_WIDTH, (int32_t)width);
2060 AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_HEIGHT, (int32_t)height);
2061
2062 // setting display width/height is optional
2063 const long long displayUnit = vtrack->GetDisplayUnit();
2064 const long long displayWidth = vtrack->GetDisplayWidth();
2065 const long long displayHeight = vtrack->GetDisplayHeight();
2066 if (displayWidth > 0 && displayWidth <= INT32_MAX
2067 && displayHeight > 0 && displayHeight <= INT32_MAX) {
2068 switch (displayUnit) {
2069 case 0: // pixels
2070 AMediaFormat_setInt32(meta,
2071 AMEDIAFORMAT_KEY_DISPLAY_WIDTH, (int32_t)displayWidth);
2072 AMediaFormat_setInt32(meta,
2073 AMEDIAFORMAT_KEY_DISPLAY_HEIGHT, (int32_t)displayHeight);
2074 break;
2075 case 1: // centimeters
2076 case 2: // inches
2077 case 3: // aspect ratio
2078 {
2079 // Physical layout size is treated the same as aspect ratio.
2080 // Note: displayWidth and displayHeight are never zero as they are
2081 // checked in the if above.
2082 const long long computedWidth =
2083 std::max(width, height * displayWidth / displayHeight);
2084 const long long computedHeight =
2085 std::max(height, width * displayHeight / displayWidth);
2086 if (computedWidth <= INT32_MAX && computedHeight <= INT32_MAX) {
2087 AMediaFormat_setInt32(meta,
2088 AMEDIAFORMAT_KEY_DISPLAY_WIDTH, (int32_t)computedWidth);
2089 AMediaFormat_setInt32(meta,
2090 AMEDIAFORMAT_KEY_DISPLAY_HEIGHT, (int32_t)computedHeight);
2091 }
2092 break;
2093 }
2094 default: // unknown display units, perhaps future version of spec.
2095 break;
2096 }
2097 }
2098
2099 getColorInformation(vtrack, meta);
2100
2101 break;
2102 }
2103
2104 case AUDIO_TRACK:
2105 {
2106 const mkvparser::AudioTrack *atrack =
2107 static_cast<const mkvparser::AudioTrack *>(track);
2108
2109 if (!strcmp("A_AAC", codecID)) {
2110 AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_AAC);
2111 if (codecPrivateSize < 2) {
2112 ALOGW("Incomplete AAC Codec Info %zu byte", codecPrivateSize);
2113 continue;
2114 }
2115 addESDSFromCodecPrivate(
2116 meta, true, codecPrivate, codecPrivateSize);
2117 } else if (!strcmp("A_VORBIS", codecID)) {
2118 AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_VORBIS);
2119
2120 err = addVorbisCodecInfo(
2121 meta, codecPrivate, codecPrivateSize);
2122 } else if (!strcmp("A_OPUS", codecID)) {
2123 AMediaFormat_setString(meta,
2124 AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_OPUS);
2125 AMediaFormat_setBuffer(meta,
2126 AMEDIAFORMAT_KEY_CSD_0, codecPrivate, codecPrivateSize);
2127 int64_t codecDelay = track->GetCodecDelay();
2128 AMediaFormat_setBuffer(meta,
2129 AMEDIAFORMAT_KEY_CSD_1, &codecDelay, sizeof(codecDelay));
2130 mSeekPreRollNs = track->GetSeekPreRoll();
2131 AMediaFormat_setBuffer(meta,
2132 AMEDIAFORMAT_KEY_CSD_2, &mSeekPreRollNs, sizeof(mSeekPreRollNs));
2133 } else if (!strcmp("A_MPEG/L3", codecID)) {
2134 AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_MPEG);
2135 } else if (!strcmp("A_FLAC", codecID)) {
2136 AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_FLAC);
2137 err = addFlacMetadata(meta, codecPrivate, codecPrivateSize);
2138 } else if (!strcmp("A_MPEG/L2", codecID)) {
2139 AMediaFormat_setString(meta,
2140 AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II);
2141 } else if (!strcmp("A_PCM/INT/LIT", codecID) ||
2142 !strcmp("A_PCM/INT/BIG", codecID)) {
2143 AMediaFormat_setString(meta,
2144 AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_RAW);
2145 int32_t bigEndian = !strcmp("A_PCM/INT/BIG", codecID) ? 1: 0;
2146 AMediaFormat_setInt32(meta,
2147 AMEDIAFORMAT_KEY_PCM_BIG_ENDIAN, bigEndian);
2148 } else if ((!strcmp("A_MS/ACM", codecID))) {
2149 if ((NULL == codecPrivate) || (codecPrivateSize < 18)) {
2150 ALOGW("unsupported audio: A_MS/ACM has no valid private data: %s, size: %zu",
2151 codecPrivate == NULL ? "null" : "non-null", codecPrivateSize);
2152 continue;
2153 } else {
2154 uint16_t ID = *(uint16_t *)codecPrivate;
2155 const char* mime = MKVWave2MIME(ID);
2156 ALOGV("A_MS/ACM type is %s", mime);
2157 if (!strncasecmp("audio/", mime, 6) &&
2158 isMkvAudioCsdSizeOK(mime, codecPrivateSize)) {
2159 AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, mime);
2160 } else {
2161 ALOGE("A_MS/ACM continue, unsupported audio type=%s, csdSize:%zu",
2162 mime, codecPrivateSize);
2163 continue;
2164 }
2165 if (!strcmp(mime, MEDIA_MIMETYPE_AUDIO_WMA)) {
2166 addESDSFromCodecPrivate(meta, true, codecPrivate, codecPrivateSize);
2167 } else if (!strcmp(mime, MEDIA_MIMETYPE_AUDIO_MS_ADPCM) ||
2168 !strcmp(mime, MEDIA_MIMETYPE_AUDIO_DVI_IMA_ADPCM)) {
2169 uint32_t blockAlign = *(uint16_t*)(codecPrivate + 12);
2170 addESDSFromCodecPrivate(meta, true, &blockAlign, sizeof(blockAlign));
2171 }
2172 }
2173 } else {
2174 ALOGW("%s is not supported.", codecID);
2175 continue;
2176 }
2177
2178 AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_SAMPLE_RATE, atrack->GetSamplingRate());
2179 AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_CHANNEL_COUNT, atrack->GetChannels());
2180 AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_BITS_PER_SAMPLE, atrack->GetBitDepth());
2181 break;
2182 }
2183
2184 default:
2185 continue;
2186 }
2187
2188 const char *language = track->GetLanguage();
2189 if (language != NULL) {
2190 char lang[4];
2191 strncpy(lang, language, 3);
2192 lang[3] = '\0';
2193 AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_LANGUAGE, lang);
2194 }
2195
2196 if (err != OK) {
2197 ALOGE("skipping track, codec specific data was malformed.");
2198 continue;
2199 }
2200
2201 long long durationNs = mSegment->GetDuration();
2202 AMediaFormat_setInt64(meta, AMEDIAFORMAT_KEY_DURATION, (durationNs + 500) / 1000);
2203
2204 const char *mimetype = "";
2205 if (!AMediaFormat_getString(meta, AMEDIAFORMAT_KEY_MIME, &mimetype)) {
2206 // do not add this track to the track list
2207 ALOGW("ignoring track with unknown mime");
2208 continue;
2209 }
2210
2211 mTracks.push();
2212 size_t n = mTracks.size() - 1;
2213 TrackInfo *trackInfo = &mTracks.editItemAt(n);
2214 initTrackInfo(track, meta, trackInfo);
2215 trackInfo->mNalLengthSize = nalSize;
2216
2217 if ((!strcmp("V_MPEG4/ISO/AVC", codecID) && codecPrivateSize == 0) ||
2218 (!strcmp(mimetype, MEDIA_MIMETYPE_VIDEO_AVC) && isSetCsdFrom1stFrame)) {
2219 // Attempt to recover from AVC track without codec private data
2220 err = synthesizeAVCC(trackInfo, n);
2221 if (err != OK) {
2222 mTracks.pop();
2223 continue;
2224 }
2225 } else if ((!strcmp("V_MPEG2", codecID) && codecPrivateSize == 0) ||
2226 (!strcmp(mimetype, MEDIA_MIMETYPE_VIDEO_MPEG2) && isSetCsdFrom1stFrame)) {
2227 // Attempt to recover from MPEG2 track without codec private data
2228 err = synthesizeMPEG2(trackInfo, n);
2229 if (err != OK) {
2230 mTracks.pop();
2231 continue;
2232 }
2233 } else if ((!strcmp("V_MPEG4/ISO/ASP", codecID) && codecPrivateSize == 0) ||
2234 (!strcmp(mimetype, MEDIA_MIMETYPE_VIDEO_MPEG4) && isSetCsdFrom1stFrame) ||
2235 (!strcmp(mimetype, MEDIA_MIMETYPE_VIDEO_XVID) && isSetCsdFrom1stFrame) ||
2236 (!strcmp(mimetype, MEDIA_MIMETYPE_VIDEO_DIVX) && isSetCsdFrom1stFrame) ||
2237 (!strcmp(mimetype, MEDIA_MIMETYPE_VIDEO_DIVX3) && isSetCsdFrom1stFrame)) {
2238 // Attempt to recover from MPEG4 track without codec private data
2239 err = synthesizeMPEG4(trackInfo, n);
2240 if (err != OK) {
2241 mTracks.pop();
2242 continue;
2243 }
2244 }
2245 // the TrackInfo owns the metadata now
2246 meta = nullptr;
2247 }
2248 if (meta) {
2249 AMediaFormat_delete(meta);
2250 }
2251 }
2252
findThumbnails()2253 void MatroskaExtractor::findThumbnails() {
2254 for (size_t i = 0; i < mTracks.size(); ++i) {
2255 TrackInfo *info = &mTracks.editItemAt(i);
2256
2257 const char *mime;
2258 CHECK(AMediaFormat_getString(info->mMeta, AMEDIAFORMAT_KEY_MIME, &mime));
2259
2260 if (strncasecmp(mime, "video/", 6)) {
2261 continue;
2262 }
2263
2264 BlockIterator iter(this, info->mTrackNum, i);
2265 int32_t j = 0;
2266 int64_t thumbnailTimeUs = 0;
2267 size_t maxBlockSize = 0;
2268 while (!iter.eos() && j < 20) {
2269 if (iter.block()->IsKey()) {
2270 ++j;
2271
2272 size_t blockSize = 0;
2273 for (int k = 0; k < iter.block()->GetFrameCount(); ++k) {
2274 blockSize += iter.block()->GetFrame(k).len;
2275 }
2276
2277 if (blockSize > maxBlockSize) {
2278 maxBlockSize = blockSize;
2279 thumbnailTimeUs = iter.blockTimeUs();
2280 }
2281 }
2282 iter.advance();
2283 }
2284 AMediaFormat_setInt64(info->mMeta,
2285 AMEDIAFORMAT_KEY_THUMBNAIL_TIME, thumbnailTimeUs);
2286 }
2287 }
2288
getMetaData(AMediaFormat * meta)2289 media_status_t MatroskaExtractor::getMetaData(AMediaFormat *meta) {
2290 AMediaFormat_setString(meta,
2291 AMEDIAFORMAT_KEY_MIME, mIsWebm ? "video/webm" : MEDIA_MIMETYPE_CONTAINER_MATROSKA);
2292
2293 return AMEDIA_OK;
2294 }
2295
flags() const2296 uint32_t MatroskaExtractor::flags() const {
2297 uint32_t x = CAN_PAUSE;
2298 if (!isLiveStreaming()) {
2299 x |= CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK;
2300 }
2301
2302 return x;
2303 }
2304
SniffMatroska(DataSourceHelper * source,float * confidence)2305 bool SniffMatroska(
2306 DataSourceHelper *source, float *confidence) {
2307 DataSourceBaseReader reader(source);
2308 mkvparser::EBMLHeader ebmlHeader;
2309 long long pos;
2310 if (ebmlHeader.Parse(&reader, pos) < 0) {
2311 return false;
2312 }
2313
2314 *confidence = 0.6;
2315
2316 return true;
2317 }
2318
2319 static const char *extensions[] = {
2320 "mka",
2321 "mkv",
2322 "webm",
2323 NULL
2324 };
2325
2326 extern "C" {
2327 // This is the only symbol that needs to be exported
2328 __attribute__ ((visibility ("default")))
GETEXTRACTORDEF()2329 ExtractorDef GETEXTRACTORDEF() {
2330 return {
2331 EXTRACTORDEF_VERSION,
2332 UUID("abbedd92-38c4-4904-a4c1-b3f45f899980"),
2333 1,
2334 "Matroska Extractor",
2335 {
2336 .v3 = {
2337 [](
2338 CDataSource *source,
2339 float *confidence,
2340 void **,
2341 FreeMetaFunc *) -> CreatorFunc {
2342 DataSourceHelper helper(source);
2343 if (SniffMatroska(&helper, confidence)) {
2344 return [](
2345 CDataSource *source,
2346 void *) -> CMediaExtractor* {
2347 return wrap(new MatroskaExtractor(new DataSourceHelper(source)));};
2348 }
2349 return NULL;
2350 },
2351 extensions
2352 }
2353 }
2354 };
2355 }
2356
2357 } // extern "C"
2358
2359 } // namespace android
2360