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