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