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