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 40namespace android { 41 42struct DataSourceReader : public mkvparser::IMkvReader { 43 explicit 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 84private: 85 sp<DataSource> mSource; 86 87 DataSourceReader(const DataSourceReader &); 88 DataSourceReader &operator=(const DataSourceReader &); 89}; 90 91//////////////////////////////////////////////////////////////////////////////// 92 93struct 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 108private: 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 123struct 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 135protected: 136 virtual ~MatroskaSource(); 137 138private: 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 164const 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. 171const 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 211MatroskaSource::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 251MatroskaSource::~MatroskaSource() { 252 clearPendingFrames(); 253} 254 255status_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 265status_t MatroskaSource::stop() { 266 clearPendingFrames(); 267 268 return OK; 269} 270 271sp<MetaData> MatroskaSource::getFormat() { 272 return mExtractor->mTracks.itemAt(mTrackIndex).mMeta; 273} 274 275//////////////////////////////////////////////////////////////////////////////// 276 277BlockIterator::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 288bool BlockIterator::eos() const { 289 return mCluster == NULL || mCluster->EOS(); 290} 291 292void BlockIterator::advance() { 293 Mutex::Autolock autoLock(mExtractor->mLock); 294 advance_l(); 295} 296 297void 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 361void 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 373void BlockIterator::seek( 374 int64_t seekTimeUs, bool isAudio, 375 int64_t *actualFrameTimeUs) { 376 Mutex::Autolock autoLock(mExtractor->mLock); 377 378 *actualFrameTimeUs = -1ll; 379 380 if (seekTimeUs > INT64_MAX / 1000ll || 381 seekTimeUs < INT64_MIN / 1000ll || 382 (mExtractor->mSeekPreRollNs > 0 && 383 (seekTimeUs * 1000ll) < INT64_MIN + mExtractor->mSeekPreRollNs) || 384 (mExtractor->mSeekPreRollNs < 0 && 385 (seekTimeUs * 1000ll) > INT64_MAX + mExtractor->mSeekPreRollNs)) { 386 ALOGE("cannot seek to %lld", (long long) seekTimeUs); 387 return; 388 } 389 390 const int64_t seekTimeNs = seekTimeUs * 1000ll - mExtractor->mSeekPreRollNs; 391 392 mkvparser::Segment* const pSegment = mExtractor->mSegment; 393 394 // Special case the 0 seek to avoid loading Cues when the application 395 // extraneously seeks to 0 before playing. 396 if (seekTimeNs <= 0) { 397 ALOGV("Seek to beginning: %" PRId64, seekTimeUs); 398 mCluster = pSegment->GetFirst(); 399 mBlockEntryIndex = 0; 400 do { 401 advance_l(); 402 } while (!eos() && block()->GetTrackNumber() != mTrackNum); 403 return; 404 } 405 406 ALOGV("Seeking to: %" PRId64, seekTimeUs); 407 408 // If the Cues have not been located then find them. 409 const mkvparser::Cues* pCues = pSegment->GetCues(); 410 const mkvparser::SeekHead* pSH = pSegment->GetSeekHead(); 411 if (!pCues && pSH) { 412 const size_t count = pSH->GetCount(); 413 const mkvparser::SeekHead::Entry* pEntry; 414 ALOGV("No Cues yet"); 415 416 for (size_t index = 0; index < count; index++) { 417 pEntry = pSH->GetEntry(index); 418 419 if (pEntry->id == 0x0C53BB6B) { // Cues ID 420 long len; long long pos; 421 pSegment->ParseCues(pEntry->pos, pos, len); 422 pCues = pSegment->GetCues(); 423 ALOGV("Cues found"); 424 break; 425 } 426 } 427 428 if (!pCues) { 429 ALOGE("No Cues in file"); 430 return; 431 } 432 } 433 else if (!pSH) { 434 ALOGE("No SeekHead"); 435 return; 436 } 437 438 const mkvparser::CuePoint* pCP; 439 mkvparser::Tracks const *pTracks = pSegment->GetTracks(); 440 while (!pCues->DoneParsing()) { 441 pCues->LoadCuePoint(); 442 pCP = pCues->GetLast(); 443 CHECK(pCP); 444 445 size_t trackCount = mExtractor->mTracks.size(); 446 for (size_t index = 0; index < trackCount; ++index) { 447 MatroskaExtractor::TrackInfo& track = mExtractor->mTracks.editItemAt(index); 448 const mkvparser::Track *pTrack = pTracks->GetTrackByNumber(track.mTrackNum); 449 if (pTrack && pTrack->GetType() == 1 && pCP->Find(pTrack)) { // VIDEO_TRACK 450 track.mCuePoints.push_back(pCP); 451 } 452 } 453 454 if (pCP->GetTime(pSegment) >= seekTimeNs) { 455 ALOGV("Parsed past relevant Cue"); 456 break; 457 } 458 } 459 460 const mkvparser::CuePoint::TrackPosition *pTP = NULL; 461 const mkvparser::Track *thisTrack = pTracks->GetTrackByNumber(mTrackNum); 462 if (thisTrack->GetType() == 1) { // video 463 MatroskaExtractor::TrackInfo& track = mExtractor->mTracks.editItemAt(mIndex); 464 pTP = track.find(seekTimeNs); 465 } else { 466 // The Cue index is built around video keyframes 467 unsigned long int trackCount = pTracks->GetTracksCount(); 468 for (size_t index = 0; index < trackCount; ++index) { 469 const mkvparser::Track *pTrack = pTracks->GetTrackByIndex(index); 470 if (pTrack && pTrack->GetType() == 1 && pCues->Find(seekTimeNs, pTrack, pCP, pTP)) { 471 ALOGV("Video track located at %zu", index); 472 break; 473 } 474 } 475 } 476 477 478 // Always *search* based on the video track, but finalize based on mTrackNum 479 if (!pTP) { 480 ALOGE("Did not locate the video track for seeking"); 481 return; 482 } 483 484 mCluster = pSegment->FindOrPreloadCluster(pTP->m_pos); 485 486 CHECK(mCluster); 487 CHECK(!mCluster->EOS()); 488 489 // mBlockEntryIndex starts at 0 but m_block starts at 1 490 CHECK_GT(pTP->m_block, 0); 491 mBlockEntryIndex = pTP->m_block - 1; 492 493 for (;;) { 494 advance_l(); 495 496 if (eos()) break; 497 498 if (isAudio || block()->IsKey()) { 499 // Accept the first key frame 500 int64_t frameTimeUs = (block()->GetTime(mCluster) + 500LL) / 1000LL; 501 if (thisTrack->GetType() == 1 || frameTimeUs >= seekTimeUs) { 502 *actualFrameTimeUs = frameTimeUs; 503 ALOGV("Requested seek point: %" PRId64 " actual: %" PRId64, 504 seekTimeUs, *actualFrameTimeUs); 505 break; 506 } 507 } 508 } 509} 510 511const mkvparser::Block *BlockIterator::block() const { 512 CHECK(!eos()); 513 514 return mBlockEntry->GetBlock(); 515} 516 517int64_t BlockIterator::blockTimeUs() const { 518 if (mCluster == NULL || mBlockEntry == NULL) { 519 return -1; 520 } 521 return (mBlockEntry->GetBlock()->GetTime(mCluster) + 500ll) / 1000ll; 522} 523 524//////////////////////////////////////////////////////////////////////////////// 525 526static unsigned U24_AT(const uint8_t *ptr) { 527 return ptr[0] << 16 | ptr[1] << 8 | ptr[2]; 528} 529 530void MatroskaSource::clearPendingFrames() { 531 while (!mPendingFrames.empty()) { 532 MediaBuffer *frame = *mPendingFrames.begin(); 533 mPendingFrames.erase(mPendingFrames.begin()); 534 535 frame->release(); 536 frame = NULL; 537 } 538} 539 540status_t MatroskaSource::setWebmBlockCryptoInfo(MediaBuffer *mbuf) { 541 if (mbuf->range_length() < 1 || mbuf->range_length() - 1 > INT32_MAX) { 542 // 1-byte signal 543 return ERROR_MALFORMED; 544 } 545 546 const uint8_t *data = (const uint8_t *)mbuf->data() + mbuf->range_offset(); 547 bool blockEncrypted = data[0] & 0x1; 548 if (blockEncrypted && mbuf->range_length() < 9) { 549 // 1-byte signal + 8-byte IV 550 return ERROR_MALFORMED; 551 } 552 553 sp<MetaData> meta = mbuf->meta_data(); 554 if (blockEncrypted) { 555 /* 556 * 0 1 2 3 557 * 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 558 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 559 * | Signal Byte | | 560 * +-+-+-+-+-+-+-+-+ IV | 561 * | | 562 * | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 563 * | | | 564 * |-+-+-+-+-+-+-+-+ | 565 * : Bytes 1..N of encrypted frame : 566 * | | 567 * | | 568 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 569 */ 570 int32_t plainSizes[] = { 0 }; 571 int32_t encryptedSizes[] = { static_cast<int32_t>(mbuf->range_length() - 9) }; 572 uint8_t ctrCounter[16] = { 0 }; 573 uint32_t type; 574 const uint8_t *keyId; 575 size_t keyIdSize; 576 sp<MetaData> trackMeta = mExtractor->mTracks.itemAt(mTrackIndex).mMeta; 577 CHECK(trackMeta->findData(kKeyCryptoKey, &type, (const void **)&keyId, &keyIdSize)); 578 meta->setData(kKeyCryptoKey, 0, keyId, keyIdSize); 579 memcpy(ctrCounter, data + 1, 8); 580 meta->setData(kKeyCryptoIV, 0, ctrCounter, 16); 581 meta->setData(kKeyPlainSizes, 0, plainSizes, sizeof(plainSizes)); 582 meta->setData(kKeyEncryptedSizes, 0, encryptedSizes, sizeof(encryptedSizes)); 583 mbuf->set_range(9, mbuf->range_length() - 9); 584 } else { 585 /* 586 * 0 1 2 3 587 * 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 588 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 589 * | Signal Byte | | 590 * +-+-+-+-+-+-+-+-+ | 591 * : Bytes 1..N of unencrypted frame : 592 * | | 593 * | | 594 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 595 */ 596 int32_t plainSizes[] = { static_cast<int32_t>(mbuf->range_length() - 1) }; 597 int32_t encryptedSizes[] = { 0 }; 598 meta->setData(kKeyPlainSizes, 0, plainSizes, sizeof(plainSizes)); 599 meta->setData(kKeyEncryptedSizes, 0, encryptedSizes, sizeof(encryptedSizes)); 600 mbuf->set_range(1, mbuf->range_length() - 1); 601 } 602 603 return OK; 604} 605 606status_t MatroskaSource::readBlock() { 607 CHECK(mPendingFrames.empty()); 608 609 if (mBlockIter.eos()) { 610 return ERROR_END_OF_STREAM; 611 } 612 613 const mkvparser::Block *block = mBlockIter.block(); 614 615 int64_t timeUs = mBlockIter.blockTimeUs(); 616 617 for (int i = 0; i < block->GetFrameCount(); ++i) { 618 MatroskaExtractor::TrackInfo *trackInfo = &mExtractor->mTracks.editItemAt(mTrackIndex); 619 const mkvparser::Block::Frame &frame = block->GetFrame(i); 620 size_t len = frame.len; 621 if (SIZE_MAX - len < trackInfo->mHeaderLen) { 622 return ERROR_MALFORMED; 623 } 624 625 len += trackInfo->mHeaderLen; 626 MediaBuffer *mbuf = new MediaBuffer(len); 627 uint8_t *data = static_cast<uint8_t *>(mbuf->data()); 628 if (trackInfo->mHeader) { 629 memcpy(data, trackInfo->mHeader, trackInfo->mHeaderLen); 630 } 631 632 mbuf->meta_data()->setInt64(kKeyTime, timeUs); 633 mbuf->meta_data()->setInt32(kKeyIsSyncFrame, block->IsKey()); 634 635 status_t err = frame.Read(mExtractor->mReader, data + trackInfo->mHeaderLen); 636 if (err == OK 637 && mExtractor->mIsWebm 638 && trackInfo->mEncrypted) { 639 err = setWebmBlockCryptoInfo(mbuf); 640 } 641 642 if (err != OK) { 643 mPendingFrames.clear(); 644 645 mBlockIter.advance(); 646 mbuf->release(); 647 return err; 648 } 649 650 mPendingFrames.push_back(mbuf); 651 } 652 653 mBlockIter.advance(); 654 655 return OK; 656} 657 658status_t MatroskaSource::read( 659 MediaBuffer **out, const ReadOptions *options) { 660 *out = NULL; 661 662 int64_t targetSampleTimeUs = -1ll; 663 664 int64_t seekTimeUs; 665 ReadOptions::SeekMode mode; 666 if (options && options->getSeekTo(&seekTimeUs, &mode) 667 && !mExtractor->isLiveStreaming()) { 668 clearPendingFrames(); 669 670 // The audio we want is located by using the Cues to seek the video 671 // stream to find the target Cluster then iterating to finalize for 672 // audio. 673 int64_t actualFrameTimeUs; 674 mBlockIter.seek(seekTimeUs, mIsAudio, &actualFrameTimeUs); 675 676 if (mode == ReadOptions::SEEK_CLOSEST) { 677 targetSampleTimeUs = actualFrameTimeUs; 678 } 679 } 680 681 while (mPendingFrames.empty()) { 682 status_t err = readBlock(); 683 684 if (err != OK) { 685 clearPendingFrames(); 686 687 return err; 688 } 689 } 690 691 MediaBuffer *frame = *mPendingFrames.begin(); 692 mPendingFrames.erase(mPendingFrames.begin()); 693 694 if (mType != AVC || mNALSizeLen == 0) { 695 if (targetSampleTimeUs >= 0ll) { 696 frame->meta_data()->setInt64( 697 kKeyTargetTime, targetSampleTimeUs); 698 } 699 700 *out = frame; 701 702 return OK; 703 } 704 705 // Each input frame contains one or more NAL fragments, each fragment 706 // is prefixed by mNALSizeLen bytes giving the fragment length, 707 // followed by a corresponding number of bytes containing the fragment. 708 // We output all these fragments into a single large buffer separated 709 // by startcodes (0x00 0x00 0x00 0x01). 710 // 711 // When mNALSizeLen is 0, we assume the data is already in the format 712 // desired. 713 714 const uint8_t *srcPtr = 715 (const uint8_t *)frame->data() + frame->range_offset(); 716 717 size_t srcSize = frame->range_length(); 718 719 size_t dstSize = 0; 720 MediaBuffer *buffer = NULL; 721 uint8_t *dstPtr = NULL; 722 723 for (int32_t pass = 0; pass < 2; ++pass) { 724 size_t srcOffset = 0; 725 size_t dstOffset = 0; 726 while (srcOffset + mNALSizeLen <= srcSize) { 727 size_t NALsize; 728 switch (mNALSizeLen) { 729 case 1: NALsize = srcPtr[srcOffset]; break; 730 case 2: NALsize = U16_AT(srcPtr + srcOffset); break; 731 case 3: NALsize = U24_AT(srcPtr + srcOffset); break; 732 case 4: NALsize = U32_AT(srcPtr + srcOffset); break; 733 default: 734 TRESPASS(); 735 } 736 737 if (srcOffset + mNALSizeLen + NALsize <= srcOffset + mNALSizeLen) { 738 frame->release(); 739 frame = NULL; 740 741 return ERROR_MALFORMED; 742 } else if (srcOffset + mNALSizeLen + NALsize > srcSize) { 743 break; 744 } 745 746 if (pass == 1) { 747 memcpy(&dstPtr[dstOffset], "\x00\x00\x00\x01", 4); 748 749 if (frame != buffer) { 750 memcpy(&dstPtr[dstOffset + 4], 751 &srcPtr[srcOffset + mNALSizeLen], 752 NALsize); 753 } 754 } 755 756 dstOffset += 4; // 0x00 00 00 01 757 dstOffset += NALsize; 758 759 srcOffset += mNALSizeLen + NALsize; 760 } 761 762 if (srcOffset < srcSize) { 763 // There were trailing bytes or not enough data to complete 764 // a fragment. 765 766 frame->release(); 767 frame = NULL; 768 769 return ERROR_MALFORMED; 770 } 771 772 if (pass == 0) { 773 dstSize = dstOffset; 774 775 if (dstSize == srcSize && mNALSizeLen == 4) { 776 // In this special case we can re-use the input buffer by substituting 777 // each 4-byte nal size with a 4-byte start code 778 buffer = frame; 779 } else { 780 buffer = new MediaBuffer(dstSize); 781 } 782 783 int64_t timeUs; 784 CHECK(frame->meta_data()->findInt64(kKeyTime, &timeUs)); 785 int32_t isSync; 786 CHECK(frame->meta_data()->findInt32(kKeyIsSyncFrame, &isSync)); 787 788 buffer->meta_data()->setInt64(kKeyTime, timeUs); 789 buffer->meta_data()->setInt32(kKeyIsSyncFrame, isSync); 790 791 dstPtr = (uint8_t *)buffer->data(); 792 } 793 } 794 795 if (frame != buffer) { 796 frame->release(); 797 frame = NULL; 798 } 799 800 if (targetSampleTimeUs >= 0ll) { 801 buffer->meta_data()->setInt64( 802 kKeyTargetTime, targetSampleTimeUs); 803 } 804 805 *out = buffer; 806 807 return OK; 808} 809 810//////////////////////////////////////////////////////////////////////////////// 811 812MatroskaExtractor::MatroskaExtractor(const sp<DataSource> &source) 813 : mDataSource(source), 814 mReader(new DataSourceReader(mDataSource)), 815 mSegment(NULL), 816 mExtractedThumbnails(false), 817 mIsWebm(false), 818 mSeekPreRollNs(0) { 819 off64_t size; 820 mIsLiveStreaming = 821 (mDataSource->flags() 822 & (DataSource::kWantsPrefetching 823 | DataSource::kIsCachingDataSource)) 824 && mDataSource->getSize(&size) != OK; 825 826 mkvparser::EBMLHeader ebmlHeader; 827 long long pos; 828 if (ebmlHeader.Parse(mReader, pos) < 0) { 829 return; 830 } 831 832 if (ebmlHeader.m_docType && !strcmp("webm", ebmlHeader.m_docType)) { 833 mIsWebm = true; 834 } 835 836 long long ret = 837 mkvparser::Segment::CreateInstance(mReader, pos, mSegment); 838 839 if (ret) { 840 CHECK(mSegment == NULL); 841 return; 842 } 843 844 // from mkvparser::Segment::Load(), but stop at first cluster 845 ret = mSegment->ParseHeaders(); 846 if (ret == 0) { 847 long len; 848 ret = mSegment->LoadCluster(pos, len); 849 if (ret >= 1) { 850 // no more clusters 851 ret = 0; 852 } 853 } else if (ret > 0) { 854 ret = mkvparser::E_BUFFER_NOT_FULL; 855 } 856 857 if (ret < 0) { 858 ALOGW("Corrupt %s source: %s", mIsWebm ? "webm" : "matroska", 859 uriDebugString(mDataSource->getUri()).c_str()); 860 delete mSegment; 861 mSegment = NULL; 862 return; 863 } 864 865#if 0 866 const mkvparser::SegmentInfo *info = mSegment->GetInfo(); 867 ALOGI("muxing app: %s, writing app: %s", 868 info->GetMuxingAppAsUTF8(), 869 info->GetWritingAppAsUTF8()); 870#endif 871 872 addTracks(); 873} 874 875MatroskaExtractor::~MatroskaExtractor() { 876 delete mSegment; 877 mSegment = NULL; 878 879 delete mReader; 880 mReader = NULL; 881} 882 883size_t MatroskaExtractor::countTracks() { 884 return mTracks.size(); 885} 886 887sp<IMediaSource> MatroskaExtractor::getTrack(size_t index) { 888 if (index >= mTracks.size()) { 889 return NULL; 890 } 891 892 return new MatroskaSource(this, index); 893} 894 895sp<MetaData> MatroskaExtractor::getTrackMetaData( 896 size_t index, uint32_t flags) { 897 if (index >= mTracks.size()) { 898 return NULL; 899 } 900 901 if ((flags & kIncludeExtensiveMetaData) && !mExtractedThumbnails 902 && !isLiveStreaming()) { 903 findThumbnails(); 904 mExtractedThumbnails = true; 905 } 906 907 return mTracks.itemAt(index).mMeta; 908} 909 910bool MatroskaExtractor::isLiveStreaming() const { 911 return mIsLiveStreaming; 912} 913 914static int bytesForSize(size_t size) { 915 // use at most 28 bits (4 times 7) 916 CHECK(size <= 0xfffffff); 917 918 if (size > 0x1fffff) { 919 return 4; 920 } else if (size > 0x3fff) { 921 return 3; 922 } else if (size > 0x7f) { 923 return 2; 924 } 925 return 1; 926} 927 928static void storeSize(uint8_t *data, size_t &idx, size_t size) { 929 int numBytes = bytesForSize(size); 930 idx += numBytes; 931 932 data += idx; 933 size_t next = 0; 934 while (numBytes--) { 935 *--data = (size & 0x7f) | next; 936 size >>= 7; 937 next = 0x80; 938 } 939} 940 941static void addESDSFromCodecPrivate( 942 const sp<MetaData> &meta, 943 bool isAudio, const void *priv, size_t privSize) { 944 945 int privSizeBytesRequired = bytesForSize(privSize); 946 int esdsSize2 = 14 + privSizeBytesRequired + privSize; 947 int esdsSize2BytesRequired = bytesForSize(esdsSize2); 948 int esdsSize1 = 4 + esdsSize2BytesRequired + esdsSize2; 949 int esdsSize1BytesRequired = bytesForSize(esdsSize1); 950 size_t esdsSize = 1 + esdsSize1BytesRequired + esdsSize1; 951 uint8_t *esds = new uint8_t[esdsSize]; 952 953 size_t idx = 0; 954 esds[idx++] = 0x03; 955 storeSize(esds, idx, esdsSize1); 956 esds[idx++] = 0x00; // ES_ID 957 esds[idx++] = 0x00; // ES_ID 958 esds[idx++] = 0x00; // streamDependenceFlag, URL_Flag, OCRstreamFlag 959 esds[idx++] = 0x04; 960 storeSize(esds, idx, esdsSize2); 961 esds[idx++] = isAudio ? 0x40 // Audio ISO/IEC 14496-3 962 : 0x20; // Visual ISO/IEC 14496-2 963 for (int i = 0; i < 12; i++) { 964 esds[idx++] = 0x00; 965 } 966 esds[idx++] = 0x05; 967 storeSize(esds, idx, privSize); 968 memcpy(esds + idx, priv, privSize); 969 970 meta->setData(kKeyESDS, 0, esds, esdsSize); 971 972 delete[] esds; 973 esds = NULL; 974} 975 976status_t addVorbisCodecInfo( 977 const sp<MetaData> &meta, 978 const void *_codecPrivate, size_t codecPrivateSize) { 979 // hexdump(_codecPrivate, codecPrivateSize); 980 981 if (codecPrivateSize < 1) { 982 return ERROR_MALFORMED; 983 } 984 985 const uint8_t *codecPrivate = (const uint8_t *)_codecPrivate; 986 987 if (codecPrivate[0] != 0x02) { 988 return ERROR_MALFORMED; 989 } 990 991 // codecInfo starts with two lengths, len1 and len2, that are 992 // "Xiph-style-lacing encoded"... 993 994 size_t offset = 1; 995 size_t len1 = 0; 996 while (offset < codecPrivateSize && codecPrivate[offset] == 0xff) { 997 if (len1 > (SIZE_MAX - 0xff)) { 998 return ERROR_MALFORMED; // would overflow 999 } 1000 len1 += 0xff; 1001 ++offset; 1002 } 1003 if (offset >= codecPrivateSize) { 1004 return ERROR_MALFORMED; 1005 } 1006 if (len1 > (SIZE_MAX - codecPrivate[offset])) { 1007 return ERROR_MALFORMED; // would overflow 1008 } 1009 len1 += codecPrivate[offset++]; 1010 1011 size_t len2 = 0; 1012 while (offset < codecPrivateSize && codecPrivate[offset] == 0xff) { 1013 if (len2 > (SIZE_MAX - 0xff)) { 1014 return ERROR_MALFORMED; // would overflow 1015 } 1016 len2 += 0xff; 1017 ++offset; 1018 } 1019 if (offset >= codecPrivateSize) { 1020 return ERROR_MALFORMED; 1021 } 1022 if (len2 > (SIZE_MAX - codecPrivate[offset])) { 1023 return ERROR_MALFORMED; // would overflow 1024 } 1025 len2 += codecPrivate[offset++]; 1026 1027 if (len1 > SIZE_MAX - len2 || offset > SIZE_MAX - (len1 + len2) || 1028 codecPrivateSize < offset + len1 + len2) { 1029 return ERROR_MALFORMED; 1030 } 1031 1032 if (codecPrivate[offset] != 0x01) { 1033 return ERROR_MALFORMED; 1034 } 1035 meta->setData(kKeyVorbisInfo, 0, &codecPrivate[offset], len1); 1036 1037 offset += len1; 1038 if (codecPrivate[offset] != 0x03) { 1039 return ERROR_MALFORMED; 1040 } 1041 1042 offset += len2; 1043 if (codecPrivate[offset] != 0x05) { 1044 return ERROR_MALFORMED; 1045 } 1046 1047 meta->setData( 1048 kKeyVorbisBooks, 0, &codecPrivate[offset], 1049 codecPrivateSize - offset); 1050 1051 return OK; 1052} 1053 1054status_t MatroskaExtractor::synthesizeAVCC(TrackInfo *trackInfo, size_t index) { 1055 BlockIterator iter(this, trackInfo->mTrackNum, index); 1056 if (iter.eos()) { 1057 return ERROR_MALFORMED; 1058 } 1059 1060 const mkvparser::Block *block = iter.block(); 1061 if (block->GetFrameCount() <= 0) { 1062 return ERROR_MALFORMED; 1063 } 1064 1065 const mkvparser::Block::Frame &frame = block->GetFrame(0); 1066 sp<ABuffer> abuf = new ABuffer(frame.len); 1067 long n = frame.Read(mReader, abuf->data()); 1068 if (n != 0) { 1069 return ERROR_MALFORMED; 1070 } 1071 1072 sp<MetaData> avcMeta = MakeAVCCodecSpecificData(abuf); 1073 if (avcMeta == NULL) { 1074 return ERROR_MALFORMED; 1075 } 1076 1077 // Override the synthesized nal length size, which is arbitrary 1078 avcMeta->setInt32(kKeyNalLengthSize, 0); 1079 trackInfo->mMeta = avcMeta; 1080 return OK; 1081} 1082 1083static inline bool isValidInt32ColourValue(long long value) { 1084 return value != mkvparser::Colour::kValueNotPresent 1085 && value >= INT32_MIN 1086 && value <= INT32_MAX; 1087} 1088 1089static inline bool isValidUint16ColourValue(long long value) { 1090 return value != mkvparser::Colour::kValueNotPresent 1091 && value >= 0 1092 && value <= UINT16_MAX; 1093} 1094 1095static inline bool isValidPrimary(const mkvparser::PrimaryChromaticity *primary) { 1096 return primary != NULL && primary->x >= 0 && primary->x <= 1 1097 && primary->y >= 0 && primary->y <= 1; 1098} 1099 1100void MatroskaExtractor::getColorInformation( 1101 const mkvparser::VideoTrack *vtrack, sp<MetaData> &meta) { 1102 const mkvparser::Colour *color = vtrack->GetColour(); 1103 if (color == NULL) { 1104 return; 1105 } 1106 1107 // Color Aspects 1108 { 1109 int32_t primaries = 2; // ISO unspecified 1110 int32_t transfer = 2; // ISO unspecified 1111 int32_t coeffs = 2; // ISO unspecified 1112 bool fullRange = false; // default 1113 bool rangeSpecified = false; 1114 1115 if (isValidInt32ColourValue(color->primaries)) { 1116 primaries = color->primaries; 1117 } 1118 if (isValidInt32ColourValue(color->transfer_characteristics)) { 1119 transfer = color->transfer_characteristics; 1120 } 1121 if (isValidInt32ColourValue(color->matrix_coefficients)) { 1122 coeffs = color->matrix_coefficients; 1123 } 1124 if (color->range != mkvparser::Colour::kValueNotPresent 1125 && color->range != 0 /* MKV unspecified */) { 1126 // We only support MKV broadcast range (== limited) and full range. 1127 // We treat all other value as the default limited range. 1128 fullRange = color->range == 2 /* MKV fullRange */; 1129 rangeSpecified = true; 1130 } 1131 1132 ColorAspects aspects; 1133 ColorUtils::convertIsoColorAspectsToCodecAspects( 1134 primaries, transfer, coeffs, fullRange, aspects); 1135 meta->setInt32(kKeyColorPrimaries, aspects.mPrimaries); 1136 meta->setInt32(kKeyTransferFunction, aspects.mTransfer); 1137 meta->setInt32(kKeyColorMatrix, aspects.mMatrixCoeffs); 1138 meta->setInt32( 1139 kKeyColorRange, rangeSpecified ? aspects.mRange : ColorAspects::RangeUnspecified); 1140 } 1141 1142 // HDR Static Info 1143 { 1144 HDRStaticInfo info, nullInfo; // nullInfo is a fully unspecified static info 1145 memset(&info, 0, sizeof(info)); 1146 memset(&nullInfo, 0, sizeof(nullInfo)); 1147 if (isValidUint16ColourValue(color->max_cll)) { 1148 info.sType1.mMaxContentLightLevel = color->max_cll; 1149 } 1150 if (isValidUint16ColourValue(color->max_fall)) { 1151 info.sType1.mMaxFrameAverageLightLevel = color->max_fall; 1152 } 1153 const mkvparser::MasteringMetadata *mastering = color->mastering_metadata; 1154 if (mastering != NULL) { 1155 // Convert matroska values to HDRStaticInfo equivalent values for each fully specified 1156 // group. See CTA-681.3 section 3.2.1 for more info. 1157 if (mastering->luminance_max >= 0.5 && mastering->luminance_max < 65535.5) { 1158 info.sType1.mMaxDisplayLuminance = (uint16_t)(mastering->luminance_max + 0.5); 1159 } 1160 if (mastering->luminance_min >= 0.00005 && mastering->luminance_min < 6.55355) { 1161 // HDRStaticInfo Type1 stores min luminance scaled 10000:1 1162 info.sType1.mMinDisplayLuminance = 1163 (uint16_t)(10000 * mastering->luminance_min + 0.5); 1164 } 1165 // HDRStaticInfo Type1 stores primaries scaled 50000:1 1166 if (isValidPrimary(mastering->white_point)) { 1167 info.sType1.mW.x = (uint16_t)(50000 * mastering->white_point->x + 0.5); 1168 info.sType1.mW.y = (uint16_t)(50000 * mastering->white_point->y + 0.5); 1169 } 1170 if (isValidPrimary(mastering->r) && isValidPrimary(mastering->g) 1171 && isValidPrimary(mastering->b)) { 1172 info.sType1.mR.x = (uint16_t)(50000 * mastering->r->x + 0.5); 1173 info.sType1.mR.y = (uint16_t)(50000 * mastering->r->y + 0.5); 1174 info.sType1.mG.x = (uint16_t)(50000 * mastering->g->x + 0.5); 1175 info.sType1.mG.y = (uint16_t)(50000 * mastering->g->y + 0.5); 1176 info.sType1.mB.x = (uint16_t)(50000 * mastering->b->x + 0.5); 1177 info.sType1.mB.y = (uint16_t)(50000 * mastering->b->y + 0.5); 1178 } 1179 } 1180 // Only advertise static info if at least one of the groups have been specified. 1181 if (memcmp(&info, &nullInfo, sizeof(info)) != 0) { 1182 info.mID = HDRStaticInfo::kType1; 1183 meta->setData(kKeyHdrStaticInfo, 'hdrS', &info, sizeof(info)); 1184 } 1185 } 1186} 1187 1188status_t MatroskaExtractor::initTrackInfo( 1189 const mkvparser::Track *track, const sp<MetaData> &meta, TrackInfo *trackInfo) { 1190 trackInfo->mTrackNum = track->GetNumber(); 1191 trackInfo->mMeta = meta; 1192 trackInfo->mExtractor = this; 1193 trackInfo->mEncrypted = false; 1194 trackInfo->mHeader = NULL; 1195 trackInfo->mHeaderLen = 0; 1196 1197 for(size_t i = 0; i < track->GetContentEncodingCount(); i++) { 1198 const mkvparser::ContentEncoding *encoding = track->GetContentEncodingByIndex(i); 1199 for(size_t j = 0; j < encoding->GetEncryptionCount(); j++) { 1200 const mkvparser::ContentEncoding::ContentEncryption *encryption; 1201 encryption = encoding->GetEncryptionByIndex(j); 1202 trackInfo->mMeta->setData(kKeyCryptoKey, 0, encryption->key_id, encryption->key_id_len); 1203 trackInfo->mEncrypted = true; 1204 break; 1205 } 1206 1207 for(size_t j = 0; j < encoding->GetCompressionCount(); j++) { 1208 const mkvparser::ContentEncoding::ContentCompression *compression; 1209 compression = encoding->GetCompressionByIndex(j); 1210 ALOGV("compression algo %llu settings_len %lld", 1211 compression->algo, compression->settings_len); 1212 if (compression->algo == 3 1213 && compression->settings 1214 && compression->settings_len > 0) { 1215 trackInfo->mHeader = compression->settings; 1216 trackInfo->mHeaderLen = compression->settings_len; 1217 } 1218 } 1219 } 1220 1221 return OK; 1222} 1223 1224void MatroskaExtractor::addTracks() { 1225 const mkvparser::Tracks *tracks = mSegment->GetTracks(); 1226 1227 for (size_t index = 0; index < tracks->GetTracksCount(); ++index) { 1228 const mkvparser::Track *track = tracks->GetTrackByIndex(index); 1229 1230 if (track == NULL) { 1231 // Apparently this is currently valid (if unexpected) behaviour 1232 // of the mkv parser lib. 1233 continue; 1234 } 1235 1236 const char *const codecID = track->GetCodecId(); 1237 ALOGV("codec id = %s", codecID); 1238 ALOGV("codec name = %s", track->GetCodecNameAsUTF8()); 1239 1240 if (codecID == NULL) { 1241 ALOGW("unknown codecID is not supported."); 1242 continue; 1243 } 1244 1245 size_t codecPrivateSize; 1246 const unsigned char *codecPrivate = 1247 track->GetCodecPrivate(codecPrivateSize); 1248 1249 enum { VIDEO_TRACK = 1, AUDIO_TRACK = 2 }; 1250 1251 sp<MetaData> meta = new MetaData; 1252 1253 status_t err = OK; 1254 1255 switch (track->GetType()) { 1256 case VIDEO_TRACK: 1257 { 1258 const mkvparser::VideoTrack *vtrack = 1259 static_cast<const mkvparser::VideoTrack *>(track); 1260 1261 if (!strcmp("V_MPEG4/ISO/AVC", codecID)) { 1262 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC); 1263 meta->setData(kKeyAVCC, 0, codecPrivate, codecPrivateSize); 1264 } else if (!strcmp("V_MPEG4/ISO/ASP", codecID)) { 1265 if (codecPrivateSize > 0) { 1266 meta->setCString( 1267 kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4); 1268 addESDSFromCodecPrivate( 1269 meta, false, codecPrivate, codecPrivateSize); 1270 } else { 1271 ALOGW("%s is detected, but does not have configuration.", 1272 codecID); 1273 continue; 1274 } 1275 } else if (!strcmp("V_VP8", codecID)) { 1276 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VP8); 1277 } else if (!strcmp("V_VP9", codecID)) { 1278 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VP9); 1279 if (codecPrivateSize > 0) { 1280 // 'csd-0' for VP9 is the Blob of Codec Private data as 1281 // specified in http://www.webmproject.org/vp9/profiles/. 1282 meta->setData( 1283 kKeyVp9CodecPrivate, 0, codecPrivate, 1284 codecPrivateSize); 1285 } 1286 } else { 1287 ALOGW("%s is not supported.", codecID); 1288 continue; 1289 } 1290 1291 const long long width = vtrack->GetWidth(); 1292 const long long height = vtrack->GetHeight(); 1293 if (width <= 0 || width > INT32_MAX) { 1294 ALOGW("track width exceeds int32_t, %lld", width); 1295 continue; 1296 } 1297 if (height <= 0 || height > INT32_MAX) { 1298 ALOGW("track height exceeds int32_t, %lld", height); 1299 continue; 1300 } 1301 meta->setInt32(kKeyWidth, (int32_t)width); 1302 meta->setInt32(kKeyHeight, (int32_t)height); 1303 1304 // setting display width/height is optional 1305 const long long displayUnit = vtrack->GetDisplayUnit(); 1306 const long long displayWidth = vtrack->GetDisplayWidth(); 1307 const long long displayHeight = vtrack->GetDisplayHeight(); 1308 if (displayWidth > 0 && displayWidth <= INT32_MAX 1309 && displayHeight > 0 && displayHeight <= INT32_MAX) { 1310 switch (displayUnit) { 1311 case 0: // pixels 1312 meta->setInt32(kKeyDisplayWidth, (int32_t)displayWidth); 1313 meta->setInt32(kKeyDisplayHeight, (int32_t)displayHeight); 1314 break; 1315 case 1: // centimeters 1316 case 2: // inches 1317 case 3: // aspect ratio 1318 { 1319 // Physical layout size is treated the same as aspect ratio. 1320 // Note: displayWidth and displayHeight are never zero as they are 1321 // checked in the if above. 1322 const long long computedWidth = 1323 std::max(width, height * displayWidth / displayHeight); 1324 const long long computedHeight = 1325 std::max(height, width * displayHeight / displayWidth); 1326 if (computedWidth <= INT32_MAX && computedHeight <= INT32_MAX) { 1327 meta->setInt32(kKeyDisplayWidth, (int32_t)computedWidth); 1328 meta->setInt32(kKeyDisplayHeight, (int32_t)computedHeight); 1329 } 1330 break; 1331 } 1332 default: // unknown display units, perhaps future version of spec. 1333 break; 1334 } 1335 } 1336 1337 getColorInformation(vtrack, meta); 1338 1339 break; 1340 } 1341 1342 case AUDIO_TRACK: 1343 { 1344 const mkvparser::AudioTrack *atrack = 1345 static_cast<const mkvparser::AudioTrack *>(track); 1346 1347 if (!strcmp("A_AAC", codecID)) { 1348 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC); 1349 CHECK(codecPrivateSize >= 2); 1350 1351 addESDSFromCodecPrivate( 1352 meta, true, codecPrivate, codecPrivateSize); 1353 } else if (!strcmp("A_VORBIS", codecID)) { 1354 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS); 1355 1356 err = addVorbisCodecInfo( 1357 meta, codecPrivate, codecPrivateSize); 1358 } else if (!strcmp("A_OPUS", codecID)) { 1359 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_OPUS); 1360 meta->setData(kKeyOpusHeader, 0, codecPrivate, codecPrivateSize); 1361 meta->setInt64(kKeyOpusCodecDelay, track->GetCodecDelay()); 1362 meta->setInt64(kKeyOpusSeekPreRoll, track->GetSeekPreRoll()); 1363 mSeekPreRollNs = track->GetSeekPreRoll(); 1364 } else if (!strcmp("A_MPEG/L3", codecID)) { 1365 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG); 1366 } else { 1367 ALOGW("%s is not supported.", codecID); 1368 continue; 1369 } 1370 1371 meta->setInt32(kKeySampleRate, atrack->GetSamplingRate()); 1372 meta->setInt32(kKeyChannelCount, atrack->GetChannels()); 1373 break; 1374 } 1375 1376 default: 1377 continue; 1378 } 1379 1380 if (err != OK) { 1381 ALOGE("skipping track, codec specific data was malformed."); 1382 continue; 1383 } 1384 1385 long long durationNs = mSegment->GetDuration(); 1386 meta->setInt64(kKeyDuration, (durationNs + 500) / 1000); 1387 1388 mTracks.push(); 1389 size_t n = mTracks.size() - 1; 1390 TrackInfo *trackInfo = &mTracks.editItemAt(n); 1391 initTrackInfo(track, meta, trackInfo); 1392 1393 if (!strcmp("V_MPEG4/ISO/AVC", codecID) && codecPrivateSize == 0) { 1394 // Attempt to recover from AVC track without codec private data 1395 err = synthesizeAVCC(trackInfo, n); 1396 if (err != OK) { 1397 mTracks.pop(); 1398 } 1399 } 1400 } 1401} 1402 1403void MatroskaExtractor::findThumbnails() { 1404 for (size_t i = 0; i < mTracks.size(); ++i) { 1405 TrackInfo *info = &mTracks.editItemAt(i); 1406 1407 const char *mime; 1408 CHECK(info->mMeta->findCString(kKeyMIMEType, &mime)); 1409 1410 if (strncasecmp(mime, "video/", 6)) { 1411 continue; 1412 } 1413 1414 BlockIterator iter(this, info->mTrackNum, i); 1415 int32_t j = 0; 1416 int64_t thumbnailTimeUs = 0; 1417 size_t maxBlockSize = 0; 1418 while (!iter.eos() && j < 20) { 1419 if (iter.block()->IsKey()) { 1420 ++j; 1421 1422 size_t blockSize = 0; 1423 for (int k = 0; k < iter.block()->GetFrameCount(); ++k) { 1424 blockSize += iter.block()->GetFrame(k).len; 1425 } 1426 1427 if (blockSize > maxBlockSize) { 1428 maxBlockSize = blockSize; 1429 thumbnailTimeUs = iter.blockTimeUs(); 1430 } 1431 } 1432 iter.advance(); 1433 } 1434 info->mMeta->setInt64(kKeyThumbnailTime, thumbnailTimeUs); 1435 } 1436} 1437 1438sp<MetaData> MatroskaExtractor::getMetaData() { 1439 sp<MetaData> meta = new MetaData; 1440 1441 meta->setCString( 1442 kKeyMIMEType, 1443 mIsWebm ? "video/webm" : MEDIA_MIMETYPE_CONTAINER_MATROSKA); 1444 1445 return meta; 1446} 1447 1448uint32_t MatroskaExtractor::flags() const { 1449 uint32_t x = CAN_PAUSE; 1450 if (!isLiveStreaming()) { 1451 x |= CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK; 1452 } 1453 1454 return x; 1455} 1456 1457bool SniffMatroska( 1458 const sp<DataSource> &source, String8 *mimeType, float *confidence, 1459 sp<AMessage> *) { 1460 DataSourceReader reader(source); 1461 mkvparser::EBMLHeader ebmlHeader; 1462 long long pos; 1463 if (ebmlHeader.Parse(&reader, pos) < 0) { 1464 return false; 1465 } 1466 1467 mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_MATROSKA); 1468 *confidence = 0.6; 1469 1470 return true; 1471} 1472 1473} // namespace android 1474