MatroskaExtractor.cpp revision 10f0fe7bcd60bdb0eceb905e84ac11555e8c1b9d
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 36namespace android { 37 38struct 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 80private: 81 sp<DataSource> mSource; 82 83 DataSourceReader(const DataSourceReader &); 84 DataSourceReader &operator=(const DataSourceReader &); 85}; 86 87//////////////////////////////////////////////////////////////////////////////// 88 89struct 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 seekToKeyFrame, 99 int64_t *actualFrameTimeUs); 100 101 const mkvparser::Block *block() const; 102 int64_t blockTimeUs() const; 103 104private: 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 118struct 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 130protected: 131 virtual ~MatroskaSource(); 132 133private: 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 158MatroskaSource::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 192MatroskaSource::~MatroskaSource() { 193 clearPendingFrames(); 194} 195 196status_t MatroskaSource::start(MetaData *params) { 197 mBlockIter.reset(); 198 199 return OK; 200} 201 202status_t MatroskaSource::stop() { 203 clearPendingFrames(); 204 205 return OK; 206} 207 208sp<MetaData> MatroskaSource::getFormat() { 209 return mExtractor->mTracks.itemAt(mTrackIndex).mMeta; 210} 211 212//////////////////////////////////////////////////////////////////////////////// 213 214BlockIterator::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 224bool BlockIterator::eos() const { 225 return mCluster == NULL || mCluster->EOS(); 226} 227 228void BlockIterator::advance() { 229 Mutex::Autolock autoLock(mExtractor->mLock); 230 advance_l(); 231} 232 233void 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 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 297void 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 309void BlockIterator::seek( 310 int64_t seekTimeUs, bool seekToKeyFrame, 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 // Pull one cue point to fix loop below 350 ALOGV("Loading Cue points"); 351 pCues->LoadCuePoint(); 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 // Make sure we don't have the necessary Cue already. 369 // If one Cue hadn't been loaded it would need to pre-emptively 370 // load one every time (until they are all loaded). 371 pCP = pCues->GetLast(); 372 if (pCP->GetTime(pSegment) >= seekTimeNs) { 373 ALOGV("Located segment"); 374 break; 375 } 376 377 pCues->LoadCuePoint(); 378 } 379 380 // Find the video track for seeking. It doesn't make sense to search the 381 // audio track because we'd still want to make sure we're jumping to a 382 // keyframe in the video track. 383 mkvparser::Tracks const *pTracks = pSegment->GetTracks(); 384 const mkvparser::Track *pTrack = NULL; 385 for (size_t index = 0; index < pTracks->GetTracksCount(); ++index) { 386 pTrack = pTracks->GetTrackByIndex(index); 387 if (pTrack && pTrack->GetType() == 1) { // VIDEO_TRACK 388 ALOGV("Video track located at %d", index); 389 break; 390 } 391 } 392 393 const mkvparser::CuePoint::TrackPosition* pTP; 394 if (pTrack) { 395 pCues->Find(seekTimeNs, pTrack, pCP, pTP); 396 } else { 397 ALOGE("Did not locate a VIDEO_TRACK"); 398 return; 399 } 400 401 mCluster = pSegment->FindOrPreloadCluster(pTP->m_pos); 402 if (pTP->m_block > 0) { 403 // m_block starts at 1, but mBlockEntryIndex is expected to start at 0 404 mBlockEntryIndex = pTP->m_block - 1; 405 } else { 406 ALOGE("m_block must be > 0"); 407 return; 408 } 409 410 long prevKeyFrameBlockEntryIndex = -1; 411 412 for (;;) { 413 advance_l(); 414 415 if (eos()) { 416 break; 417 } 418 419 if (block()->GetTrackNumber() != mTrackNum) { 420 continue; 421 } 422 423 if (block()->IsKey()) { 424 prevKeyFrameBlockEntryIndex = mBlockEntryIndex - 1; 425 } 426 427 int64_t timeNs = block()->GetTime(mCluster); 428 429 if (timeNs >= seekTimeNs) { 430 *actualFrameTimeUs = (timeNs + 500ll) / 1000ll; 431 break; 432 } 433 } 434 435 if (eos()) { 436 return; 437 } 438 439 if (seekToKeyFrame && !block()->IsKey()) { 440 CHECK_GE(prevKeyFrameBlockEntryIndex, 0); 441 mBlockEntryIndex = prevKeyFrameBlockEntryIndex; 442 advance_l(); 443 } 444} 445 446const mkvparser::Block *BlockIterator::block() const { 447 CHECK(!eos()); 448 449 return mBlockEntry->GetBlock(); 450} 451 452int64_t BlockIterator::blockTimeUs() const { 453 return (mBlockEntry->GetBlock()->GetTime(mCluster) + 500ll) / 1000ll; 454} 455 456//////////////////////////////////////////////////////////////////////////////// 457 458static unsigned U24_AT(const uint8_t *ptr) { 459 return ptr[0] << 16 | ptr[1] << 8 | ptr[2]; 460} 461 462static size_t clz(uint8_t x) { 463 size_t numLeadingZeroes = 0; 464 465 while (!(x & 0x80)) { 466 ++numLeadingZeroes; 467 x = x << 1; 468 } 469 470 return numLeadingZeroes; 471} 472 473void MatroskaSource::clearPendingFrames() { 474 while (!mPendingFrames.empty()) { 475 MediaBuffer *frame = *mPendingFrames.begin(); 476 mPendingFrames.erase(mPendingFrames.begin()); 477 478 frame->release(); 479 frame = NULL; 480 } 481} 482 483status_t MatroskaSource::readBlock() { 484 CHECK(mPendingFrames.empty()); 485 486 if (mBlockIter.eos()) { 487 return ERROR_END_OF_STREAM; 488 } 489 490 const mkvparser::Block *block = mBlockIter.block(); 491 492 int64_t timeUs = mBlockIter.blockTimeUs(); 493 494 for (int i = 0; i < block->GetFrameCount(); ++i) { 495 const mkvparser::Block::Frame &frame = block->GetFrame(i); 496 497 MediaBuffer *mbuf = new MediaBuffer(frame.len); 498 mbuf->meta_data()->setInt64(kKeyTime, timeUs); 499 mbuf->meta_data()->setInt32(kKeyIsSyncFrame, block->IsKey()); 500 501 long n = frame.Read(mExtractor->mReader, (unsigned char *)mbuf->data()); 502 if (n != 0) { 503 mPendingFrames.clear(); 504 505 mBlockIter.advance(); 506 return ERROR_IO; 507 } 508 509 mPendingFrames.push_back(mbuf); 510 } 511 512 mBlockIter.advance(); 513 514 return OK; 515} 516 517status_t MatroskaSource::read( 518 MediaBuffer **out, const ReadOptions *options) { 519 *out = NULL; 520 521 int64_t targetSampleTimeUs = -1ll; 522 523 int64_t seekTimeUs; 524 ReadOptions::SeekMode mode; 525 if (options && options->getSeekTo(&seekTimeUs, &mode) 526 && !mExtractor->isLiveStreaming()) { 527 clearPendingFrames(); 528 529 // Apparently keyframe indication in audio tracks is unreliable, 530 // fortunately in all our currently supported audio encodings every 531 // frame is effectively a keyframe. 532 int64_t actualFrameTimeUs; 533 mBlockIter.seek(seekTimeUs, !mIsAudio, &actualFrameTimeUs); 534 535 if (mode == ReadOptions::SEEK_CLOSEST) { 536 targetSampleTimeUs = actualFrameTimeUs; 537 } 538 } 539 540 while (mPendingFrames.empty()) { 541 status_t err = readBlock(); 542 543 if (err != OK) { 544 clearPendingFrames(); 545 546 return err; 547 } 548 } 549 550 MediaBuffer *frame = *mPendingFrames.begin(); 551 mPendingFrames.erase(mPendingFrames.begin()); 552 553 if (mType != AVC) { 554 if (targetSampleTimeUs >= 0ll) { 555 frame->meta_data()->setInt64( 556 kKeyTargetTime, targetSampleTimeUs); 557 } 558 559 *out = frame; 560 561 return OK; 562 } 563 564 // Each input frame contains one or more NAL fragments, each fragment 565 // is prefixed by mNALSizeLen bytes giving the fragment length, 566 // followed by a corresponding number of bytes containing the fragment. 567 // We output all these fragments into a single large buffer separated 568 // by startcodes (0x00 0x00 0x00 0x01). 569 570 const uint8_t *srcPtr = 571 (const uint8_t *)frame->data() + frame->range_offset(); 572 573 size_t srcSize = frame->range_length(); 574 575 size_t dstSize = 0; 576 MediaBuffer *buffer = NULL; 577 uint8_t *dstPtr = NULL; 578 579 for (int32_t pass = 0; pass < 2; ++pass) { 580 size_t srcOffset = 0; 581 size_t dstOffset = 0; 582 while (srcOffset + mNALSizeLen <= srcSize) { 583 size_t NALsize; 584 switch (mNALSizeLen) { 585 case 1: NALsize = srcPtr[srcOffset]; break; 586 case 2: NALsize = U16_AT(srcPtr + srcOffset); break; 587 case 3: NALsize = U24_AT(srcPtr + srcOffset); break; 588 case 4: NALsize = U32_AT(srcPtr + srcOffset); break; 589 default: 590 TRESPASS(); 591 } 592 593 if (srcOffset + mNALSizeLen + NALsize > srcSize) { 594 break; 595 } 596 597 if (pass == 1) { 598 memcpy(&dstPtr[dstOffset], "\x00\x00\x00\x01", 4); 599 600 memcpy(&dstPtr[dstOffset + 4], 601 &srcPtr[srcOffset + mNALSizeLen], 602 NALsize); 603 } 604 605 dstOffset += 4; // 0x00 00 00 01 606 dstOffset += NALsize; 607 608 srcOffset += mNALSizeLen + NALsize; 609 } 610 611 if (srcOffset < srcSize) { 612 // There were trailing bytes or not enough data to complete 613 // a fragment. 614 615 frame->release(); 616 frame = NULL; 617 618 return ERROR_MALFORMED; 619 } 620 621 if (pass == 0) { 622 dstSize = dstOffset; 623 624 buffer = new MediaBuffer(dstSize); 625 626 int64_t timeUs; 627 CHECK(frame->meta_data()->findInt64(kKeyTime, &timeUs)); 628 int32_t isSync; 629 CHECK(frame->meta_data()->findInt32(kKeyIsSyncFrame, &isSync)); 630 631 buffer->meta_data()->setInt64(kKeyTime, timeUs); 632 buffer->meta_data()->setInt32(kKeyIsSyncFrame, isSync); 633 634 dstPtr = (uint8_t *)buffer->data(); 635 } 636 } 637 638 frame->release(); 639 frame = NULL; 640 641 if (targetSampleTimeUs >= 0ll) { 642 buffer->meta_data()->setInt64( 643 kKeyTargetTime, targetSampleTimeUs); 644 } 645 646 *out = buffer; 647 648 return OK; 649} 650 651//////////////////////////////////////////////////////////////////////////////// 652 653MatroskaExtractor::MatroskaExtractor(const sp<DataSource> &source) 654 : mDataSource(source), 655 mReader(new DataSourceReader(mDataSource)), 656 mSegment(NULL), 657 mExtractedThumbnails(false), 658 mIsWebm(false) { 659 off64_t size; 660 mIsLiveStreaming = 661 (mDataSource->flags() 662 & (DataSource::kWantsPrefetching 663 | DataSource::kIsCachingDataSource)) 664 && mDataSource->getSize(&size) != OK; 665 666 mkvparser::EBMLHeader ebmlHeader; 667 long long pos; 668 if (ebmlHeader.Parse(mReader, pos) < 0) { 669 return; 670 } 671 672 if (ebmlHeader.m_docType && !strcmp("webm", ebmlHeader.m_docType)) { 673 mIsWebm = true; 674 } 675 676 long long ret = 677 mkvparser::Segment::CreateInstance(mReader, pos, mSegment); 678 679 if (ret) { 680 CHECK(mSegment == NULL); 681 return; 682 } 683 684 ret = mSegment->ParseHeaders(); 685 CHECK_EQ(ret, 0); 686 687 long len; 688 ret = mSegment->LoadCluster(pos, len); 689 CHECK_EQ(ret, 0); 690 691 if (ret < 0) { 692 delete mSegment; 693 mSegment = NULL; 694 return; 695 } 696 697#if 0 698 const mkvparser::SegmentInfo *info = mSegment->GetInfo(); 699 ALOGI("muxing app: %s, writing app: %s", 700 info->GetMuxingAppAsUTF8(), 701 info->GetWritingAppAsUTF8()); 702#endif 703 704 addTracks(); 705} 706 707MatroskaExtractor::~MatroskaExtractor() { 708 delete mSegment; 709 mSegment = NULL; 710 711 delete mReader; 712 mReader = NULL; 713} 714 715size_t MatroskaExtractor::countTracks() { 716 return mTracks.size(); 717} 718 719sp<MediaSource> MatroskaExtractor::getTrack(size_t index) { 720 if (index >= mTracks.size()) { 721 return NULL; 722 } 723 724 return new MatroskaSource(this, index); 725} 726 727sp<MetaData> MatroskaExtractor::getTrackMetaData( 728 size_t index, uint32_t flags) { 729 if (index >= mTracks.size()) { 730 return NULL; 731 } 732 733 if ((flags & kIncludeExtensiveMetaData) && !mExtractedThumbnails 734 && !isLiveStreaming()) { 735 findThumbnails(); 736 mExtractedThumbnails = true; 737 } 738 739 return mTracks.itemAt(index).mMeta; 740} 741 742bool MatroskaExtractor::isLiveStreaming() const { 743 return mIsLiveStreaming; 744} 745 746static void addESDSFromCodecPrivate( 747 const sp<MetaData> &meta, 748 bool isAudio, const void *priv, size_t privSize) { 749 static const uint8_t kStaticESDS[] = { 750 0x03, 22, 751 0x00, 0x00, // ES_ID 752 0x00, // streamDependenceFlag, URL_Flag, OCRstreamFlag 753 754 0x04, 17, 755 0x40, // ObjectTypeIndication 756 0x00, 0x00, 0x00, 0x00, 757 0x00, 0x00, 0x00, 0x00, 758 0x00, 0x00, 0x00, 0x00, 759 760 0x05, 761 // CodecSpecificInfo (with size prefix) follows 762 }; 763 764 // Make sure all sizes can be coded in a single byte. 765 CHECK(privSize + 22 - 2 < 128); 766 size_t esdsSize = sizeof(kStaticESDS) + privSize + 1; 767 uint8_t *esds = new uint8_t[esdsSize]; 768 memcpy(esds, kStaticESDS, sizeof(kStaticESDS)); 769 uint8_t *ptr = esds + sizeof(kStaticESDS); 770 *ptr++ = privSize; 771 memcpy(ptr, priv, privSize); 772 773 // Increment by codecPrivateSize less 2 bytes that are accounted for 774 // already in lengths of 22/17 775 esds[1] += privSize - 2; 776 esds[6] += privSize - 2; 777 778 // Set ObjectTypeIndication. 779 esds[7] = isAudio ? 0x40 // Audio ISO/IEC 14496-3 780 : 0x20; // Visual ISO/IEC 14496-2 781 782 meta->setData(kKeyESDS, 0, esds, esdsSize); 783 784 delete[] esds; 785 esds = NULL; 786} 787 788void addVorbisCodecInfo( 789 const sp<MetaData> &meta, 790 const void *_codecPrivate, size_t codecPrivateSize) { 791 // printf("vorbis private data follows:\n"); 792 // hexdump(_codecPrivate, codecPrivateSize); 793 794 CHECK(codecPrivateSize >= 3); 795 796 const uint8_t *codecPrivate = (const uint8_t *)_codecPrivate; 797 CHECK(codecPrivate[0] == 0x02); 798 799 size_t len1 = codecPrivate[1]; 800 size_t len2 = codecPrivate[2]; 801 802 CHECK(codecPrivateSize > 3 + len1 + len2); 803 804 CHECK(codecPrivate[3] == 0x01); 805 meta->setData(kKeyVorbisInfo, 0, &codecPrivate[3], len1); 806 807 CHECK(codecPrivate[len1 + 3] == 0x03); 808 809 CHECK(codecPrivate[len1 + len2 + 3] == 0x05); 810 meta->setData( 811 kKeyVorbisBooks, 0, &codecPrivate[len1 + len2 + 3], 812 codecPrivateSize - len1 - len2 - 3); 813} 814 815void MatroskaExtractor::addTracks() { 816 const mkvparser::Tracks *tracks = mSegment->GetTracks(); 817 818 for (size_t index = 0; index < tracks->GetTracksCount(); ++index) { 819 const mkvparser::Track *track = tracks->GetTrackByIndex(index); 820 821 if (track == NULL) { 822 // Apparently this is currently valid (if unexpected) behaviour 823 // of the mkv parser lib. 824 continue; 825 } 826 827 const char *const codecID = track->GetCodecId(); 828 ALOGV("codec id = %s", codecID); 829 ALOGV("codec name = %s", track->GetCodecNameAsUTF8()); 830 831 size_t codecPrivateSize; 832 const unsigned char *codecPrivate = 833 track->GetCodecPrivate(codecPrivateSize); 834 835 enum { VIDEO_TRACK = 1, AUDIO_TRACK = 2 }; 836 837 sp<MetaData> meta = new MetaData; 838 839 switch (track->GetType()) { 840 case VIDEO_TRACK: 841 { 842 const mkvparser::VideoTrack *vtrack = 843 static_cast<const mkvparser::VideoTrack *>(track); 844 845 if (!strcmp("V_MPEG4/ISO/AVC", codecID)) { 846 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC); 847 meta->setData(kKeyAVCC, 0, codecPrivate, codecPrivateSize); 848 } else if (!strcmp("V_MPEG4/ISO/ASP", codecID)) { 849 if (codecPrivateSize > 0) { 850 meta->setCString( 851 kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4); 852 addESDSFromCodecPrivate( 853 meta, false, codecPrivate, codecPrivateSize); 854 } else { 855 ALOGW("%s is detected, but does not have configuration.", 856 codecID); 857 continue; 858 } 859 } else if (!strcmp("V_VP8", codecID)) { 860 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VPX); 861 } else { 862 ALOGW("%s is not supported.", codecID); 863 continue; 864 } 865 866 meta->setInt32(kKeyWidth, vtrack->GetWidth()); 867 meta->setInt32(kKeyHeight, vtrack->GetHeight()); 868 break; 869 } 870 871 case AUDIO_TRACK: 872 { 873 const mkvparser::AudioTrack *atrack = 874 static_cast<const mkvparser::AudioTrack *>(track); 875 876 if (!strcmp("A_AAC", codecID)) { 877 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC); 878 CHECK(codecPrivateSize >= 2); 879 880 addESDSFromCodecPrivate( 881 meta, true, codecPrivate, codecPrivateSize); 882 } else if (!strcmp("A_VORBIS", codecID)) { 883 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS); 884 885 addVorbisCodecInfo(meta, codecPrivate, codecPrivateSize); 886 } else if (!strcmp("A_MPEG/L3", codecID)) { 887 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG); 888 } else { 889 ALOGW("%s is not supported.", codecID); 890 continue; 891 } 892 893 meta->setInt32(kKeySampleRate, atrack->GetSamplingRate()); 894 meta->setInt32(kKeyChannelCount, atrack->GetChannels()); 895 break; 896 } 897 898 default: 899 continue; 900 } 901 902 long long durationNs = mSegment->GetDuration(); 903 meta->setInt64(kKeyDuration, (durationNs + 500) / 1000); 904 905 mTracks.push(); 906 TrackInfo *trackInfo = &mTracks.editItemAt(mTracks.size() - 1); 907 trackInfo->mTrackNum = track->GetNumber(); 908 trackInfo->mMeta = meta; 909 } 910} 911 912void MatroskaExtractor::findThumbnails() { 913 for (size_t i = 0; i < mTracks.size(); ++i) { 914 TrackInfo *info = &mTracks.editItemAt(i); 915 916 const char *mime; 917 CHECK(info->mMeta->findCString(kKeyMIMEType, &mime)); 918 919 if (strncasecmp(mime, "video/", 6)) { 920 continue; 921 } 922 923 BlockIterator iter(this, info->mTrackNum); 924 int32_t i = 0; 925 int64_t thumbnailTimeUs = 0; 926 size_t maxBlockSize = 0; 927 while (!iter.eos() && i < 20) { 928 if (iter.block()->IsKey()) { 929 ++i; 930 931 size_t blockSize = 0; 932 for (int i = 0; i < iter.block()->GetFrameCount(); ++i) { 933 blockSize += iter.block()->GetFrame(i).len; 934 } 935 936 if (blockSize > maxBlockSize) { 937 maxBlockSize = blockSize; 938 thumbnailTimeUs = iter.blockTimeUs(); 939 } 940 } 941 iter.advance(); 942 } 943 info->mMeta->setInt64(kKeyThumbnailTime, thumbnailTimeUs); 944 } 945} 946 947sp<MetaData> MatroskaExtractor::getMetaData() { 948 sp<MetaData> meta = new MetaData; 949 950 meta->setCString( 951 kKeyMIMEType, 952 mIsWebm ? "video/webm" : MEDIA_MIMETYPE_CONTAINER_MATROSKA); 953 954 return meta; 955} 956 957uint32_t MatroskaExtractor::flags() const { 958 uint32_t x = CAN_PAUSE; 959 if (!isLiveStreaming()) { 960 x |= CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK; 961 } 962 963 return x; 964} 965 966bool SniffMatroska( 967 const sp<DataSource> &source, String8 *mimeType, float *confidence, 968 sp<AMessage> *) { 969 DataSourceReader reader(source); 970 mkvparser::EBMLHeader ebmlHeader; 971 long long pos; 972 if (ebmlHeader.Parse(&reader, pos) < 0) { 973 return false; 974 } 975 976 mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_MATROSKA); 977 *confidence = 0.6; 978 979 return true; 980} 981 982} // namespace android 983