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