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 #include "avc_utils.h" 23 24 #include <media/stagefright/foundation/ADebug.h> 25 #include <media/stagefright/foundation/AUtils.h> 26 #include <media/stagefright/foundation/ABuffer.h> 27 #include <media/stagefright/foundation/ColorUtils.h> 28 #include <media/stagefright/foundation/hexdump.h> 29 #include <media/stagefright/DataSource.h> 30 #include <media/stagefright/MediaBuffer.h> 31 #include <media/stagefright/MediaDefs.h> 32 #include <media/stagefright/MediaErrors.h> 33 #include <media/stagefright/MediaSource.h> 34 #include <media/stagefright/MetaData.h> 35 #include <media/stagefright/Utils.h> 36 #include <utils/String8.h> 37 38 #include <inttypes.h> 39 40 namespace android { 41 42 struct DataSourceReader : public mkvparser::IMkvReader { 43 DataSourceReader(const sp<DataSource> &source) 44 : mSource(source) { 45 } 46 47 virtual int Read(long long position, long length, unsigned char* buffer) { 48 CHECK(position >= 0); 49 CHECK(length >= 0); 50 51 if (length == 0) { 52 return 0; 53 } 54 55 ssize_t n = mSource->readAt(position, buffer, length); 56 57 if (n <= 0) { 58 return -1; 59 } 60 61 return 0; 62 } 63 64 virtual int Length(long long* total, long long* available) { 65 off64_t size; 66 if (mSource->getSize(&size) != OK) { 67 *total = -1; 68 *available = (long long)((1ull << 63) - 1); 69 70 return 0; 71 } 72 73 if (total) { 74 *total = size; 75 } 76 77 if (available) { 78 *available = size; 79 } 80 81 return 0; 82 } 83 84 private: 85 sp<DataSource> mSource; 86 87 DataSourceReader(const DataSourceReader &); 88 DataSourceReader &operator=(const DataSourceReader &); 89 }; 90 91 //////////////////////////////////////////////////////////////////////////////// 92 93 struct BlockIterator { 94 BlockIterator(MatroskaExtractor *extractor, unsigned long trackNum, unsigned long index); 95 96 bool eos() const; 97 98 void advance(); 99 void reset(); 100 101 void seek( 102 int64_t seekTimeUs, bool isAudio, 103 int64_t *actualFrameTimeUs); 104 105 const mkvparser::Block *block() const; 106 int64_t blockTimeUs() const; 107 108 private: 109 MatroskaExtractor *mExtractor; 110 long long mTrackNum; 111 unsigned long mIndex; 112 113 const mkvparser::Cluster *mCluster; 114 const mkvparser::BlockEntry *mBlockEntry; 115 long mBlockEntryIndex; 116 117 void advance_l(); 118 119 BlockIterator(const BlockIterator &); 120 BlockIterator &operator=(const BlockIterator &); 121 }; 122 123 struct MatroskaSource : public MediaSource { 124 MatroskaSource( 125 const sp<MatroskaExtractor> &extractor, size_t index); 126 127 virtual status_t start(MetaData *params); 128 virtual status_t stop(); 129 130 virtual sp<MetaData> getFormat(); 131 132 virtual status_t read( 133 MediaBuffer **buffer, const ReadOptions *options); 134 135 protected: 136 virtual ~MatroskaSource(); 137 138 private: 139 enum Type { 140 AVC, 141 AAC, 142 OTHER 143 }; 144 145 sp<MatroskaExtractor> mExtractor; 146 size_t mTrackIndex; 147 Type mType; 148 bool mIsAudio; 149 BlockIterator mBlockIter; 150 ssize_t mNALSizeLen; // for type AVC 151 152 List<MediaBuffer *> mPendingFrames; 153 154 status_t advance(); 155 156 status_t setWebmBlockCryptoInfo(MediaBuffer *mbuf); 157 status_t readBlock(); 158 void clearPendingFrames(); 159 160 MatroskaSource(const MatroskaSource &); 161 MatroskaSource &operator=(const MatroskaSource &); 162 }; 163 164 const mkvparser::Track* MatroskaExtractor::TrackInfo::getTrack() const { 165 return mExtractor->mSegment->GetTracks()->GetTrackByNumber(mTrackNum); 166 } 167 168 // This function does exactly the same as mkvparser::Cues::Find, except that it 169 // searches in our own track based vectors. We should not need this once mkvparser 170 // adds the same functionality. 171 const mkvparser::CuePoint::TrackPosition *MatroskaExtractor::TrackInfo::find( 172 long long timeNs) const { 173 ALOGV("mCuePoints.size %zu", mCuePoints.size()); 174 if (mCuePoints.empty()) { 175 return NULL; 176 } 177 178 const mkvparser::CuePoint* cp = mCuePoints.itemAt(0); 179 const mkvparser::Track* track = getTrack(); 180 if (timeNs <= cp->GetTime(mExtractor->mSegment)) { 181 return cp->Find(track); 182 } 183 184 // Binary searches through relevant cues; assumes cues are ordered by timecode. 185 // If we do detect out-of-order cues, return NULL. 186 size_t lo = 0; 187 size_t hi = mCuePoints.size(); 188 while (lo < hi) { 189 const size_t mid = lo + (hi - lo) / 2; 190 const mkvparser::CuePoint* const midCp = mCuePoints.itemAt(mid); 191 const long long cueTimeNs = midCp->GetTime(mExtractor->mSegment); 192 if (cueTimeNs <= timeNs) { 193 lo = mid + 1; 194 } else { 195 hi = mid; 196 } 197 } 198 199 if (lo == 0) { 200 return NULL; 201 } 202 203 cp = mCuePoints.itemAt(lo - 1); 204 if (cp->GetTime(mExtractor->mSegment) > timeNs) { 205 return NULL; 206 } 207 208 return cp->Find(track); 209 } 210 211 MatroskaSource::MatroskaSource( 212 const sp<MatroskaExtractor> &extractor, size_t index) 213 : mExtractor(extractor), 214 mTrackIndex(index), 215 mType(OTHER), 216 mIsAudio(false), 217 mBlockIter(mExtractor.get(), 218 mExtractor->mTracks.itemAt(index).mTrackNum, 219 index), 220 mNALSizeLen(-1) { 221 sp<MetaData> meta = mExtractor->mTracks.itemAt(index).mMeta; 222 223 const char *mime; 224 CHECK(meta->findCString(kKeyMIMEType, &mime)); 225 226 mIsAudio = !strncasecmp("audio/", mime, 6); 227 228 if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 229 mType = AVC; 230 231 uint32_t dummy; 232 const uint8_t *avcc; 233 size_t avccSize; 234 int32_t nalSizeLen = 0; 235 if (meta->findInt32(kKeyNalLengthSize, &nalSizeLen)) { 236 if (nalSizeLen >= 0 && nalSizeLen <= 4) { 237 mNALSizeLen = nalSizeLen; 238 } 239 } else if (meta->findData(kKeyAVCC, &dummy, (const void **)&avcc, &avccSize) 240 && avccSize >= 5u) { 241 mNALSizeLen = 1 + (avcc[4] & 3); 242 ALOGV("mNALSizeLen = %zd", mNALSizeLen); 243 } else { 244 ALOGE("No mNALSizeLen"); 245 } 246 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 247 mType = AAC; 248 } 249 } 250 251 MatroskaSource::~MatroskaSource() { 252 clearPendingFrames(); 253 } 254 255 status_t MatroskaSource::start(MetaData * /* params */) { 256 if (mType == AVC && mNALSizeLen < 0) { 257 return ERROR_MALFORMED; 258 } 259 260 mBlockIter.reset(); 261 262 return OK; 263 } 264 265 status_t MatroskaSource::stop() { 266 clearPendingFrames(); 267 268 return OK; 269 } 270 271 sp<MetaData> MatroskaSource::getFormat() { 272 return mExtractor->mTracks.itemAt(mTrackIndex).mMeta; 273 } 274 275 //////////////////////////////////////////////////////////////////////////////// 276 277 BlockIterator::BlockIterator( 278 MatroskaExtractor *extractor, unsigned long trackNum, unsigned long index) 279 : mExtractor(extractor), 280 mTrackNum(trackNum), 281 mIndex(index), 282 mCluster(NULL), 283 mBlockEntry(NULL), 284 mBlockEntryIndex(0) { 285 reset(); 286 } 287 288 bool BlockIterator::eos() const { 289 return mCluster == NULL || mCluster->EOS(); 290 } 291 292 void BlockIterator::advance() { 293 Mutex::Autolock autoLock(mExtractor->mLock); 294 advance_l(); 295 } 296 297 void BlockIterator::advance_l() { 298 for (;;) { 299 long res = mCluster->GetEntry(mBlockEntryIndex, mBlockEntry); 300 ALOGV("GetEntry returned %ld", res); 301 302 long long pos; 303 long len; 304 if (res < 0) { 305 // Need to parse this cluster some more 306 307 CHECK_EQ(res, mkvparser::E_BUFFER_NOT_FULL); 308 309 res = mCluster->Parse(pos, len); 310 ALOGV("Parse returned %ld", res); 311 312 if (res < 0) { 313 // I/O error 314 315 ALOGE("Cluster::Parse returned result %ld", res); 316 317 mCluster = NULL; 318 break; 319 } 320 321 continue; 322 } else if (res == 0) { 323 // We're done with this cluster 324 325 const mkvparser::Cluster *nextCluster; 326 res = mExtractor->mSegment->ParseNext( 327 mCluster, nextCluster, pos, len); 328 ALOGV("ParseNext returned %ld", res); 329 330 if (res != 0) { 331 // EOF or error 332 333 mCluster = NULL; 334 break; 335 } 336 337 CHECK_EQ(res, 0); 338 CHECK(nextCluster != NULL); 339 CHECK(!nextCluster->EOS()); 340 341 mCluster = nextCluster; 342 343 res = mCluster->Parse(pos, len); 344 ALOGV("Parse (2) returned %ld", res); 345 CHECK_GE(res, 0); 346 347 mBlockEntryIndex = 0; 348 continue; 349 } 350 351 CHECK(mBlockEntry != NULL); 352 CHECK(mBlockEntry->GetBlock() != NULL); 353 ++mBlockEntryIndex; 354 355 if (mBlockEntry->GetBlock()->GetTrackNumber() == mTrackNum) { 356 break; 357 } 358 } 359 } 360 361 void BlockIterator::reset() { 362 Mutex::Autolock autoLock(mExtractor->mLock); 363 364 mCluster = mExtractor->mSegment->GetFirst(); 365 mBlockEntry = NULL; 366 mBlockEntryIndex = 0; 367 368 do { 369 advance_l(); 370 } while (!eos() && block()->GetTrackNumber() != mTrackNum); 371 } 372 373 void BlockIterator::seek( 374 int64_t seekTimeUs, bool isAudio, 375 int64_t *actualFrameTimeUs) { 376 Mutex::Autolock autoLock(mExtractor->mLock); 377 378 *actualFrameTimeUs = -1ll; 379 380 const int64_t seekTimeNs = seekTimeUs * 1000ll - mExtractor->mSeekPreRollNs; 381 382 mkvparser::Segment* const pSegment = mExtractor->mSegment; 383 384 // Special case the 0 seek to avoid loading Cues when the application 385 // extraneously seeks to 0 before playing. 386 if (seekTimeNs <= 0) { 387 ALOGV("Seek to beginning: %" PRId64, seekTimeUs); 388 mCluster = pSegment->GetFirst(); 389 mBlockEntryIndex = 0; 390 do { 391 advance_l(); 392 } while (!eos() && block()->GetTrackNumber() != mTrackNum); 393 return; 394 } 395 396 ALOGV("Seeking to: %" PRId64, seekTimeUs); 397 398 // If the Cues have not been located then find them. 399 const mkvparser::Cues* pCues = pSegment->GetCues(); 400 const mkvparser::SeekHead* pSH = pSegment->GetSeekHead(); 401 if (!pCues && pSH) { 402 const size_t count = pSH->GetCount(); 403 const mkvparser::SeekHead::Entry* pEntry; 404 ALOGV("No Cues yet"); 405 406 for (size_t index = 0; index < count; index++) { 407 pEntry = pSH->GetEntry(index); 408 409 if (pEntry->id == 0x0C53BB6B) { // Cues ID 410 long len; long long pos; 411 pSegment->ParseCues(pEntry->pos, pos, len); 412 pCues = pSegment->GetCues(); 413 ALOGV("Cues found"); 414 break; 415 } 416 } 417 418 if (!pCues) { 419 ALOGE("No Cues in file"); 420 return; 421 } 422 } 423 else if (!pSH) { 424 ALOGE("No SeekHead"); 425 return; 426 } 427 428 const mkvparser::CuePoint* pCP; 429 mkvparser::Tracks const *pTracks = pSegment->GetTracks(); 430 while (!pCues->DoneParsing()) { 431 pCues->LoadCuePoint(); 432 pCP = pCues->GetLast(); 433 CHECK(pCP); 434 435 size_t trackCount = mExtractor->mTracks.size(); 436 for (size_t index = 0; index < trackCount; ++index) { 437 MatroskaExtractor::TrackInfo& track = mExtractor->mTracks.editItemAt(index); 438 const mkvparser::Track *pTrack = pTracks->GetTrackByNumber(track.mTrackNum); 439 if (pTrack && pTrack->GetType() == 1 && pCP->Find(pTrack)) { // VIDEO_TRACK 440 track.mCuePoints.push_back(pCP); 441 } 442 } 443 444 if (pCP->GetTime(pSegment) >= seekTimeNs) { 445 ALOGV("Parsed past relevant Cue"); 446 break; 447 } 448 } 449 450 const mkvparser::CuePoint::TrackPosition *pTP = NULL; 451 const mkvparser::Track *thisTrack = pTracks->GetTrackByNumber(mTrackNum); 452 if (thisTrack->GetType() == 1) { // video 453 MatroskaExtractor::TrackInfo& track = mExtractor->mTracks.editItemAt(mIndex); 454 pTP = track.find(seekTimeNs); 455 } else { 456 // The Cue index is built around video keyframes 457 unsigned long int trackCount = pTracks->GetTracksCount(); 458 for (size_t index = 0; index < trackCount; ++index) { 459 const mkvparser::Track *pTrack = pTracks->GetTrackByIndex(index); 460 if (pTrack && pTrack->GetType() == 1 && pCues->Find(seekTimeNs, pTrack, pCP, pTP)) { 461 ALOGV("Video track located at %zu", index); 462 break; 463 } 464 } 465 } 466 467 468 // Always *search* based on the video track, but finalize based on mTrackNum 469 if (!pTP) { 470 ALOGE("Did not locate the video track for seeking"); 471 return; 472 } 473 474 mCluster = pSegment->FindOrPreloadCluster(pTP->m_pos); 475 476 CHECK(mCluster); 477 CHECK(!mCluster->EOS()); 478 479 // mBlockEntryIndex starts at 0 but m_block starts at 1 480 CHECK_GT(pTP->m_block, 0); 481 mBlockEntryIndex = pTP->m_block - 1; 482 483 for (;;) { 484 advance_l(); 485 486 if (eos()) break; 487 488 if (isAudio || block()->IsKey()) { 489 // Accept the first key frame 490 int64_t frameTimeUs = (block()->GetTime(mCluster) + 500LL) / 1000LL; 491 if (thisTrack->GetType() == 1 || frameTimeUs >= seekTimeUs) { 492 *actualFrameTimeUs = frameTimeUs; 493 ALOGV("Requested seek point: %" PRId64 " actual: %" PRId64, 494 seekTimeUs, *actualFrameTimeUs); 495 break; 496 } 497 } 498 } 499 } 500 501 const mkvparser::Block *BlockIterator::block() const { 502 CHECK(!eos()); 503 504 return mBlockEntry->GetBlock(); 505 } 506 507 int64_t BlockIterator::blockTimeUs() const { 508 if (mCluster == NULL || mBlockEntry == NULL) { 509 return -1; 510 } 511 return (mBlockEntry->GetBlock()->GetTime(mCluster) + 500ll) / 1000ll; 512 } 513 514 //////////////////////////////////////////////////////////////////////////////// 515 516 static unsigned U24_AT(const uint8_t *ptr) { 517 return ptr[0] << 16 | ptr[1] << 8 | ptr[2]; 518 } 519 520 void MatroskaSource::clearPendingFrames() { 521 while (!mPendingFrames.empty()) { 522 MediaBuffer *frame = *mPendingFrames.begin(); 523 mPendingFrames.erase(mPendingFrames.begin()); 524 525 frame->release(); 526 frame = NULL; 527 } 528 } 529 530 status_t MatroskaSource::setWebmBlockCryptoInfo(MediaBuffer *mbuf) { 531 if (mbuf->range_length() < 1 || mbuf->range_length() - 1 > INT32_MAX) { 532 // 1-byte signal 533 return ERROR_MALFORMED; 534 } 535 536 const uint8_t *data = (const uint8_t *)mbuf->data() + mbuf->range_offset(); 537 bool blockEncrypted = data[0] & 0x1; 538 if (blockEncrypted && mbuf->range_length() < 9) { 539 // 1-byte signal + 8-byte IV 540 return ERROR_MALFORMED; 541 } 542 543 sp<MetaData> meta = mbuf->meta_data(); 544 if (blockEncrypted) { 545 /* 546 * 0 1 2 3 547 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 548 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 549 * | Signal Byte | | 550 * +-+-+-+-+-+-+-+-+ IV | 551 * | | 552 * | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 553 * | | | 554 * |-+-+-+-+-+-+-+-+ | 555 * : Bytes 1..N of encrypted frame : 556 * | | 557 * | | 558 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 559 */ 560 int32_t plainSizes[] = { 0 }; 561 int32_t encryptedSizes[] = { static_cast<int32_t>(mbuf->range_length() - 9) }; 562 uint8_t ctrCounter[16] = { 0 }; 563 uint32_t type; 564 const uint8_t *keyId; 565 size_t keyIdSize; 566 sp<MetaData> trackMeta = mExtractor->mTracks.itemAt(mTrackIndex).mMeta; 567 CHECK(trackMeta->findData(kKeyCryptoKey, &type, (const void **)&keyId, &keyIdSize)); 568 meta->setData(kKeyCryptoKey, 0, keyId, keyIdSize); 569 memcpy(ctrCounter, data + 1, 8); 570 meta->setData(kKeyCryptoIV, 0, ctrCounter, 16); 571 meta->setData(kKeyPlainSizes, 0, plainSizes, sizeof(plainSizes)); 572 meta->setData(kKeyEncryptedSizes, 0, encryptedSizes, sizeof(encryptedSizes)); 573 mbuf->set_range(9, mbuf->range_length() - 9); 574 } else { 575 /* 576 * 0 1 2 3 577 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 578 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 579 * | Signal Byte | | 580 * +-+-+-+-+-+-+-+-+ | 581 * : Bytes 1..N of unencrypted frame : 582 * | | 583 * | | 584 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 585 */ 586 int32_t plainSizes[] = { static_cast<int32_t>(mbuf->range_length() - 1) }; 587 int32_t encryptedSizes[] = { 0 }; 588 meta->setData(kKeyPlainSizes, 0, plainSizes, sizeof(plainSizes)); 589 meta->setData(kKeyEncryptedSizes, 0, encryptedSizes, sizeof(encryptedSizes)); 590 mbuf->set_range(1, mbuf->range_length() - 1); 591 } 592 593 return OK; 594 } 595 596 status_t MatroskaSource::readBlock() { 597 CHECK(mPendingFrames.empty()); 598 599 if (mBlockIter.eos()) { 600 return ERROR_END_OF_STREAM; 601 } 602 603 const mkvparser::Block *block = mBlockIter.block(); 604 605 int64_t timeUs = mBlockIter.blockTimeUs(); 606 607 for (int i = 0; i < block->GetFrameCount(); ++i) { 608 const mkvparser::Block::Frame &frame = block->GetFrame(i); 609 610 MediaBuffer *mbuf = new MediaBuffer(frame.len); 611 mbuf->meta_data()->setInt64(kKeyTime, timeUs); 612 mbuf->meta_data()->setInt32(kKeyIsSyncFrame, block->IsKey()); 613 614 status_t err = frame.Read(mExtractor->mReader, static_cast<uint8_t *>(mbuf->data())); 615 if (err == OK 616 && mExtractor->mIsWebm 617 && mExtractor->mTracks.itemAt(mTrackIndex).mEncrypted) { 618 err = setWebmBlockCryptoInfo(mbuf); 619 } 620 621 if (err != OK) { 622 mPendingFrames.clear(); 623 624 mBlockIter.advance(); 625 mbuf->release(); 626 return err; 627 } 628 629 mPendingFrames.push_back(mbuf); 630 } 631 632 mBlockIter.advance(); 633 634 return OK; 635 } 636 637 status_t MatroskaSource::read( 638 MediaBuffer **out, const ReadOptions *options) { 639 *out = NULL; 640 641 int64_t targetSampleTimeUs = -1ll; 642 643 int64_t seekTimeUs; 644 ReadOptions::SeekMode mode; 645 if (options && options->getSeekTo(&seekTimeUs, &mode) 646 && !mExtractor->isLiveStreaming()) { 647 clearPendingFrames(); 648 649 // The audio we want is located by using the Cues to seek the video 650 // stream to find the target Cluster then iterating to finalize for 651 // audio. 652 int64_t actualFrameTimeUs; 653 mBlockIter.seek(seekTimeUs, mIsAudio, &actualFrameTimeUs); 654 655 if (mode == ReadOptions::SEEK_CLOSEST) { 656 targetSampleTimeUs = actualFrameTimeUs; 657 } 658 } 659 660 while (mPendingFrames.empty()) { 661 status_t err = readBlock(); 662 663 if (err != OK) { 664 clearPendingFrames(); 665 666 return err; 667 } 668 } 669 670 MediaBuffer *frame = *mPendingFrames.begin(); 671 mPendingFrames.erase(mPendingFrames.begin()); 672 673 if (mType != AVC || mNALSizeLen == 0) { 674 if (targetSampleTimeUs >= 0ll) { 675 frame->meta_data()->setInt64( 676 kKeyTargetTime, targetSampleTimeUs); 677 } 678 679 *out = frame; 680 681 return OK; 682 } 683 684 // Each input frame contains one or more NAL fragments, each fragment 685 // is prefixed by mNALSizeLen bytes giving the fragment length, 686 // followed by a corresponding number of bytes containing the fragment. 687 // We output all these fragments into a single large buffer separated 688 // by startcodes (0x00 0x00 0x00 0x01). 689 // 690 // When mNALSizeLen is 0, we assume the data is already in the format 691 // desired. 692 693 const uint8_t *srcPtr = 694 (const uint8_t *)frame->data() + frame->range_offset(); 695 696 size_t srcSize = frame->range_length(); 697 698 size_t dstSize = 0; 699 MediaBuffer *buffer = NULL; 700 uint8_t *dstPtr = NULL; 701 702 for (int32_t pass = 0; pass < 2; ++pass) { 703 size_t srcOffset = 0; 704 size_t dstOffset = 0; 705 while (srcOffset + mNALSizeLen <= srcSize) { 706 size_t NALsize; 707 switch (mNALSizeLen) { 708 case 1: NALsize = srcPtr[srcOffset]; break; 709 case 2: NALsize = U16_AT(srcPtr + srcOffset); break; 710 case 3: NALsize = U24_AT(srcPtr + srcOffset); break; 711 case 4: NALsize = U32_AT(srcPtr + srcOffset); break; 712 default: 713 TRESPASS(); 714 } 715 716 if (srcOffset + mNALSizeLen + NALsize <= srcOffset + mNALSizeLen) { 717 frame->release(); 718 frame = NULL; 719 720 return ERROR_MALFORMED; 721 } else if (srcOffset + mNALSizeLen + NALsize > srcSize) { 722 break; 723 } 724 725 if (pass == 1) { 726 memcpy(&dstPtr[dstOffset], "\x00\x00\x00\x01", 4); 727 728 if (frame != buffer) { 729 memcpy(&dstPtr[dstOffset + 4], 730 &srcPtr[srcOffset + mNALSizeLen], 731 NALsize); 732 } 733 } 734 735 dstOffset += 4; // 0x00 00 00 01 736 dstOffset += NALsize; 737 738 srcOffset += mNALSizeLen + NALsize; 739 } 740 741 if (srcOffset < srcSize) { 742 // There were trailing bytes or not enough data to complete 743 // a fragment. 744 745 frame->release(); 746 frame = NULL; 747 748 return ERROR_MALFORMED; 749 } 750 751 if (pass == 0) { 752 dstSize = dstOffset; 753 754 if (dstSize == srcSize && mNALSizeLen == 4) { 755 // In this special case we can re-use the input buffer by substituting 756 // each 4-byte nal size with a 4-byte start code 757 buffer = frame; 758 } else { 759 buffer = new MediaBuffer(dstSize); 760 } 761 762 int64_t timeUs; 763 CHECK(frame->meta_data()->findInt64(kKeyTime, &timeUs)); 764 int32_t isSync; 765 CHECK(frame->meta_data()->findInt32(kKeyIsSyncFrame, &isSync)); 766 767 buffer->meta_data()->setInt64(kKeyTime, timeUs); 768 buffer->meta_data()->setInt32(kKeyIsSyncFrame, isSync); 769 770 dstPtr = (uint8_t *)buffer->data(); 771 } 772 } 773 774 if (frame != buffer) { 775 frame->release(); 776 frame = NULL; 777 } 778 779 if (targetSampleTimeUs >= 0ll) { 780 buffer->meta_data()->setInt64( 781 kKeyTargetTime, targetSampleTimeUs); 782 } 783 784 *out = buffer; 785 786 return OK; 787 } 788 789 //////////////////////////////////////////////////////////////////////////////// 790 791 MatroskaExtractor::MatroskaExtractor(const sp<DataSource> &source) 792 : mDataSource(source), 793 mReader(new DataSourceReader(mDataSource)), 794 mSegment(NULL), 795 mExtractedThumbnails(false), 796 mIsWebm(false), 797 mSeekPreRollNs(0) { 798 off64_t size; 799 mIsLiveStreaming = 800 (mDataSource->flags() 801 & (DataSource::kWantsPrefetching 802 | DataSource::kIsCachingDataSource)) 803 && mDataSource->getSize(&size) != OK; 804 805 mkvparser::EBMLHeader ebmlHeader; 806 long long pos; 807 if (ebmlHeader.Parse(mReader, pos) < 0) { 808 return; 809 } 810 811 if (ebmlHeader.m_docType && !strcmp("webm", ebmlHeader.m_docType)) { 812 mIsWebm = true; 813 } 814 815 long long ret = 816 mkvparser::Segment::CreateInstance(mReader, pos, mSegment); 817 818 if (ret) { 819 CHECK(mSegment == NULL); 820 return; 821 } 822 823 // from mkvparser::Segment::Load(), but stop at first cluster 824 ret = mSegment->ParseHeaders(); 825 if (ret == 0) { 826 long len; 827 ret = mSegment->LoadCluster(pos, len); 828 if (ret >= 1) { 829 // no more clusters 830 ret = 0; 831 } 832 } else if (ret > 0) { 833 ret = mkvparser::E_BUFFER_NOT_FULL; 834 } 835 836 if (ret < 0) { 837 ALOGW("Corrupt %s source: %s", mIsWebm ? "webm" : "matroska", 838 uriDebugString(mDataSource->getUri()).c_str()); 839 delete mSegment; 840 mSegment = NULL; 841 return; 842 } 843 844 #if 0 845 const mkvparser::SegmentInfo *info = mSegment->GetInfo(); 846 ALOGI("muxing app: %s, writing app: %s", 847 info->GetMuxingAppAsUTF8(), 848 info->GetWritingAppAsUTF8()); 849 #endif 850 851 addTracks(); 852 } 853 854 MatroskaExtractor::~MatroskaExtractor() { 855 delete mSegment; 856 mSegment = NULL; 857 858 delete mReader; 859 mReader = NULL; 860 } 861 862 size_t MatroskaExtractor::countTracks() { 863 return mTracks.size(); 864 } 865 866 sp<IMediaSource> MatroskaExtractor::getTrack(size_t index) { 867 if (index >= mTracks.size()) { 868 return NULL; 869 } 870 871 return new MatroskaSource(this, index); 872 } 873 874 sp<MetaData> MatroskaExtractor::getTrackMetaData( 875 size_t index, uint32_t flags) { 876 if (index >= mTracks.size()) { 877 return NULL; 878 } 879 880 if ((flags & kIncludeExtensiveMetaData) && !mExtractedThumbnails 881 && !isLiveStreaming()) { 882 findThumbnails(); 883 mExtractedThumbnails = true; 884 } 885 886 return mTracks.itemAt(index).mMeta; 887 } 888 889 bool MatroskaExtractor::isLiveStreaming() const { 890 return mIsLiveStreaming; 891 } 892 893 static int bytesForSize(size_t size) { 894 // use at most 28 bits (4 times 7) 895 CHECK(size <= 0xfffffff); 896 897 if (size > 0x1fffff) { 898 return 4; 899 } else if (size > 0x3fff) { 900 return 3; 901 } else if (size > 0x7f) { 902 return 2; 903 } 904 return 1; 905 } 906 907 static void storeSize(uint8_t *data, size_t &idx, size_t size) { 908 int numBytes = bytesForSize(size); 909 idx += numBytes; 910 911 data += idx; 912 size_t next = 0; 913 while (numBytes--) { 914 *--data = (size & 0x7f) | next; 915 size >>= 7; 916 next = 0x80; 917 } 918 } 919 920 static void addESDSFromCodecPrivate( 921 const sp<MetaData> &meta, 922 bool isAudio, const void *priv, size_t privSize) { 923 924 int privSizeBytesRequired = bytesForSize(privSize); 925 int esdsSize2 = 14 + privSizeBytesRequired + privSize; 926 int esdsSize2BytesRequired = bytesForSize(esdsSize2); 927 int esdsSize1 = 4 + esdsSize2BytesRequired + esdsSize2; 928 int esdsSize1BytesRequired = bytesForSize(esdsSize1); 929 size_t esdsSize = 1 + esdsSize1BytesRequired + esdsSize1; 930 uint8_t *esds = new uint8_t[esdsSize]; 931 932 size_t idx = 0; 933 esds[idx++] = 0x03; 934 storeSize(esds, idx, esdsSize1); 935 esds[idx++] = 0x00; // ES_ID 936 esds[idx++] = 0x00; // ES_ID 937 esds[idx++] = 0x00; // streamDependenceFlag, URL_Flag, OCRstreamFlag 938 esds[idx++] = 0x04; 939 storeSize(esds, idx, esdsSize2); 940 esds[idx++] = isAudio ? 0x40 // Audio ISO/IEC 14496-3 941 : 0x20; // Visual ISO/IEC 14496-2 942 for (int i = 0; i < 12; i++) { 943 esds[idx++] = 0x00; 944 } 945 esds[idx++] = 0x05; 946 storeSize(esds, idx, privSize); 947 memcpy(esds + idx, priv, privSize); 948 949 meta->setData(kKeyESDS, 0, esds, esdsSize); 950 951 delete[] esds; 952 esds = NULL; 953 } 954 955 status_t addVorbisCodecInfo( 956 const sp<MetaData> &meta, 957 const void *_codecPrivate, size_t codecPrivateSize) { 958 // hexdump(_codecPrivate, codecPrivateSize); 959 960 if (codecPrivateSize < 1) { 961 return ERROR_MALFORMED; 962 } 963 964 const uint8_t *codecPrivate = (const uint8_t *)_codecPrivate; 965 966 if (codecPrivate[0] != 0x02) { 967 return ERROR_MALFORMED; 968 } 969 970 // codecInfo starts with two lengths, len1 and len2, that are 971 // "Xiph-style-lacing encoded"... 972 973 size_t offset = 1; 974 size_t len1 = 0; 975 while (offset < codecPrivateSize && codecPrivate[offset] == 0xff) { 976 if (len1 > (SIZE_MAX - 0xff)) { 977 return ERROR_MALFORMED; // would overflow 978 } 979 len1 += 0xff; 980 ++offset; 981 } 982 if (offset >= codecPrivateSize) { 983 return ERROR_MALFORMED; 984 } 985 if (len1 > (SIZE_MAX - codecPrivate[offset])) { 986 return ERROR_MALFORMED; // would overflow 987 } 988 len1 += codecPrivate[offset++]; 989 990 size_t len2 = 0; 991 while (offset < codecPrivateSize && codecPrivate[offset] == 0xff) { 992 if (len2 > (SIZE_MAX - 0xff)) { 993 return ERROR_MALFORMED; // would overflow 994 } 995 len2 += 0xff; 996 ++offset; 997 } 998 if (offset >= codecPrivateSize) { 999 return ERROR_MALFORMED; 1000 } 1001 if (len2 > (SIZE_MAX - codecPrivate[offset])) { 1002 return ERROR_MALFORMED; // would overflow 1003 } 1004 len2 += codecPrivate[offset++]; 1005 1006 if (len1 > SIZE_MAX - len2 || offset > SIZE_MAX - (len1 + len2) || 1007 codecPrivateSize < offset + len1 + len2) { 1008 return ERROR_MALFORMED; 1009 } 1010 1011 if (codecPrivate[offset] != 0x01) { 1012 return ERROR_MALFORMED; 1013 } 1014 meta->setData(kKeyVorbisInfo, 0, &codecPrivate[offset], len1); 1015 1016 offset += len1; 1017 if (codecPrivate[offset] != 0x03) { 1018 return ERROR_MALFORMED; 1019 } 1020 1021 offset += len2; 1022 if (codecPrivate[offset] != 0x05) { 1023 return ERROR_MALFORMED; 1024 } 1025 1026 meta->setData( 1027 kKeyVorbisBooks, 0, &codecPrivate[offset], 1028 codecPrivateSize - offset); 1029 1030 return OK; 1031 } 1032 1033 status_t MatroskaExtractor::synthesizeAVCC(TrackInfo *trackInfo, size_t index) { 1034 BlockIterator iter(this, trackInfo->mTrackNum, index); 1035 if (iter.eos()) { 1036 return ERROR_MALFORMED; 1037 } 1038 1039 const mkvparser::Block *block = iter.block(); 1040 if (block->GetFrameCount() <= 0) { 1041 return ERROR_MALFORMED; 1042 } 1043 1044 const mkvparser::Block::Frame &frame = block->GetFrame(0); 1045 sp<ABuffer> abuf = new ABuffer(frame.len); 1046 long n = frame.Read(mReader, abuf->data()); 1047 if (n != 0) { 1048 return ERROR_MALFORMED; 1049 } 1050 1051 sp<MetaData> avcMeta = MakeAVCCodecSpecificData(abuf); 1052 if (avcMeta == NULL) { 1053 return ERROR_MALFORMED; 1054 } 1055 1056 // Override the synthesized nal length size, which is arbitrary 1057 avcMeta->setInt32(kKeyNalLengthSize, 0); 1058 trackInfo->mMeta = avcMeta; 1059 return OK; 1060 } 1061 1062 static inline bool isValidInt32ColourValue(long long value) { 1063 return value != mkvparser::Colour::kValueNotPresent 1064 && value >= INT32_MIN 1065 && value <= INT32_MAX; 1066 } 1067 1068 static inline bool isValidUint16ColourValue(long long value) { 1069 return value != mkvparser::Colour::kValueNotPresent 1070 && value >= 0 1071 && value <= UINT16_MAX; 1072 } 1073 1074 static inline bool isValidPrimary(const mkvparser::PrimaryChromaticity *primary) { 1075 return primary != NULL && primary->x >= 0 && primary->x <= 1 1076 && primary->y >= 0 && primary->y <= 1; 1077 } 1078 1079 void MatroskaExtractor::getColorInformation( 1080 const mkvparser::VideoTrack *vtrack, sp<MetaData> &meta) { 1081 const mkvparser::Colour *color = vtrack->GetColour(); 1082 if (color == NULL) { 1083 return; 1084 } 1085 1086 // Color Aspects 1087 { 1088 int32_t primaries = 2; // ISO unspecified 1089 int32_t transfer = 2; // ISO unspecified 1090 int32_t coeffs = 2; // ISO unspecified 1091 bool fullRange = false; // default 1092 bool rangeSpecified = false; 1093 1094 if (isValidInt32ColourValue(color->primaries)) { 1095 primaries = color->primaries; 1096 } 1097 if (isValidInt32ColourValue(color->transfer_characteristics)) { 1098 transfer = color->transfer_characteristics; 1099 } 1100 if (isValidInt32ColourValue(color->matrix_coefficients)) { 1101 coeffs = color->matrix_coefficients; 1102 } 1103 if (color->range != mkvparser::Colour::kValueNotPresent 1104 && color->range != 0 /* MKV unspecified */) { 1105 // We only support MKV broadcast range (== limited) and full range. 1106 // We treat all other value as the default limited range. 1107 fullRange = color->range == 2 /* MKV fullRange */; 1108 rangeSpecified = true; 1109 } 1110 1111 ColorAspects aspects; 1112 ColorUtils::convertIsoColorAspectsToCodecAspects( 1113 primaries, transfer, coeffs, fullRange, aspects); 1114 meta->setInt32(kKeyColorPrimaries, aspects.mPrimaries); 1115 meta->setInt32(kKeyTransferFunction, aspects.mTransfer); 1116 meta->setInt32(kKeyColorMatrix, aspects.mMatrixCoeffs); 1117 meta->setInt32( 1118 kKeyColorRange, rangeSpecified ? aspects.mRange : ColorAspects::RangeUnspecified); 1119 } 1120 1121 // HDR Static Info 1122 { 1123 HDRStaticInfo info, nullInfo; // nullInfo is a fully unspecified static info 1124 memset(&info, 0, sizeof(info)); 1125 memset(&nullInfo, 0, sizeof(nullInfo)); 1126 if (isValidUint16ColourValue(color->max_cll)) { 1127 info.sType1.mMaxContentLightLevel = color->max_cll; 1128 } 1129 if (isValidUint16ColourValue(color->max_fall)) { 1130 info.sType1.mMaxFrameAverageLightLevel = color->max_fall; 1131 } 1132 const mkvparser::MasteringMetadata *mastering = color->mastering_metadata; 1133 if (mastering != NULL) { 1134 // Convert matroska values to HDRStaticInfo equivalent values for each fully specified 1135 // group. See CTA-681.3 section 3.2.1 for more info. 1136 if (mastering->luminance_max >= 0.5 && mastering->luminance_max < 65535.5) { 1137 info.sType1.mMaxDisplayLuminance = (uint16_t)(mastering->luminance_max + 0.5); 1138 } 1139 if (mastering->luminance_min >= 0.00005 && mastering->luminance_min < 6.55355) { 1140 // HDRStaticInfo Type1 stores min luminance scaled 10000:1 1141 info.sType1.mMinDisplayLuminance = 1142 (uint16_t)(10000 * mastering->luminance_min + 0.5); 1143 } 1144 // HDRStaticInfo Type1 stores primaries scaled 50000:1 1145 if (isValidPrimary(mastering->white_point)) { 1146 info.sType1.mW.x = (uint16_t)(50000 * mastering->white_point->x + 0.5); 1147 info.sType1.mW.y = (uint16_t)(50000 * mastering->white_point->y + 0.5); 1148 } 1149 if (isValidPrimary(mastering->r) && isValidPrimary(mastering->g) 1150 && isValidPrimary(mastering->b)) { 1151 info.sType1.mR.x = (uint16_t)(50000 * mastering->r->x + 0.5); 1152 info.sType1.mR.y = (uint16_t)(50000 * mastering->r->y + 0.5); 1153 info.sType1.mG.x = (uint16_t)(50000 * mastering->g->x + 0.5); 1154 info.sType1.mG.y = (uint16_t)(50000 * mastering->g->y + 0.5); 1155 info.sType1.mB.x = (uint16_t)(50000 * mastering->b->x + 0.5); 1156 info.sType1.mB.y = (uint16_t)(50000 * mastering->b->y + 0.5); 1157 } 1158 } 1159 // Only advertise static info if at least one of the groups have been specified. 1160 if (memcmp(&info, &nullInfo, sizeof(info)) != 0) { 1161 info.mID = HDRStaticInfo::kType1; 1162 meta->setData(kKeyHdrStaticInfo, 'hdrS', &info, sizeof(info)); 1163 } 1164 } 1165 } 1166 1167 void MatroskaExtractor::addTracks() { 1168 const mkvparser::Tracks *tracks = mSegment->GetTracks(); 1169 1170 for (size_t index = 0; index < tracks->GetTracksCount(); ++index) { 1171 const mkvparser::Track *track = tracks->GetTrackByIndex(index); 1172 1173 if (track == NULL) { 1174 // Apparently this is currently valid (if unexpected) behaviour 1175 // of the mkv parser lib. 1176 continue; 1177 } 1178 1179 const char *const codecID = track->GetCodecId(); 1180 ALOGV("codec id = %s", codecID); 1181 ALOGV("codec name = %s", track->GetCodecNameAsUTF8()); 1182 1183 if (codecID == NULL) { 1184 ALOGW("unknown codecID is not supported."); 1185 continue; 1186 } 1187 1188 size_t codecPrivateSize; 1189 const unsigned char *codecPrivate = 1190 track->GetCodecPrivate(codecPrivateSize); 1191 1192 enum { VIDEO_TRACK = 1, AUDIO_TRACK = 2 }; 1193 1194 sp<MetaData> meta = new MetaData; 1195 1196 status_t err = OK; 1197 1198 switch (track->GetType()) { 1199 case VIDEO_TRACK: 1200 { 1201 const mkvparser::VideoTrack *vtrack = 1202 static_cast<const mkvparser::VideoTrack *>(track); 1203 1204 if (!strcmp("V_MPEG4/ISO/AVC", codecID)) { 1205 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC); 1206 meta->setData(kKeyAVCC, 0, codecPrivate, codecPrivateSize); 1207 } else if (!strcmp("V_MPEG4/ISO/ASP", codecID)) { 1208 if (codecPrivateSize > 0) { 1209 meta->setCString( 1210 kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4); 1211 addESDSFromCodecPrivate( 1212 meta, false, codecPrivate, codecPrivateSize); 1213 } else { 1214 ALOGW("%s is detected, but does not have configuration.", 1215 codecID); 1216 continue; 1217 } 1218 } else if (!strcmp("V_VP8", codecID)) { 1219 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VP8); 1220 } else if (!strcmp("V_VP9", codecID)) { 1221 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VP9); 1222 if (codecPrivateSize > 0) { 1223 // 'csd-0' for VP9 is the Blob of Codec Private data as 1224 // specified in http://www.webmproject.org/vp9/profiles/. 1225 meta->setData( 1226 kKeyVp9CodecPrivate, 0, codecPrivate, 1227 codecPrivateSize); 1228 } 1229 } else { 1230 ALOGW("%s is not supported.", codecID); 1231 continue; 1232 } 1233 1234 meta->setInt32(kKeyWidth, vtrack->GetWidth()); 1235 meta->setInt32(kKeyHeight, vtrack->GetHeight()); 1236 1237 getColorInformation(vtrack, meta); 1238 1239 break; 1240 } 1241 1242 case AUDIO_TRACK: 1243 { 1244 const mkvparser::AudioTrack *atrack = 1245 static_cast<const mkvparser::AudioTrack *>(track); 1246 1247 if (!strcmp("A_AAC", codecID)) { 1248 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC); 1249 CHECK(codecPrivateSize >= 2); 1250 1251 addESDSFromCodecPrivate( 1252 meta, true, codecPrivate, codecPrivateSize); 1253 } else if (!strcmp("A_VORBIS", codecID)) { 1254 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS); 1255 1256 err = addVorbisCodecInfo( 1257 meta, codecPrivate, codecPrivateSize); 1258 } else if (!strcmp("A_OPUS", codecID)) { 1259 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_OPUS); 1260 meta->setData(kKeyOpusHeader, 0, codecPrivate, codecPrivateSize); 1261 meta->setInt64(kKeyOpusCodecDelay, track->GetCodecDelay()); 1262 meta->setInt64(kKeyOpusSeekPreRoll, track->GetSeekPreRoll()); 1263 mSeekPreRollNs = track->GetSeekPreRoll(); 1264 } else if (!strcmp("A_MPEG/L3", codecID)) { 1265 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG); 1266 } else { 1267 ALOGW("%s is not supported.", codecID); 1268 continue; 1269 } 1270 1271 meta->setInt32(kKeySampleRate, atrack->GetSamplingRate()); 1272 meta->setInt32(kKeyChannelCount, atrack->GetChannels()); 1273 break; 1274 } 1275 1276 default: 1277 continue; 1278 } 1279 1280 if (err != OK) { 1281 ALOGE("skipping track, codec specific data was malformed."); 1282 continue; 1283 } 1284 1285 long long durationNs = mSegment->GetDuration(); 1286 meta->setInt64(kKeyDuration, (durationNs + 500) / 1000); 1287 1288 mTracks.push(); 1289 size_t n = mTracks.size() - 1; 1290 TrackInfo *trackInfo = &mTracks.editItemAt(n); 1291 trackInfo->mTrackNum = track->GetNumber(); 1292 trackInfo->mMeta = meta; 1293 trackInfo->mExtractor = this; 1294 1295 trackInfo->mEncrypted = false; 1296 for(size_t i = 0; i < track->GetContentEncodingCount() && !trackInfo->mEncrypted; i++) { 1297 const mkvparser::ContentEncoding *encoding = track->GetContentEncodingByIndex(i); 1298 for(size_t j = 0; j < encoding->GetEncryptionCount(); j++) { 1299 const mkvparser::ContentEncoding::ContentEncryption *encryption; 1300 encryption = encoding->GetEncryptionByIndex(j); 1301 meta->setData(kKeyCryptoKey, 0, encryption->key_id, encryption->key_id_len); 1302 trackInfo->mEncrypted = true; 1303 break; 1304 } 1305 } 1306 1307 if (!strcmp("V_MPEG4/ISO/AVC", codecID) && codecPrivateSize == 0) { 1308 // Attempt to recover from AVC track without codec private data 1309 err = synthesizeAVCC(trackInfo, n); 1310 if (err != OK) { 1311 mTracks.pop(); 1312 } 1313 } 1314 } 1315 } 1316 1317 void MatroskaExtractor::findThumbnails() { 1318 for (size_t i = 0; i < mTracks.size(); ++i) { 1319 TrackInfo *info = &mTracks.editItemAt(i); 1320 1321 const char *mime; 1322 CHECK(info->mMeta->findCString(kKeyMIMEType, &mime)); 1323 1324 if (strncasecmp(mime, "video/", 6)) { 1325 continue; 1326 } 1327 1328 BlockIterator iter(this, info->mTrackNum, i); 1329 int32_t j = 0; 1330 int64_t thumbnailTimeUs = 0; 1331 size_t maxBlockSize = 0; 1332 while (!iter.eos() && j < 20) { 1333 if (iter.block()->IsKey()) { 1334 ++j; 1335 1336 size_t blockSize = 0; 1337 for (int k = 0; k < iter.block()->GetFrameCount(); ++k) { 1338 blockSize += iter.block()->GetFrame(k).len; 1339 } 1340 1341 if (blockSize > maxBlockSize) { 1342 maxBlockSize = blockSize; 1343 thumbnailTimeUs = iter.blockTimeUs(); 1344 } 1345 } 1346 iter.advance(); 1347 } 1348 info->mMeta->setInt64(kKeyThumbnailTime, thumbnailTimeUs); 1349 } 1350 } 1351 1352 sp<MetaData> MatroskaExtractor::getMetaData() { 1353 sp<MetaData> meta = new MetaData; 1354 1355 meta->setCString( 1356 kKeyMIMEType, 1357 mIsWebm ? "video/webm" : MEDIA_MIMETYPE_CONTAINER_MATROSKA); 1358 1359 return meta; 1360 } 1361 1362 uint32_t MatroskaExtractor::flags() const { 1363 uint32_t x = CAN_PAUSE; 1364 if (!isLiveStreaming()) { 1365 x |= CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK; 1366 } 1367 1368 return x; 1369 } 1370 1371 bool SniffMatroska( 1372 const sp<DataSource> &source, String8 *mimeType, float *confidence, 1373 sp<AMessage> *) { 1374 DataSourceReader reader(source); 1375 mkvparser::EBMLHeader ebmlHeader; 1376 long long pos; 1377 if (ebmlHeader.Parse(&reader, pos) < 0) { 1378 return false; 1379 } 1380 1381 mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_MATROSKA); 1382 *confidence = 0.6; 1383 1384 return true; 1385 } 1386 1387 } // namespace android 1388