MatroskaExtractor.cpp revision 5ec58d925520e6913fba3fc54413881af751c610
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 int64_t seekTimeNs = seekTimeUs * 1000ll; 317 318 mCluster = mExtractor->mSegment->FindCluster(seekTimeNs); 319 mBlockEntry = NULL; 320 mBlockEntryIndex = 0; 321 322 long prevKeyFrameBlockEntryIndex = -1; 323 324 for (;;) { 325 advance_l(); 326 327 if (eos()) { 328 break; 329 } 330 331 if (block()->GetTrackNumber() != mTrackNum) { 332 continue; 333 } 334 335 if (block()->IsKey()) { 336 prevKeyFrameBlockEntryIndex = mBlockEntryIndex - 1; 337 } 338 339 int64_t timeNs = block()->GetTime(mCluster); 340 341 if (timeNs >= seekTimeNs) { 342 *actualFrameTimeUs = (timeNs + 500ll) / 1000ll; 343 break; 344 } 345 } 346 347 if (eos()) { 348 return; 349 } 350 351 if (seekToKeyFrame && !block()->IsKey()) { 352 CHECK_GE(prevKeyFrameBlockEntryIndex, 0); 353 mBlockEntryIndex = prevKeyFrameBlockEntryIndex; 354 advance_l(); 355 } 356} 357 358const mkvparser::Block *BlockIterator::block() const { 359 CHECK(!eos()); 360 361 return mBlockEntry->GetBlock(); 362} 363 364int64_t BlockIterator::blockTimeUs() const { 365 return (mBlockEntry->GetBlock()->GetTime(mCluster) + 500ll) / 1000ll; 366} 367 368//////////////////////////////////////////////////////////////////////////////// 369 370static unsigned U24_AT(const uint8_t *ptr) { 371 return ptr[0] << 16 | ptr[1] << 8 | ptr[2]; 372} 373 374static size_t clz(uint8_t x) { 375 size_t numLeadingZeroes = 0; 376 377 while (!(x & 0x80)) { 378 ++numLeadingZeroes; 379 x = x << 1; 380 } 381 382 return numLeadingZeroes; 383} 384 385void MatroskaSource::clearPendingFrames() { 386 while (!mPendingFrames.empty()) { 387 MediaBuffer *frame = *mPendingFrames.begin(); 388 mPendingFrames.erase(mPendingFrames.begin()); 389 390 frame->release(); 391 frame = NULL; 392 } 393} 394 395status_t MatroskaSource::readBlock() { 396 CHECK(mPendingFrames.empty()); 397 398 if (mBlockIter.eos()) { 399 return ERROR_END_OF_STREAM; 400 } 401 402 const mkvparser::Block *block = mBlockIter.block(); 403 404 int64_t timeUs = mBlockIter.blockTimeUs(); 405 406 for (int i = 0; i < block->GetFrameCount(); ++i) { 407 const mkvparser::Block::Frame &frame = block->GetFrame(i); 408 409 MediaBuffer *mbuf = new MediaBuffer(frame.len); 410 mbuf->meta_data()->setInt64(kKeyTime, timeUs); 411 mbuf->meta_data()->setInt32(kKeyIsSyncFrame, block->IsKey()); 412 413 long n = frame.Read(mExtractor->mReader, (unsigned char *)mbuf->data()); 414 if (n != 0) { 415 mPendingFrames.clear(); 416 417 mBlockIter.advance(); 418 return ERROR_IO; 419 } 420 421 mPendingFrames.push_back(mbuf); 422 } 423 424 mBlockIter.advance(); 425 426 return OK; 427} 428 429status_t MatroskaSource::read( 430 MediaBuffer **out, const ReadOptions *options) { 431 *out = NULL; 432 433 int64_t targetSampleTimeUs = -1ll; 434 435 int64_t seekTimeUs; 436 ReadOptions::SeekMode mode; 437 if (options && options->getSeekTo(&seekTimeUs, &mode) 438 && !mExtractor->isLiveStreaming()) { 439 clearPendingFrames(); 440 441 // Apparently keyframe indication in audio tracks is unreliable, 442 // fortunately in all our currently supported audio encodings every 443 // frame is effectively a keyframe. 444 int64_t actualFrameTimeUs; 445 mBlockIter.seek(seekTimeUs, !mIsAudio, &actualFrameTimeUs); 446 447 if (mode == ReadOptions::SEEK_CLOSEST) { 448 targetSampleTimeUs = actualFrameTimeUs; 449 } 450 } 451 452 while (mPendingFrames.empty()) { 453 status_t err = readBlock(); 454 455 if (err != OK) { 456 clearPendingFrames(); 457 458 return err; 459 } 460 } 461 462 MediaBuffer *frame = *mPendingFrames.begin(); 463 mPendingFrames.erase(mPendingFrames.begin()); 464 465 if (mType != AVC) { 466 if (targetSampleTimeUs >= 0ll) { 467 frame->meta_data()->setInt64( 468 kKeyTargetTime, targetSampleTimeUs); 469 } 470 471 *out = frame; 472 473 return OK; 474 } 475 476 // Each input frame contains one or more NAL fragments, each fragment 477 // is prefixed by mNALSizeLen bytes giving the fragment length, 478 // followed by a corresponding number of bytes containing the fragment. 479 // We output all these fragments into a single large buffer separated 480 // by startcodes (0x00 0x00 0x00 0x01). 481 482 const uint8_t *srcPtr = 483 (const uint8_t *)frame->data() + frame->range_offset(); 484 485 size_t srcSize = frame->range_length(); 486 487 size_t dstSize = 0; 488 MediaBuffer *buffer = NULL; 489 uint8_t *dstPtr = NULL; 490 491 for (int32_t pass = 0; pass < 2; ++pass) { 492 size_t srcOffset = 0; 493 size_t dstOffset = 0; 494 while (srcOffset + mNALSizeLen <= srcSize) { 495 size_t NALsize; 496 switch (mNALSizeLen) { 497 case 1: NALsize = srcPtr[srcOffset]; break; 498 case 2: NALsize = U16_AT(srcPtr + srcOffset); break; 499 case 3: NALsize = U24_AT(srcPtr + srcOffset); break; 500 case 4: NALsize = U32_AT(srcPtr + srcOffset); break; 501 default: 502 TRESPASS(); 503 } 504 505 if (srcOffset + mNALSizeLen + NALsize > srcSize) { 506 break; 507 } 508 509 if (pass == 1) { 510 memcpy(&dstPtr[dstOffset], "\x00\x00\x00\x01", 4); 511 512 memcpy(&dstPtr[dstOffset + 4], 513 &srcPtr[srcOffset + mNALSizeLen], 514 NALsize); 515 } 516 517 dstOffset += 4; // 0x00 00 00 01 518 dstOffset += NALsize; 519 520 srcOffset += mNALSizeLen + NALsize; 521 } 522 523 if (srcOffset < srcSize) { 524 // There were trailing bytes or not enough data to complete 525 // a fragment. 526 527 frame->release(); 528 frame = NULL; 529 530 return ERROR_MALFORMED; 531 } 532 533 if (pass == 0) { 534 dstSize = dstOffset; 535 536 buffer = new MediaBuffer(dstSize); 537 538 int64_t timeUs; 539 CHECK(frame->meta_data()->findInt64(kKeyTime, &timeUs)); 540 int32_t isSync; 541 CHECK(frame->meta_data()->findInt32(kKeyIsSyncFrame, &isSync)); 542 543 buffer->meta_data()->setInt64(kKeyTime, timeUs); 544 buffer->meta_data()->setInt32(kKeyIsSyncFrame, isSync); 545 546 dstPtr = (uint8_t *)buffer->data(); 547 } 548 } 549 550 frame->release(); 551 frame = NULL; 552 553 if (targetSampleTimeUs >= 0ll) { 554 buffer->meta_data()->setInt64( 555 kKeyTargetTime, targetSampleTimeUs); 556 } 557 558 *out = buffer; 559 560 return OK; 561} 562 563//////////////////////////////////////////////////////////////////////////////// 564 565MatroskaExtractor::MatroskaExtractor(const sp<DataSource> &source) 566 : mDataSource(source), 567 mReader(new DataSourceReader(mDataSource)), 568 mSegment(NULL), 569 mExtractedThumbnails(false), 570 mIsWebm(false) { 571 off64_t size; 572 mIsLiveStreaming = 573 (mDataSource->flags() 574 & (DataSource::kWantsPrefetching 575 | DataSource::kIsCachingDataSource)) 576 && mDataSource->getSize(&size) != OK; 577 578 mkvparser::EBMLHeader ebmlHeader; 579 long long pos; 580 if (ebmlHeader.Parse(mReader, pos) < 0) { 581 return; 582 } 583 584 if (ebmlHeader.m_docType && !strcmp("webm", ebmlHeader.m_docType)) { 585 mIsWebm = true; 586 } 587 588 long long ret = 589 mkvparser::Segment::CreateInstance(mReader, pos, mSegment); 590 591 if (ret) { 592 CHECK(mSegment == NULL); 593 return; 594 } 595 596 if (isLiveStreaming()) { 597 ret = mSegment->ParseHeaders(); 598 CHECK_EQ(ret, 0); 599 600 long len; 601 ret = mSegment->LoadCluster(pos, len); 602 CHECK_EQ(ret, 0); 603 } else { 604 ret = mSegment->Load(); 605 } 606 607 if (ret < 0) { 608 delete mSegment; 609 mSegment = NULL; 610 return; 611 } 612 613#if 0 614 const mkvparser::SegmentInfo *info = mSegment->GetInfo(); 615 ALOGI("muxing app: %s, writing app: %s", 616 info->GetMuxingAppAsUTF8(), 617 info->GetWritingAppAsUTF8()); 618#endif 619 620 addTracks(); 621} 622 623MatroskaExtractor::~MatroskaExtractor() { 624 delete mSegment; 625 mSegment = NULL; 626 627 delete mReader; 628 mReader = NULL; 629} 630 631size_t MatroskaExtractor::countTracks() { 632 return mTracks.size(); 633} 634 635sp<MediaSource> MatroskaExtractor::getTrack(size_t index) { 636 if (index >= mTracks.size()) { 637 return NULL; 638 } 639 640 return new MatroskaSource(this, index); 641} 642 643sp<MetaData> MatroskaExtractor::getTrackMetaData( 644 size_t index, uint32_t flags) { 645 if (index >= mTracks.size()) { 646 return NULL; 647 } 648 649 if ((flags & kIncludeExtensiveMetaData) && !mExtractedThumbnails 650 && !isLiveStreaming()) { 651 findThumbnails(); 652 mExtractedThumbnails = true; 653 } 654 655 return mTracks.itemAt(index).mMeta; 656} 657 658bool MatroskaExtractor::isLiveStreaming() const { 659 return mIsLiveStreaming; 660} 661 662static void addESDSFromCodecPrivate( 663 const sp<MetaData> &meta, 664 bool isAudio, const void *priv, size_t privSize) { 665 static const uint8_t kStaticESDS[] = { 666 0x03, 22, 667 0x00, 0x00, // ES_ID 668 0x00, // streamDependenceFlag, URL_Flag, OCRstreamFlag 669 670 0x04, 17, 671 0x40, // ObjectTypeIndication 672 0x00, 0x00, 0x00, 0x00, 673 0x00, 0x00, 0x00, 0x00, 674 0x00, 0x00, 0x00, 0x00, 675 676 0x05, 677 // CodecSpecificInfo (with size prefix) follows 678 }; 679 680 // Make sure all sizes can be coded in a single byte. 681 CHECK(privSize + 22 - 2 < 128); 682 size_t esdsSize = sizeof(kStaticESDS) + privSize + 1; 683 uint8_t *esds = new uint8_t[esdsSize]; 684 memcpy(esds, kStaticESDS, sizeof(kStaticESDS)); 685 uint8_t *ptr = esds + sizeof(kStaticESDS); 686 *ptr++ = privSize; 687 memcpy(ptr, priv, privSize); 688 689 // Increment by codecPrivateSize less 2 bytes that are accounted for 690 // already in lengths of 22/17 691 esds[1] += privSize - 2; 692 esds[6] += privSize - 2; 693 694 // Set ObjectTypeIndication. 695 esds[7] = isAudio ? 0x40 // Audio ISO/IEC 14496-3 696 : 0x20; // Visual ISO/IEC 14496-2 697 698 meta->setData(kKeyESDS, 0, esds, esdsSize); 699 700 delete[] esds; 701 esds = NULL; 702} 703 704void addVorbisCodecInfo( 705 const sp<MetaData> &meta, 706 const void *_codecPrivate, size_t codecPrivateSize) { 707 // printf("vorbis private data follows:\n"); 708 // hexdump(_codecPrivate, codecPrivateSize); 709 710 CHECK(codecPrivateSize >= 3); 711 712 const uint8_t *codecPrivate = (const uint8_t *)_codecPrivate; 713 CHECK(codecPrivate[0] == 0x02); 714 715 size_t len1 = codecPrivate[1]; 716 size_t len2 = codecPrivate[2]; 717 718 CHECK(codecPrivateSize > 3 + len1 + len2); 719 720 CHECK(codecPrivate[3] == 0x01); 721 meta->setData(kKeyVorbisInfo, 0, &codecPrivate[3], len1); 722 723 CHECK(codecPrivate[len1 + 3] == 0x03); 724 725 CHECK(codecPrivate[len1 + len2 + 3] == 0x05); 726 meta->setData( 727 kKeyVorbisBooks, 0, &codecPrivate[len1 + len2 + 3], 728 codecPrivateSize - len1 - len2 - 3); 729} 730 731void MatroskaExtractor::addTracks() { 732 const mkvparser::Tracks *tracks = mSegment->GetTracks(); 733 734 for (size_t index = 0; index < tracks->GetTracksCount(); ++index) { 735 const mkvparser::Track *track = tracks->GetTrackByIndex(index); 736 737 if (track == NULL) { 738 // Apparently this is currently valid (if unexpected) behaviour 739 // of the mkv parser lib. 740 continue; 741 } 742 743 const char *const codecID = track->GetCodecId(); 744 ALOGV("codec id = %s", codecID); 745 ALOGV("codec name = %s", track->GetCodecNameAsUTF8()); 746 747 size_t codecPrivateSize; 748 const unsigned char *codecPrivate = 749 track->GetCodecPrivate(codecPrivateSize); 750 751 enum { VIDEO_TRACK = 1, AUDIO_TRACK = 2 }; 752 753 sp<MetaData> meta = new MetaData; 754 755 switch (track->GetType()) { 756 case VIDEO_TRACK: 757 { 758 const mkvparser::VideoTrack *vtrack = 759 static_cast<const mkvparser::VideoTrack *>(track); 760 761 if (!strcmp("V_MPEG4/ISO/AVC", codecID)) { 762 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC); 763 meta->setData(kKeyAVCC, 0, codecPrivate, codecPrivateSize); 764 } else if (!strcmp("V_MPEG4/ISO/ASP", codecID)) { 765 if (codecPrivateSize > 0) { 766 meta->setCString( 767 kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4); 768 addESDSFromCodecPrivate( 769 meta, false, codecPrivate, codecPrivateSize); 770 } else { 771 ALOGW("%s is detected, but does not have configuration.", 772 codecID); 773 continue; 774 } 775 } else if (!strcmp("V_VP8", codecID)) { 776 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VPX); 777 } else { 778 ALOGW("%s is not supported.", codecID); 779 continue; 780 } 781 782 meta->setInt32(kKeyWidth, vtrack->GetWidth()); 783 meta->setInt32(kKeyHeight, vtrack->GetHeight()); 784 break; 785 } 786 787 case AUDIO_TRACK: 788 { 789 const mkvparser::AudioTrack *atrack = 790 static_cast<const mkvparser::AudioTrack *>(track); 791 792 if (!strcmp("A_AAC", codecID)) { 793 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC); 794 CHECK(codecPrivateSize >= 2); 795 796 addESDSFromCodecPrivate( 797 meta, true, codecPrivate, codecPrivateSize); 798 } else if (!strcmp("A_VORBIS", codecID)) { 799 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS); 800 801 addVorbisCodecInfo(meta, codecPrivate, codecPrivateSize); 802 } else if (!strcmp("A_MPEG/L3", codecID)) { 803 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG); 804 } else { 805 ALOGW("%s is not supported.", codecID); 806 continue; 807 } 808 809 meta->setInt32(kKeySampleRate, atrack->GetSamplingRate()); 810 meta->setInt32(kKeyChannelCount, atrack->GetChannels()); 811 break; 812 } 813 814 default: 815 continue; 816 } 817 818 long long durationNs = mSegment->GetDuration(); 819 meta->setInt64(kKeyDuration, (durationNs + 500) / 1000); 820 821 mTracks.push(); 822 TrackInfo *trackInfo = &mTracks.editItemAt(mTracks.size() - 1); 823 trackInfo->mTrackNum = track->GetNumber(); 824 trackInfo->mMeta = meta; 825 } 826} 827 828void MatroskaExtractor::findThumbnails() { 829 for (size_t i = 0; i < mTracks.size(); ++i) { 830 TrackInfo *info = &mTracks.editItemAt(i); 831 832 const char *mime; 833 CHECK(info->mMeta->findCString(kKeyMIMEType, &mime)); 834 835 if (strncasecmp(mime, "video/", 6)) { 836 continue; 837 } 838 839 BlockIterator iter(this, info->mTrackNum); 840 int32_t i = 0; 841 int64_t thumbnailTimeUs = 0; 842 size_t maxBlockSize = 0; 843 while (!iter.eos() && i < 20) { 844 if (iter.block()->IsKey()) { 845 ++i; 846 847 size_t blockSize = 0; 848 for (int i = 0; i < iter.block()->GetFrameCount(); ++i) { 849 blockSize += iter.block()->GetFrame(i).len; 850 } 851 852 if (blockSize > maxBlockSize) { 853 maxBlockSize = blockSize; 854 thumbnailTimeUs = iter.blockTimeUs(); 855 } 856 } 857 iter.advance(); 858 } 859 info->mMeta->setInt64(kKeyThumbnailTime, thumbnailTimeUs); 860 } 861} 862 863sp<MetaData> MatroskaExtractor::getMetaData() { 864 sp<MetaData> meta = new MetaData; 865 866 meta->setCString( 867 kKeyMIMEType, 868 mIsWebm ? "video/webm" : MEDIA_MIMETYPE_CONTAINER_MATROSKA); 869 870 return meta; 871} 872 873uint32_t MatroskaExtractor::flags() const { 874 uint32_t x = CAN_PAUSE; 875 if (!isLiveStreaming()) { 876 x |= CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK; 877 } 878 879 return x; 880} 881 882bool SniffMatroska( 883 const sp<DataSource> &source, String8 *mimeType, float *confidence, 884 sp<AMessage> *) { 885 DataSourceReader reader(source); 886 mkvparser::EBMLHeader ebmlHeader; 887 long long pos; 888 if (ebmlHeader.Parse(&reader, pos) < 0) { 889 return false; 890 } 891 892 mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_MATROSKA); 893 *confidence = 0.6; 894 895 return true; 896} 897 898} // namespace android 899