1 /*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "MatroskaExtractor"
19 #include <utils/Log.h>
20
21 #include "MatroskaExtractor.h"
22
23 #include <media/stagefright/foundation/ADebug.h>
24 #include <media/stagefright/foundation/AUtils.h>
25 #include <media/stagefright/foundation/hexdump.h>
26 #include <media/stagefright/DataSource.h>
27 #include <media/stagefright/MediaBuffer.h>
28 #include <media/stagefright/MediaDefs.h>
29 #include <media/stagefright/MediaErrors.h>
30 #include <media/stagefright/MediaSource.h>
31 #include <media/stagefright/MetaData.h>
32 #include <media/stagefright/Utils.h>
33 #include <utils/String8.h>
34
35 #include <inttypes.h>
36
37 namespace android {
38
39 struct DataSourceReader : public mkvparser::IMkvReader {
DataSourceReaderandroid::DataSourceReader40 DataSourceReader(const sp<DataSource> &source)
41 : mSource(source) {
42 }
43
Readandroid::DataSourceReader44 virtual int Read(long long position, long length, unsigned char* buffer) {
45 CHECK(position >= 0);
46 CHECK(length >= 0);
47
48 if (length == 0) {
49 return 0;
50 }
51
52 ssize_t n = mSource->readAt(position, buffer, length);
53
54 if (n <= 0) {
55 return -1;
56 }
57
58 return 0;
59 }
60
Lengthandroid::DataSourceReader61 virtual int Length(long long* total, long long* available) {
62 off64_t size;
63 if (mSource->getSize(&size) != OK) {
64 *total = -1;
65 *available = (long long)((1ull << 63) - 1);
66
67 return 0;
68 }
69
70 if (total) {
71 *total = size;
72 }
73
74 if (available) {
75 *available = size;
76 }
77
78 return 0;
79 }
80
81 private:
82 sp<DataSource> mSource;
83
84 DataSourceReader(const DataSourceReader &);
85 DataSourceReader &operator=(const DataSourceReader &);
86 };
87
88 ////////////////////////////////////////////////////////////////////////////////
89
90 struct BlockIterator {
91 BlockIterator(MatroskaExtractor *extractor, unsigned long trackNum, unsigned long index);
92
93 bool eos() const;
94
95 void advance();
96 void reset();
97
98 void seek(
99 int64_t seekTimeUs, bool isAudio,
100 int64_t *actualFrameTimeUs);
101
102 const mkvparser::Block *block() const;
103 int64_t blockTimeUs() const;
104
105 private:
106 MatroskaExtractor *mExtractor;
107 long long mTrackNum;
108 unsigned long mIndex;
109
110 const mkvparser::Cluster *mCluster;
111 const mkvparser::BlockEntry *mBlockEntry;
112 long mBlockEntryIndex;
113
114 void advance_l();
115
116 BlockIterator(const BlockIterator &);
117 BlockIterator &operator=(const BlockIterator &);
118 };
119
120 struct MatroskaSource : public MediaSource {
121 MatroskaSource(
122 const sp<MatroskaExtractor> &extractor, size_t index);
123
124 virtual status_t start(MetaData *params);
125 virtual status_t stop();
126
127 virtual sp<MetaData> getFormat();
128
129 virtual status_t read(
130 MediaBuffer **buffer, const ReadOptions *options);
131
132 protected:
133 virtual ~MatroskaSource();
134
135 private:
136 enum Type {
137 AVC,
138 AAC,
139 OTHER
140 };
141
142 sp<MatroskaExtractor> mExtractor;
143 size_t mTrackIndex;
144 Type mType;
145 bool mIsAudio;
146 BlockIterator mBlockIter;
147 size_t mNALSizeLen; // for type AVC
148
149 List<MediaBuffer *> mPendingFrames;
150
151 status_t advance();
152
153 status_t readBlock();
154 void clearPendingFrames();
155
156 MatroskaSource(const MatroskaSource &);
157 MatroskaSource &operator=(const MatroskaSource &);
158 };
159
getTrack() const160 const mkvparser::Track* MatroskaExtractor::TrackInfo::getTrack() const {
161 return mExtractor->mSegment->GetTracks()->GetTrackByNumber(mTrackNum);
162 }
163
164 // This function does exactly the same as mkvparser::Cues::Find, except that it
165 // searches in our own track based vectors. We should not need this once mkvparser
166 // adds the same functionality.
find(long long timeNs) const167 const mkvparser::CuePoint::TrackPosition *MatroskaExtractor::TrackInfo::find(
168 long long timeNs) const {
169 ALOGV("mCuePoints.size %zu", mCuePoints.size());
170 if (mCuePoints.empty()) {
171 return NULL;
172 }
173
174 const mkvparser::CuePoint* cp = mCuePoints.itemAt(0);
175 const mkvparser::Track* track = getTrack();
176 if (timeNs <= cp->GetTime(mExtractor->mSegment)) {
177 return cp->Find(track);
178 }
179
180 // Binary searches through relevant cues; assumes cues are ordered by timecode.
181 // If we do detect out-of-order cues, return NULL.
182 size_t lo = 0;
183 size_t hi = mCuePoints.size();
184 while (lo < hi) {
185 const size_t mid = lo + (hi - lo) / 2;
186 const mkvparser::CuePoint* const midCp = mCuePoints.itemAt(mid);
187 const long long cueTimeNs = midCp->GetTime(mExtractor->mSegment);
188 if (cueTimeNs <= timeNs) {
189 lo = mid + 1;
190 } else {
191 hi = mid;
192 }
193 }
194
195 if (lo == 0) {
196 return NULL;
197 }
198
199 cp = mCuePoints.itemAt(lo - 1);
200 if (cp->GetTime(mExtractor->mSegment) > timeNs) {
201 return NULL;
202 }
203
204 return cp->Find(track);
205 }
206
MatroskaSource(const sp<MatroskaExtractor> & extractor,size_t index)207 MatroskaSource::MatroskaSource(
208 const sp<MatroskaExtractor> &extractor, size_t index)
209 : mExtractor(extractor),
210 mTrackIndex(index),
211 mType(OTHER),
212 mIsAudio(false),
213 mBlockIter(mExtractor.get(),
214 mExtractor->mTracks.itemAt(index).mTrackNum,
215 index),
216 mNALSizeLen(0) {
217 sp<MetaData> meta = mExtractor->mTracks.itemAt(index).mMeta;
218
219 const char *mime;
220 CHECK(meta->findCString(kKeyMIMEType, &mime));
221
222 mIsAudio = !strncasecmp("audio/", mime, 6);
223
224 if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
225 mType = AVC;
226
227 uint32_t dummy;
228 const uint8_t *avcc;
229 size_t avccSize;
230 CHECK(meta->findData(
231 kKeyAVCC, &dummy, (const void **)&avcc, &avccSize));
232
233 CHECK_GE(avccSize, 5u);
234
235 mNALSizeLen = 1 + (avcc[4] & 3);
236 ALOGV("mNALSizeLen = %zu", mNALSizeLen);
237 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
238 mType = AAC;
239 }
240 }
241
~MatroskaSource()242 MatroskaSource::~MatroskaSource() {
243 clearPendingFrames();
244 }
245
start(MetaData *)246 status_t MatroskaSource::start(MetaData * /* params */) {
247 mBlockIter.reset();
248
249 return OK;
250 }
251
stop()252 status_t MatroskaSource::stop() {
253 clearPendingFrames();
254
255 return OK;
256 }
257
getFormat()258 sp<MetaData> MatroskaSource::getFormat() {
259 return mExtractor->mTracks.itemAt(mTrackIndex).mMeta;
260 }
261
262 ////////////////////////////////////////////////////////////////////////////////
263
BlockIterator(MatroskaExtractor * extractor,unsigned long trackNum,unsigned long index)264 BlockIterator::BlockIterator(
265 MatroskaExtractor *extractor, unsigned long trackNum, unsigned long index)
266 : mExtractor(extractor),
267 mTrackNum(trackNum),
268 mIndex(index),
269 mCluster(NULL),
270 mBlockEntry(NULL),
271 mBlockEntryIndex(0) {
272 reset();
273 }
274
eos() const275 bool BlockIterator::eos() const {
276 return mCluster == NULL || mCluster->EOS();
277 }
278
advance()279 void BlockIterator::advance() {
280 Mutex::Autolock autoLock(mExtractor->mLock);
281 advance_l();
282 }
283
advance_l()284 void BlockIterator::advance_l() {
285 for (;;) {
286 long res = mCluster->GetEntry(mBlockEntryIndex, mBlockEntry);
287 ALOGV("GetEntry returned %ld", res);
288
289 long long pos;
290 long len;
291 if (res < 0) {
292 // Need to parse this cluster some more
293
294 CHECK_EQ(res, mkvparser::E_BUFFER_NOT_FULL);
295
296 res = mCluster->Parse(pos, len);
297 ALOGV("Parse returned %ld", res);
298
299 if (res < 0) {
300 // I/O error
301
302 ALOGE("Cluster::Parse returned result %ld", res);
303
304 mCluster = NULL;
305 break;
306 }
307
308 continue;
309 } else if (res == 0) {
310 // We're done with this cluster
311
312 const mkvparser::Cluster *nextCluster;
313 res = mExtractor->mSegment->ParseNext(
314 mCluster, nextCluster, pos, len);
315 ALOGV("ParseNext returned %ld", res);
316
317 if (res != 0) {
318 // EOF or error
319
320 mCluster = NULL;
321 break;
322 }
323
324 CHECK_EQ(res, 0);
325 CHECK(nextCluster != NULL);
326 CHECK(!nextCluster->EOS());
327
328 mCluster = nextCluster;
329
330 res = mCluster->Parse(pos, len);
331 ALOGV("Parse (2) returned %ld", res);
332 CHECK_GE(res, 0);
333
334 mBlockEntryIndex = 0;
335 continue;
336 }
337
338 CHECK(mBlockEntry != NULL);
339 CHECK(mBlockEntry->GetBlock() != NULL);
340 ++mBlockEntryIndex;
341
342 if (mBlockEntry->GetBlock()->GetTrackNumber() == mTrackNum) {
343 break;
344 }
345 }
346 }
347
reset()348 void BlockIterator::reset() {
349 Mutex::Autolock autoLock(mExtractor->mLock);
350
351 mCluster = mExtractor->mSegment->GetFirst();
352 mBlockEntry = NULL;
353 mBlockEntryIndex = 0;
354
355 do {
356 advance_l();
357 } while (!eos() && block()->GetTrackNumber() != mTrackNum);
358 }
359
seek(int64_t seekTimeUs,bool isAudio,int64_t * actualFrameTimeUs)360 void BlockIterator::seek(
361 int64_t seekTimeUs, bool isAudio,
362 int64_t *actualFrameTimeUs) {
363 Mutex::Autolock autoLock(mExtractor->mLock);
364
365 *actualFrameTimeUs = -1ll;
366
367 const int64_t seekTimeNs = seekTimeUs * 1000ll - mExtractor->mSeekPreRollNs;
368
369 mkvparser::Segment* const pSegment = mExtractor->mSegment;
370
371 // Special case the 0 seek to avoid loading Cues when the application
372 // extraneously seeks to 0 before playing.
373 if (seekTimeNs <= 0) {
374 ALOGV("Seek to beginning: %" PRId64, seekTimeUs);
375 mCluster = pSegment->GetFirst();
376 mBlockEntryIndex = 0;
377 do {
378 advance_l();
379 } while (!eos() && block()->GetTrackNumber() != mTrackNum);
380 return;
381 }
382
383 ALOGV("Seeking to: %" PRId64, seekTimeUs);
384
385 // If the Cues have not been located then find them.
386 const mkvparser::Cues* pCues = pSegment->GetCues();
387 const mkvparser::SeekHead* pSH = pSegment->GetSeekHead();
388 if (!pCues && pSH) {
389 const size_t count = pSH->GetCount();
390 const mkvparser::SeekHead::Entry* pEntry;
391 ALOGV("No Cues yet");
392
393 for (size_t index = 0; index < count; index++) {
394 pEntry = pSH->GetEntry(index);
395
396 if (pEntry->id == 0x0C53BB6B) { // Cues ID
397 long len; long long pos;
398 pSegment->ParseCues(pEntry->pos, pos, len);
399 pCues = pSegment->GetCues();
400 ALOGV("Cues found");
401 break;
402 }
403 }
404
405 if (!pCues) {
406 ALOGE("No Cues in file");
407 return;
408 }
409 }
410 else if (!pSH) {
411 ALOGE("No SeekHead");
412 return;
413 }
414
415 const mkvparser::CuePoint* pCP;
416 mkvparser::Tracks const *pTracks = pSegment->GetTracks();
417 while (!pCues->DoneParsing()) {
418 pCues->LoadCuePoint();
419 pCP = pCues->GetLast();
420 CHECK(pCP);
421
422 size_t trackCount = mExtractor->mTracks.size();
423 for (size_t index = 0; index < trackCount; ++index) {
424 MatroskaExtractor::TrackInfo& track = mExtractor->mTracks.editItemAt(index);
425 const mkvparser::Track *pTrack = pTracks->GetTrackByNumber(track.mTrackNum);
426 if (pTrack && pTrack->GetType() == 1 && pCP->Find(pTrack)) { // VIDEO_TRACK
427 track.mCuePoints.push_back(pCP);
428 }
429 }
430
431 if (pCP->GetTime(pSegment) >= seekTimeNs) {
432 ALOGV("Parsed past relevant Cue");
433 break;
434 }
435 }
436
437 const mkvparser::CuePoint::TrackPosition *pTP = NULL;
438 const mkvparser::Track *thisTrack = pTracks->GetTrackByNumber(mTrackNum);
439 if (thisTrack->GetType() == 1) { // video
440 MatroskaExtractor::TrackInfo& track = mExtractor->mTracks.editItemAt(mIndex);
441 pTP = track.find(seekTimeNs);
442 } else {
443 // The Cue index is built around video keyframes
444 unsigned long int trackCount = pTracks->GetTracksCount();
445 for (size_t index = 0; index < trackCount; ++index) {
446 const mkvparser::Track *pTrack = pTracks->GetTrackByIndex(index);
447 if (pTrack && pTrack->GetType() == 1 && pCues->Find(seekTimeNs, pTrack, pCP, pTP)) {
448 ALOGV("Video track located at %zu", index);
449 break;
450 }
451 }
452 }
453
454
455 // Always *search* based on the video track, but finalize based on mTrackNum
456 if (!pTP) {
457 ALOGE("Did not locate the video track for seeking");
458 return;
459 }
460
461 mCluster = pSegment->FindOrPreloadCluster(pTP->m_pos);
462
463 CHECK(mCluster);
464 CHECK(!mCluster->EOS());
465
466 // mBlockEntryIndex starts at 0 but m_block starts at 1
467 CHECK_GT(pTP->m_block, 0);
468 mBlockEntryIndex = pTP->m_block - 1;
469
470 for (;;) {
471 advance_l();
472
473 if (eos()) break;
474
475 if (isAudio || block()->IsKey()) {
476 // Accept the first key frame
477 int64_t frameTimeUs = (block()->GetTime(mCluster) + 500LL) / 1000LL;
478 if (thisTrack->GetType() == 1 || frameTimeUs >= seekTimeUs) {
479 *actualFrameTimeUs = frameTimeUs;
480 ALOGV("Requested seek point: %" PRId64 " actual: %" PRId64,
481 seekTimeUs, *actualFrameTimeUs);
482 break;
483 }
484 }
485 }
486 }
487
block() const488 const mkvparser::Block *BlockIterator::block() const {
489 CHECK(!eos());
490
491 return mBlockEntry->GetBlock();
492 }
493
blockTimeUs() const494 int64_t BlockIterator::blockTimeUs() const {
495 return (mBlockEntry->GetBlock()->GetTime(mCluster) + 500ll) / 1000ll;
496 }
497
498 ////////////////////////////////////////////////////////////////////////////////
499
U24_AT(const uint8_t * ptr)500 static unsigned U24_AT(const uint8_t *ptr) {
501 return ptr[0] << 16 | ptr[1] << 8 | ptr[2];
502 }
503
clearPendingFrames()504 void MatroskaSource::clearPendingFrames() {
505 while (!mPendingFrames.empty()) {
506 MediaBuffer *frame = *mPendingFrames.begin();
507 mPendingFrames.erase(mPendingFrames.begin());
508
509 frame->release();
510 frame = NULL;
511 }
512 }
513
readBlock()514 status_t MatroskaSource::readBlock() {
515 CHECK(mPendingFrames.empty());
516
517 if (mBlockIter.eos()) {
518 return ERROR_END_OF_STREAM;
519 }
520
521 const mkvparser::Block *block = mBlockIter.block();
522
523 int64_t timeUs = mBlockIter.blockTimeUs();
524
525 for (int i = 0; i < block->GetFrameCount(); ++i) {
526 const mkvparser::Block::Frame &frame = block->GetFrame(i);
527
528 MediaBuffer *mbuf = new MediaBuffer(frame.len);
529 mbuf->meta_data()->setInt64(kKeyTime, timeUs);
530 mbuf->meta_data()->setInt32(kKeyIsSyncFrame, block->IsKey());
531
532 long n = frame.Read(mExtractor->mReader, (unsigned char *)mbuf->data());
533 if (n != 0) {
534 mPendingFrames.clear();
535
536 mBlockIter.advance();
537 return ERROR_IO;
538 }
539
540 mPendingFrames.push_back(mbuf);
541 }
542
543 mBlockIter.advance();
544
545 return OK;
546 }
547
read(MediaBuffer ** out,const ReadOptions * options)548 status_t MatroskaSource::read(
549 MediaBuffer **out, const ReadOptions *options) {
550 *out = NULL;
551
552 int64_t targetSampleTimeUs = -1ll;
553
554 int64_t seekTimeUs;
555 ReadOptions::SeekMode mode;
556 if (options && options->getSeekTo(&seekTimeUs, &mode)
557 && !mExtractor->isLiveStreaming()) {
558 clearPendingFrames();
559
560 // The audio we want is located by using the Cues to seek the video
561 // stream to find the target Cluster then iterating to finalize for
562 // audio.
563 int64_t actualFrameTimeUs;
564 mBlockIter.seek(seekTimeUs, mIsAudio, &actualFrameTimeUs);
565
566 if (mode == ReadOptions::SEEK_CLOSEST) {
567 targetSampleTimeUs = actualFrameTimeUs;
568 }
569 }
570
571 while (mPendingFrames.empty()) {
572 status_t err = readBlock();
573
574 if (err != OK) {
575 clearPendingFrames();
576
577 return err;
578 }
579 }
580
581 MediaBuffer *frame = *mPendingFrames.begin();
582 mPendingFrames.erase(mPendingFrames.begin());
583
584 if (mType != AVC) {
585 if (targetSampleTimeUs >= 0ll) {
586 frame->meta_data()->setInt64(
587 kKeyTargetTime, targetSampleTimeUs);
588 }
589
590 *out = frame;
591
592 return OK;
593 }
594
595 // Each input frame contains one or more NAL fragments, each fragment
596 // is prefixed by mNALSizeLen bytes giving the fragment length,
597 // followed by a corresponding number of bytes containing the fragment.
598 // We output all these fragments into a single large buffer separated
599 // by startcodes (0x00 0x00 0x00 0x01).
600
601 const uint8_t *srcPtr =
602 (const uint8_t *)frame->data() + frame->range_offset();
603
604 size_t srcSize = frame->range_length();
605
606 size_t dstSize = 0;
607 MediaBuffer *buffer = NULL;
608 uint8_t *dstPtr = NULL;
609
610 for (int32_t pass = 0; pass < 2; ++pass) {
611 size_t srcOffset = 0;
612 size_t dstOffset = 0;
613 while (srcOffset + mNALSizeLen <= srcSize) {
614 size_t NALsize;
615 switch (mNALSizeLen) {
616 case 1: NALsize = srcPtr[srcOffset]; break;
617 case 2: NALsize = U16_AT(srcPtr + srcOffset); break;
618 case 3: NALsize = U24_AT(srcPtr + srcOffset); break;
619 case 4: NALsize = U32_AT(srcPtr + srcOffset); break;
620 default:
621 TRESPASS();
622 }
623
624 if (srcOffset + mNALSizeLen + NALsize <= srcOffset + mNALSizeLen) {
625 frame->release();
626 frame = NULL;
627
628 return ERROR_MALFORMED;
629 } else if (srcOffset + mNALSizeLen + NALsize > srcSize) {
630 break;
631 }
632
633 if (pass == 1) {
634 memcpy(&dstPtr[dstOffset], "\x00\x00\x00\x01", 4);
635
636 memcpy(&dstPtr[dstOffset + 4],
637 &srcPtr[srcOffset + mNALSizeLen],
638 NALsize);
639 }
640
641 dstOffset += 4; // 0x00 00 00 01
642 dstOffset += NALsize;
643
644 srcOffset += mNALSizeLen + NALsize;
645 }
646
647 if (srcOffset < srcSize) {
648 // There were trailing bytes or not enough data to complete
649 // a fragment.
650
651 frame->release();
652 frame = NULL;
653
654 return ERROR_MALFORMED;
655 }
656
657 if (pass == 0) {
658 dstSize = dstOffset;
659
660 buffer = new MediaBuffer(dstSize);
661
662 int64_t timeUs;
663 CHECK(frame->meta_data()->findInt64(kKeyTime, &timeUs));
664 int32_t isSync;
665 CHECK(frame->meta_data()->findInt32(kKeyIsSyncFrame, &isSync));
666
667 buffer->meta_data()->setInt64(kKeyTime, timeUs);
668 buffer->meta_data()->setInt32(kKeyIsSyncFrame, isSync);
669
670 dstPtr = (uint8_t *)buffer->data();
671 }
672 }
673
674 frame->release();
675 frame = NULL;
676
677 if (targetSampleTimeUs >= 0ll) {
678 buffer->meta_data()->setInt64(
679 kKeyTargetTime, targetSampleTimeUs);
680 }
681
682 *out = buffer;
683
684 return OK;
685 }
686
687 ////////////////////////////////////////////////////////////////////////////////
688
MatroskaExtractor(const sp<DataSource> & source)689 MatroskaExtractor::MatroskaExtractor(const sp<DataSource> &source)
690 : mDataSource(source),
691 mReader(new DataSourceReader(mDataSource)),
692 mSegment(NULL),
693 mExtractedThumbnails(false),
694 mIsWebm(false),
695 mSeekPreRollNs(0) {
696 off64_t size;
697 mIsLiveStreaming =
698 (mDataSource->flags()
699 & (DataSource::kWantsPrefetching
700 | DataSource::kIsCachingDataSource))
701 && mDataSource->getSize(&size) != OK;
702
703 mkvparser::EBMLHeader ebmlHeader;
704 long long pos;
705 if (ebmlHeader.Parse(mReader, pos) < 0) {
706 return;
707 }
708
709 if (ebmlHeader.m_docType && !strcmp("webm", ebmlHeader.m_docType)) {
710 mIsWebm = true;
711 }
712
713 long long ret =
714 mkvparser::Segment::CreateInstance(mReader, pos, mSegment);
715
716 if (ret) {
717 CHECK(mSegment == NULL);
718 return;
719 }
720
721 // from mkvparser::Segment::Load(), but stop at first cluster
722 ret = mSegment->ParseHeaders();
723 if (ret == 0) {
724 long len;
725 ret = mSegment->LoadCluster(pos, len);
726 if (ret >= 1) {
727 // no more clusters
728 ret = 0;
729 }
730 } else if (ret > 0) {
731 ret = mkvparser::E_BUFFER_NOT_FULL;
732 }
733
734 if (ret < 0) {
735 ALOGW("Corrupt %s source: %s", mIsWebm ? "webm" : "matroska",
736 uriDebugString(mDataSource->getUri()).c_str());
737 delete mSegment;
738 mSegment = NULL;
739 return;
740 }
741
742 #if 0
743 const mkvparser::SegmentInfo *info = mSegment->GetInfo();
744 ALOGI("muxing app: %s, writing app: %s",
745 info->GetMuxingAppAsUTF8(),
746 info->GetWritingAppAsUTF8());
747 #endif
748
749 addTracks();
750 }
751
~MatroskaExtractor()752 MatroskaExtractor::~MatroskaExtractor() {
753 delete mSegment;
754 mSegment = NULL;
755
756 delete mReader;
757 mReader = NULL;
758 }
759
countTracks()760 size_t MatroskaExtractor::countTracks() {
761 return mTracks.size();
762 }
763
getTrack(size_t index)764 sp<MediaSource> MatroskaExtractor::getTrack(size_t index) {
765 if (index >= mTracks.size()) {
766 return NULL;
767 }
768
769 return new MatroskaSource(this, index);
770 }
771
getTrackMetaData(size_t index,uint32_t flags)772 sp<MetaData> MatroskaExtractor::getTrackMetaData(
773 size_t index, uint32_t flags) {
774 if (index >= mTracks.size()) {
775 return NULL;
776 }
777
778 if ((flags & kIncludeExtensiveMetaData) && !mExtractedThumbnails
779 && !isLiveStreaming()) {
780 findThumbnails();
781 mExtractedThumbnails = true;
782 }
783
784 return mTracks.itemAt(index).mMeta;
785 }
786
isLiveStreaming() const787 bool MatroskaExtractor::isLiveStreaming() const {
788 return mIsLiveStreaming;
789 }
790
bytesForSize(size_t size)791 static int bytesForSize(size_t size) {
792 // use at most 28 bits (4 times 7)
793 CHECK(size <= 0xfffffff);
794
795 if (size > 0x1fffff) {
796 return 4;
797 } else if (size > 0x3fff) {
798 return 3;
799 } else if (size > 0x7f) {
800 return 2;
801 }
802 return 1;
803 }
804
storeSize(uint8_t * data,size_t & idx,size_t size)805 static void storeSize(uint8_t *data, size_t &idx, size_t size) {
806 int numBytes = bytesForSize(size);
807 idx += numBytes;
808
809 data += idx;
810 size_t next = 0;
811 while (numBytes--) {
812 *--data = (size & 0x7f) | next;
813 size >>= 7;
814 next = 0x80;
815 }
816 }
817
addESDSFromCodecPrivate(const sp<MetaData> & meta,bool isAudio,const void * priv,size_t privSize)818 static void addESDSFromCodecPrivate(
819 const sp<MetaData> &meta,
820 bool isAudio, const void *priv, size_t privSize) {
821
822 int privSizeBytesRequired = bytesForSize(privSize);
823 int esdsSize2 = 14 + privSizeBytesRequired + privSize;
824 int esdsSize2BytesRequired = bytesForSize(esdsSize2);
825 int esdsSize1 = 4 + esdsSize2BytesRequired + esdsSize2;
826 int esdsSize1BytesRequired = bytesForSize(esdsSize1);
827 size_t esdsSize = 1 + esdsSize1BytesRequired + esdsSize1;
828 uint8_t *esds = new uint8_t[esdsSize];
829
830 size_t idx = 0;
831 esds[idx++] = 0x03;
832 storeSize(esds, idx, esdsSize1);
833 esds[idx++] = 0x00; // ES_ID
834 esds[idx++] = 0x00; // ES_ID
835 esds[idx++] = 0x00; // streamDependenceFlag, URL_Flag, OCRstreamFlag
836 esds[idx++] = 0x04;
837 storeSize(esds, idx, esdsSize2);
838 esds[idx++] = isAudio ? 0x40 // Audio ISO/IEC 14496-3
839 : 0x20; // Visual ISO/IEC 14496-2
840 for (int i = 0; i < 12; i++) {
841 esds[idx++] = 0x00;
842 }
843 esds[idx++] = 0x05;
844 storeSize(esds, idx, privSize);
845 memcpy(esds + idx, priv, privSize);
846
847 meta->setData(kKeyESDS, 0, esds, esdsSize);
848
849 delete[] esds;
850 esds = NULL;
851 }
852
addVorbisCodecInfo(const sp<MetaData> & meta,const void * _codecPrivate,size_t codecPrivateSize)853 status_t addVorbisCodecInfo(
854 const sp<MetaData> &meta,
855 const void *_codecPrivate, size_t codecPrivateSize) {
856 // hexdump(_codecPrivate, codecPrivateSize);
857
858 if (codecPrivateSize < 1) {
859 return ERROR_MALFORMED;
860 }
861
862 const uint8_t *codecPrivate = (const uint8_t *)_codecPrivate;
863
864 if (codecPrivate[0] != 0x02) {
865 return ERROR_MALFORMED;
866 }
867
868 // codecInfo starts with two lengths, len1 and len2, that are
869 // "Xiph-style-lacing encoded"...
870
871 size_t offset = 1;
872 size_t len1 = 0;
873 while (offset < codecPrivateSize && codecPrivate[offset] == 0xff) {
874 if (len1 > (SIZE_MAX - 0xff)) {
875 return ERROR_MALFORMED; // would overflow
876 }
877 len1 += 0xff;
878 ++offset;
879 }
880 if (offset >= codecPrivateSize) {
881 return ERROR_MALFORMED;
882 }
883 if (len1 > (SIZE_MAX - codecPrivate[offset])) {
884 return ERROR_MALFORMED; // would overflow
885 }
886 len1 += codecPrivate[offset++];
887
888 size_t len2 = 0;
889 while (offset < codecPrivateSize && codecPrivate[offset] == 0xff) {
890 if (len2 > (SIZE_MAX - 0xff)) {
891 return ERROR_MALFORMED; // would overflow
892 }
893 len2 += 0xff;
894 ++offset;
895 }
896 if (offset >= codecPrivateSize) {
897 return ERROR_MALFORMED;
898 }
899 if (len2 > (SIZE_MAX - codecPrivate[offset])) {
900 return ERROR_MALFORMED; // would overflow
901 }
902 len2 += codecPrivate[offset++];
903
904 if (len1 > SIZE_MAX - len2 || offset > SIZE_MAX - (len1 + len2) ||
905 codecPrivateSize < offset + len1 + len2) {
906 return ERROR_MALFORMED;
907 }
908
909 if (codecPrivate[offset] != 0x01) {
910 return ERROR_MALFORMED;
911 }
912 meta->setData(kKeyVorbisInfo, 0, &codecPrivate[offset], len1);
913
914 offset += len1;
915 if (codecPrivate[offset] != 0x03) {
916 return ERROR_MALFORMED;
917 }
918
919 offset += len2;
920 if (codecPrivate[offset] != 0x05) {
921 return ERROR_MALFORMED;
922 }
923
924 meta->setData(
925 kKeyVorbisBooks, 0, &codecPrivate[offset],
926 codecPrivateSize - offset);
927
928 return OK;
929 }
930
addTracks()931 void MatroskaExtractor::addTracks() {
932 const mkvparser::Tracks *tracks = mSegment->GetTracks();
933
934 for (size_t index = 0; index < tracks->GetTracksCount(); ++index) {
935 const mkvparser::Track *track = tracks->GetTrackByIndex(index);
936
937 if (track == NULL) {
938 // Apparently this is currently valid (if unexpected) behaviour
939 // of the mkv parser lib.
940 continue;
941 }
942
943 const char *const codecID = track->GetCodecId();
944 ALOGV("codec id = %s", codecID);
945 ALOGV("codec name = %s", track->GetCodecNameAsUTF8());
946
947 if (codecID == NULL) {
948 ALOGW("unknown codecID is not supported.");
949 continue;
950 }
951
952 size_t codecPrivateSize;
953 const unsigned char *codecPrivate =
954 track->GetCodecPrivate(codecPrivateSize);
955
956 enum { VIDEO_TRACK = 1, AUDIO_TRACK = 2 };
957
958 sp<MetaData> meta = new MetaData;
959
960 status_t err = OK;
961
962 switch (track->GetType()) {
963 case VIDEO_TRACK:
964 {
965 const mkvparser::VideoTrack *vtrack =
966 static_cast<const mkvparser::VideoTrack *>(track);
967
968 if (!strcmp("V_MPEG4/ISO/AVC", codecID)) {
969 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
970 meta->setData(kKeyAVCC, 0, codecPrivate, codecPrivateSize);
971 } else if (!strcmp("V_MPEG4/ISO/ASP", codecID)) {
972 if (codecPrivateSize > 0) {
973 meta->setCString(
974 kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
975 addESDSFromCodecPrivate(
976 meta, false, codecPrivate, codecPrivateSize);
977 } else {
978 ALOGW("%s is detected, but does not have configuration.",
979 codecID);
980 continue;
981 }
982 } else if (!strcmp("V_VP8", codecID)) {
983 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VP8);
984 } else if (!strcmp("V_VP9", codecID)) {
985 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VP9);
986 } else {
987 ALOGW("%s is not supported.", codecID);
988 continue;
989 }
990
991 meta->setInt32(kKeyWidth, vtrack->GetWidth());
992 meta->setInt32(kKeyHeight, vtrack->GetHeight());
993 break;
994 }
995
996 case AUDIO_TRACK:
997 {
998 const mkvparser::AudioTrack *atrack =
999 static_cast<const mkvparser::AudioTrack *>(track);
1000
1001 if (!strcmp("A_AAC", codecID)) {
1002 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
1003 CHECK(codecPrivateSize >= 2);
1004
1005 addESDSFromCodecPrivate(
1006 meta, true, codecPrivate, codecPrivateSize);
1007 } else if (!strcmp("A_VORBIS", codecID)) {
1008 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS);
1009
1010 err = addVorbisCodecInfo(
1011 meta, codecPrivate, codecPrivateSize);
1012 } else if (!strcmp("A_OPUS", codecID)) {
1013 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_OPUS);
1014 meta->setData(kKeyOpusHeader, 0, codecPrivate, codecPrivateSize);
1015 meta->setInt64(kKeyOpusCodecDelay, track->GetCodecDelay());
1016 meta->setInt64(kKeyOpusSeekPreRoll, track->GetSeekPreRoll());
1017 mSeekPreRollNs = track->GetSeekPreRoll();
1018 } else if (!strcmp("A_MPEG/L3", codecID)) {
1019 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
1020 } else {
1021 ALOGW("%s is not supported.", codecID);
1022 continue;
1023 }
1024
1025 meta->setInt32(kKeySampleRate, atrack->GetSamplingRate());
1026 meta->setInt32(kKeyChannelCount, atrack->GetChannels());
1027 break;
1028 }
1029
1030 default:
1031 continue;
1032 }
1033
1034 if (err != OK) {
1035 ALOGE("skipping track, codec specific data was malformed.");
1036 continue;
1037 }
1038
1039 long long durationNs = mSegment->GetDuration();
1040 meta->setInt64(kKeyDuration, (durationNs + 500) / 1000);
1041
1042 mTracks.push();
1043 TrackInfo *trackInfo = &mTracks.editItemAt(mTracks.size() - 1);
1044 trackInfo->mTrackNum = track->GetNumber();
1045 trackInfo->mMeta = meta;
1046 trackInfo->mExtractor = this;
1047 }
1048 }
1049
findThumbnails()1050 void MatroskaExtractor::findThumbnails() {
1051 for (size_t i = 0; i < mTracks.size(); ++i) {
1052 TrackInfo *info = &mTracks.editItemAt(i);
1053
1054 const char *mime;
1055 CHECK(info->mMeta->findCString(kKeyMIMEType, &mime));
1056
1057 if (strncasecmp(mime, "video/", 6)) {
1058 continue;
1059 }
1060
1061 BlockIterator iter(this, info->mTrackNum, i);
1062 int32_t j = 0;
1063 int64_t thumbnailTimeUs = 0;
1064 size_t maxBlockSize = 0;
1065 while (!iter.eos() && j < 20) {
1066 if (iter.block()->IsKey()) {
1067 ++j;
1068
1069 size_t blockSize = 0;
1070 for (int k = 0; k < iter.block()->GetFrameCount(); ++k) {
1071 blockSize += iter.block()->GetFrame(k).len;
1072 }
1073
1074 if (blockSize > maxBlockSize) {
1075 maxBlockSize = blockSize;
1076 thumbnailTimeUs = iter.blockTimeUs();
1077 }
1078 }
1079 iter.advance();
1080 }
1081 info->mMeta->setInt64(kKeyThumbnailTime, thumbnailTimeUs);
1082 }
1083 }
1084
getMetaData()1085 sp<MetaData> MatroskaExtractor::getMetaData() {
1086 sp<MetaData> meta = new MetaData;
1087
1088 meta->setCString(
1089 kKeyMIMEType,
1090 mIsWebm ? "video/webm" : MEDIA_MIMETYPE_CONTAINER_MATROSKA);
1091
1092 return meta;
1093 }
1094
flags() const1095 uint32_t MatroskaExtractor::flags() const {
1096 uint32_t x = CAN_PAUSE;
1097 if (!isLiveStreaming()) {
1098 x |= CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK;
1099 }
1100
1101 return x;
1102 }
1103
SniffMatroska(const sp<DataSource> & source,String8 * mimeType,float * confidence,sp<AMessage> *)1104 bool SniffMatroska(
1105 const sp<DataSource> &source, String8 *mimeType, float *confidence,
1106 sp<AMessage> *) {
1107 DataSourceReader reader(source);
1108 mkvparser::EBMLHeader ebmlHeader;
1109 long long pos;
1110 if (ebmlHeader.Parse(&reader, pos) < 0) {
1111 return false;
1112 }
1113
1114 mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_MATROSKA);
1115 *confidence = 0.6;
1116
1117 return true;
1118 }
1119
1120 } // namespace android
1121