1 /* 2 * Copyright (C) 2011 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 "AVIExtractor" 19 #include <utils/Log.h> 20 21 #include "include/avc_utils.h" 22 #include "include/AVIExtractor.h" 23 24 #include <binder/ProcessState.h> 25 #include <media/stagefright/foundation/hexdump.h> 26 #include <media/stagefright/foundation/ABuffer.h> 27 #include <media/stagefright/foundation/ADebug.h> 28 #include <media/stagefright/DataSource.h> 29 #include <media/stagefright/MediaBuffer.h> 30 #include <media/stagefright/MediaBufferGroup.h> 31 #include <media/stagefright/MediaDefs.h> 32 #include <media/stagefright/MediaErrors.h> 33 #include <media/stagefright/MetaData.h> 34 #include <media/stagefright/Utils.h> 35 36 namespace android { 37 38 struct AVIExtractor::AVISource : public MediaSource { 39 AVISource(const sp<AVIExtractor> &extractor, size_t trackIndex); 40 41 virtual status_t start(MetaData *params); 42 virtual status_t stop(); 43 44 virtual sp<MetaData> getFormat(); 45 46 virtual status_t read( 47 MediaBuffer **buffer, const ReadOptions *options); 48 49 protected: 50 virtual ~AVISource(); 51 52 private: 53 sp<AVIExtractor> mExtractor; 54 size_t mTrackIndex; 55 const AVIExtractor::Track &mTrack; 56 MediaBufferGroup *mBufferGroup; 57 size_t mSampleIndex; 58 59 sp<MP3Splitter> mSplitter; 60 61 DISALLOW_EVIL_CONSTRUCTORS(AVISource); 62 }; 63 64 //////////////////////////////////////////////////////////////////////////////// 65 66 struct AVIExtractor::MP3Splitter : public RefBase { 67 MP3Splitter(); 68 69 void clear(); 70 void append(MediaBuffer *buffer); 71 status_t read(MediaBuffer **buffer); 72 73 protected: 74 virtual ~MP3Splitter(); 75 76 private: 77 bool mFindSync; 78 int64_t mBaseTimeUs; 79 int64_t mNumSamplesRead; 80 sp<ABuffer> mBuffer; 81 82 bool resync(); 83 84 DISALLOW_EVIL_CONSTRUCTORS(MP3Splitter); 85 }; 86 87 //////////////////////////////////////////////////////////////////////////////// 88 89 AVIExtractor::AVISource::AVISource( 90 const sp<AVIExtractor> &extractor, size_t trackIndex) 91 : mExtractor(extractor), 92 mTrackIndex(trackIndex), 93 mTrack(mExtractor->mTracks.itemAt(trackIndex)), 94 mBufferGroup(NULL) { 95 } 96 97 AVIExtractor::AVISource::~AVISource() { 98 if (mBufferGroup) { 99 stop(); 100 } 101 } 102 103 status_t AVIExtractor::AVISource::start(MetaData *params) { 104 CHECK(!mBufferGroup); 105 106 mBufferGroup = new MediaBufferGroup; 107 108 mBufferGroup->add_buffer(new MediaBuffer(mTrack.mMaxSampleSize)); 109 mBufferGroup->add_buffer(new MediaBuffer(mTrack.mMaxSampleSize)); 110 mSampleIndex = 0; 111 112 const char *mime; 113 CHECK(mTrack.mMeta->findCString(kKeyMIMEType, &mime)); 114 115 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) { 116 mSplitter = new MP3Splitter; 117 } else { 118 mSplitter.clear(); 119 } 120 121 return OK; 122 } 123 124 status_t AVIExtractor::AVISource::stop() { 125 CHECK(mBufferGroup); 126 127 delete mBufferGroup; 128 mBufferGroup = NULL; 129 130 mSplitter.clear(); 131 132 return OK; 133 } 134 135 sp<MetaData> AVIExtractor::AVISource::getFormat() { 136 return mTrack.mMeta; 137 } 138 139 status_t AVIExtractor::AVISource::read( 140 MediaBuffer **buffer, const ReadOptions *options) { 141 CHECK(mBufferGroup); 142 143 *buffer = NULL; 144 145 int64_t seekTimeUs; 146 ReadOptions::SeekMode seekMode; 147 if (options && options->getSeekTo(&seekTimeUs, &seekMode)) { 148 status_t err = 149 mExtractor->getSampleIndexAtTime( 150 mTrackIndex, seekTimeUs, seekMode, &mSampleIndex); 151 152 if (err != OK) { 153 return ERROR_END_OF_STREAM; 154 } 155 156 if (mSplitter != NULL) { 157 mSplitter->clear(); 158 } 159 } 160 161 for (;;) { 162 if (mSplitter != NULL) { 163 status_t err = mSplitter->read(buffer); 164 165 if (err == OK) { 166 break; 167 } else if (err != -EAGAIN) { 168 return err; 169 } 170 } 171 172 off64_t offset; 173 size_t size; 174 bool isKey; 175 int64_t timeUs; 176 status_t err = mExtractor->getSampleInfo( 177 mTrackIndex, mSampleIndex, &offset, &size, &isKey, &timeUs); 178 179 ++mSampleIndex; 180 181 if (err != OK) { 182 return ERROR_END_OF_STREAM; 183 } 184 185 MediaBuffer *out; 186 CHECK_EQ(mBufferGroup->acquire_buffer(&out), (status_t)OK); 187 188 ssize_t n = mExtractor->mDataSource->readAt(offset, out->data(), size); 189 190 if (n < (ssize_t)size) { 191 return n < 0 ? (status_t)n : (status_t)ERROR_MALFORMED; 192 } 193 194 out->set_range(0, size); 195 196 out->meta_data()->setInt64(kKeyTime, timeUs); 197 198 if (isKey) { 199 out->meta_data()->setInt32(kKeyIsSyncFrame, 1); 200 } 201 202 if (mSplitter == NULL) { 203 *buffer = out; 204 break; 205 } 206 207 mSplitter->append(out); 208 out->release(); 209 out = NULL; 210 } 211 212 return OK; 213 } 214 215 //////////////////////////////////////////////////////////////////////////////// 216 217 AVIExtractor::MP3Splitter::MP3Splitter() 218 : mFindSync(true), 219 mBaseTimeUs(-1ll), 220 mNumSamplesRead(0) { 221 } 222 223 AVIExtractor::MP3Splitter::~MP3Splitter() { 224 } 225 226 void AVIExtractor::MP3Splitter::clear() { 227 mFindSync = true; 228 mBaseTimeUs = -1ll; 229 mNumSamplesRead = 0; 230 231 if (mBuffer != NULL) { 232 mBuffer->setRange(0, 0); 233 } 234 } 235 236 void AVIExtractor::MP3Splitter::append(MediaBuffer *buffer) { 237 size_t prevCapacity = (mBuffer != NULL) ? mBuffer->capacity() : 0; 238 239 if (mBaseTimeUs < 0) { 240 CHECK(mBuffer == NULL || mBuffer->size() == 0); 241 CHECK(buffer->meta_data()->findInt64(kKeyTime, &mBaseTimeUs)); 242 mNumSamplesRead = 0; 243 } 244 245 if (mBuffer != NULL && mBuffer->offset() > 0) { 246 memmove(mBuffer->base(), mBuffer->data(), mBuffer->size()); 247 mBuffer->setRange(0, mBuffer->size()); 248 } 249 250 if (mBuffer == NULL 251 || mBuffer->size() + buffer->range_length() > prevCapacity) { 252 size_t newCapacity = 253 (prevCapacity + buffer->range_length() + 1023) & ~1023; 254 255 sp<ABuffer> newBuffer = new ABuffer(newCapacity); 256 if (mBuffer != NULL) { 257 memcpy(newBuffer->data(), mBuffer->data(), mBuffer->size()); 258 newBuffer->setRange(0, mBuffer->size()); 259 } else { 260 newBuffer->setRange(0, 0); 261 } 262 mBuffer = newBuffer; 263 } 264 265 memcpy(mBuffer->data() + mBuffer->size(), 266 (const uint8_t *)buffer->data() + buffer->range_offset(), 267 buffer->range_length()); 268 269 mBuffer->setRange(0, mBuffer->size() + buffer->range_length()); 270 } 271 272 bool AVIExtractor::MP3Splitter::resync() { 273 if (mBuffer == NULL) { 274 return false; 275 } 276 277 bool foundSync = false; 278 for (size_t offset = 0; offset + 3 < mBuffer->size(); ++offset) { 279 uint32_t firstHeader = U32_AT(mBuffer->data() + offset); 280 281 size_t frameSize; 282 if (!GetMPEGAudioFrameSize(firstHeader, &frameSize)) { 283 continue; 284 } 285 286 size_t subsequentOffset = offset + frameSize; 287 size_t i = 3; 288 while (i > 0) { 289 if (subsequentOffset + 3 >= mBuffer->size()) { 290 break; 291 } 292 293 static const uint32_t kMask = 0xfffe0c00; 294 295 uint32_t header = U32_AT(mBuffer->data() + subsequentOffset); 296 if ((header & kMask) != (firstHeader & kMask)) { 297 break; 298 } 299 300 if (!GetMPEGAudioFrameSize(header, &frameSize)) { 301 break; 302 } 303 304 subsequentOffset += frameSize; 305 --i; 306 } 307 308 if (i == 0) { 309 foundSync = true; 310 memmove(mBuffer->data(), 311 mBuffer->data() + offset, 312 mBuffer->size() - offset); 313 314 mBuffer->setRange(0, mBuffer->size() - offset); 315 break; 316 } 317 } 318 319 return foundSync; 320 } 321 322 status_t AVIExtractor::MP3Splitter::read(MediaBuffer **out) { 323 *out = NULL; 324 325 if (mFindSync) { 326 if (!resync()) { 327 return -EAGAIN; 328 } 329 330 mFindSync = false; 331 } 332 333 if (mBuffer->size() < 4) { 334 return -EAGAIN; 335 } 336 337 uint32_t header = U32_AT(mBuffer->data()); 338 size_t frameSize; 339 int sampleRate; 340 int numSamples; 341 if (!GetMPEGAudioFrameSize( 342 header, &frameSize, &sampleRate, NULL, NULL, &numSamples)) { 343 return ERROR_MALFORMED; 344 } 345 346 if (mBuffer->size() < frameSize) { 347 return -EAGAIN; 348 } 349 350 MediaBuffer *mbuf = new MediaBuffer(frameSize); 351 memcpy(mbuf->data(), mBuffer->data(), frameSize); 352 353 int64_t timeUs = mBaseTimeUs + (mNumSamplesRead * 1000000ll) / sampleRate; 354 mNumSamplesRead += numSamples; 355 356 mbuf->meta_data()->setInt64(kKeyTime, timeUs); 357 358 mBuffer->setRange( 359 mBuffer->offset() + frameSize, mBuffer->size() - frameSize); 360 361 *out = mbuf; 362 363 return OK; 364 } 365 366 //////////////////////////////////////////////////////////////////////////////// 367 368 AVIExtractor::AVIExtractor(const sp<DataSource> &dataSource) 369 : mDataSource(dataSource) { 370 mInitCheck = parseHeaders(); 371 372 if (mInitCheck != OK) { 373 mTracks.clear(); 374 } 375 } 376 377 AVIExtractor::~AVIExtractor() { 378 } 379 380 size_t AVIExtractor::countTracks() { 381 return mTracks.size(); 382 } 383 384 sp<MediaSource> AVIExtractor::getTrack(size_t index) { 385 return index < mTracks.size() ? new AVISource(this, index) : NULL; 386 } 387 388 sp<MetaData> AVIExtractor::getTrackMetaData( 389 size_t index, uint32_t flags) { 390 return index < mTracks.size() ? mTracks.editItemAt(index).mMeta : NULL; 391 } 392 393 sp<MetaData> AVIExtractor::getMetaData() { 394 sp<MetaData> meta = new MetaData; 395 396 if (mInitCheck == OK) { 397 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_AVI); 398 } 399 400 return meta; 401 } 402 403 status_t AVIExtractor::parseHeaders() { 404 mTracks.clear(); 405 mMovieOffset = 0; 406 mFoundIndex = false; 407 mOffsetsAreAbsolute = false; 408 409 ssize_t res = parseChunk(0ll, -1ll); 410 411 if (res < 0) { 412 return (status_t)res; 413 } 414 415 if (mMovieOffset == 0ll || !mFoundIndex) { 416 return ERROR_MALFORMED; 417 } 418 419 return OK; 420 } 421 422 ssize_t AVIExtractor::parseChunk(off64_t offset, off64_t size, int depth) { 423 if (size >= 0 && size < 8) { 424 return ERROR_MALFORMED; 425 } 426 427 uint8_t tmp[12]; 428 ssize_t n = mDataSource->readAt(offset, tmp, 8); 429 430 if (n < 8) { 431 return (n < 0) ? n : (ssize_t)ERROR_MALFORMED; 432 } 433 434 uint32_t fourcc = U32_AT(tmp); 435 uint32_t chunkSize = U32LE_AT(&tmp[4]); 436 437 if (size >= 0 && chunkSize + 8 > size) { 438 return ERROR_MALFORMED; 439 } 440 441 static const char kPrefix[] = " "; 442 const char *prefix = &kPrefix[strlen(kPrefix) - 2 * depth]; 443 444 if (fourcc == FOURCC('L', 'I', 'S', 'T') 445 || fourcc == FOURCC('R', 'I', 'F', 'F')) { 446 // It's a list of chunks 447 448 if (size >= 0 && size < 12) { 449 return ERROR_MALFORMED; 450 } 451 452 n = mDataSource->readAt(offset + 8, &tmp[8], 4); 453 454 if (n < 4) { 455 return (n < 0) ? n : (ssize_t)ERROR_MALFORMED; 456 } 457 458 uint32_t subFourcc = U32_AT(&tmp[8]); 459 460 LOGV("%s offset 0x%08llx LIST of '%c%c%c%c', size %d", 461 prefix, 462 offset, 463 (char)(subFourcc >> 24), 464 (char)((subFourcc >> 16) & 0xff), 465 (char)((subFourcc >> 8) & 0xff), 466 (char)(subFourcc & 0xff), 467 chunkSize - 4); 468 469 if (subFourcc == FOURCC('m', 'o', 'v', 'i')) { 470 // We're not going to parse this, but will take note of the 471 // offset. 472 473 mMovieOffset = offset; 474 } else { 475 off64_t subOffset = offset + 12; 476 off64_t subOffsetLimit = subOffset + chunkSize - 4; 477 while (subOffset < subOffsetLimit) { 478 ssize_t res = 479 parseChunk(subOffset, subOffsetLimit - subOffset, depth + 1); 480 481 if (res < 0) { 482 return res; 483 } 484 485 subOffset += res; 486 } 487 } 488 } else { 489 LOGV("%s offset 0x%08llx CHUNK '%c%c%c%c'", 490 prefix, 491 offset, 492 (char)(fourcc >> 24), 493 (char)((fourcc >> 16) & 0xff), 494 (char)((fourcc >> 8) & 0xff), 495 (char)(fourcc & 0xff)); 496 497 status_t err = OK; 498 499 switch (fourcc) { 500 case FOURCC('s', 't', 'r', 'h'): 501 { 502 err = parseStreamHeader(offset + 8, chunkSize); 503 break; 504 } 505 506 case FOURCC('s', 't', 'r', 'f'): 507 { 508 err = parseStreamFormat(offset + 8, chunkSize); 509 break; 510 } 511 512 case FOURCC('i', 'd', 'x', '1'): 513 { 514 err = parseIndex(offset + 8, chunkSize); 515 break; 516 } 517 518 default: 519 break; 520 } 521 522 if (err != OK) { 523 return err; 524 } 525 } 526 527 if (chunkSize & 1) { 528 ++chunkSize; 529 } 530 531 return chunkSize + 8; 532 } 533 534 static const char *GetMIMETypeForHandler(uint32_t handler) { 535 switch (handler) { 536 // Wow... shamelessly copied from 537 // http://wiki.multimedia.cx/index.php?title=ISO_MPEG-4 538 539 case FOURCC('3', 'I', 'V', '2'): 540 case FOURCC('3', 'i', 'v', '2'): 541 case FOURCC('B', 'L', 'Z', '0'): 542 case FOURCC('D', 'I', 'G', 'I'): 543 case FOURCC('D', 'I', 'V', '1'): 544 case FOURCC('d', 'i', 'v', '1'): 545 case FOURCC('D', 'I', 'V', 'X'): 546 case FOURCC('d', 'i', 'v', 'x'): 547 case FOURCC('D', 'X', '5', '0'): 548 case FOURCC('d', 'x', '5', '0'): 549 case FOURCC('D', 'X', 'G', 'M'): 550 case FOURCC('E', 'M', '4', 'A'): 551 case FOURCC('E', 'P', 'H', 'V'): 552 case FOURCC('F', 'M', 'P', '4'): 553 case FOURCC('f', 'm', 'p', '4'): 554 case FOURCC('F', 'V', 'F', 'W'): 555 case FOURCC('H', 'D', 'X', '4'): 556 case FOURCC('h', 'd', 'x', '4'): 557 case FOURCC('M', '4', 'C', 'C'): 558 case FOURCC('M', '4', 'S', '2'): 559 case FOURCC('m', '4', 's', '2'): 560 case FOURCC('M', 'P', '4', 'S'): 561 case FOURCC('m', 'p', '4', 's'): 562 case FOURCC('M', 'P', '4', 'V'): 563 case FOURCC('m', 'p', '4', 'v'): 564 case FOURCC('M', 'V', 'X', 'M'): 565 case FOURCC('R', 'M', 'P', '4'): 566 case FOURCC('S', 'E', 'D', 'G'): 567 case FOURCC('S', 'M', 'P', '4'): 568 case FOURCC('U', 'M', 'P', '4'): 569 case FOURCC('W', 'V', '1', 'F'): 570 case FOURCC('X', 'V', 'I', 'D'): 571 case FOURCC('X', 'v', 'i', 'D'): 572 case FOURCC('x', 'v', 'i', 'd'): 573 case FOURCC('X', 'V', 'I', 'X'): 574 return MEDIA_MIMETYPE_VIDEO_MPEG4; 575 576 // from http://wiki.multimedia.cx/index.php?title=H264 577 case FOURCC('a', 'v', 'c', '1'): 578 case FOURCC('d', 'a', 'v', 'c'): 579 case FOURCC('x', '2', '6', '4'): 580 case FOURCC('v', 's', 's', 'h'): 581 return MEDIA_MIMETYPE_VIDEO_AVC; 582 583 default: 584 return NULL; 585 } 586 } 587 588 status_t AVIExtractor::parseStreamHeader(off64_t offset, size_t size) { 589 if (size != 56) { 590 return ERROR_MALFORMED; 591 } 592 593 if (mTracks.size() > 99) { 594 return -ERANGE; 595 } 596 597 sp<ABuffer> buffer = new ABuffer(size); 598 ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size()); 599 600 if (n < (ssize_t)size) { 601 return n < 0 ? (status_t)n : ERROR_MALFORMED; 602 } 603 604 const uint8_t *data = buffer->data(); 605 606 uint32_t type = U32_AT(data); 607 uint32_t handler = U32_AT(&data[4]); 608 uint32_t flags = U32LE_AT(&data[8]); 609 610 sp<MetaData> meta = new MetaData; 611 612 uint32_t rate = U32LE_AT(&data[20]); 613 uint32_t scale = U32LE_AT(&data[24]); 614 615 uint32_t sampleSize = U32LE_AT(&data[44]); 616 617 const char *mime = NULL; 618 Track::Kind kind = Track::OTHER; 619 620 if (type == FOURCC('v', 'i', 'd', 's')) { 621 mime = GetMIMETypeForHandler(handler); 622 623 if (mime && strncasecmp(mime, "video/", 6)) { 624 return ERROR_MALFORMED; 625 } 626 627 if (mime == NULL) { 628 LOGW("Unsupported video format '%c%c%c%c'", 629 (char)(handler >> 24), 630 (char)((handler >> 16) & 0xff), 631 (char)((handler >> 8) & 0xff), 632 (char)(handler & 0xff)); 633 } 634 635 kind = Track::VIDEO; 636 } else if (type == FOURCC('a', 'u', 'd', 's')) { 637 if (mime && strncasecmp(mime, "audio/", 6)) { 638 return ERROR_MALFORMED; 639 } 640 641 kind = Track::AUDIO; 642 } 643 644 if (!mime) { 645 mime = "application/octet-stream"; 646 } 647 648 meta->setCString(kKeyMIMEType, mime); 649 650 mTracks.push(); 651 Track *track = &mTracks.editItemAt(mTracks.size() - 1); 652 653 track->mMeta = meta; 654 track->mRate = rate; 655 track->mScale = scale; 656 track->mBytesPerSample = sampleSize; 657 track->mKind = kind; 658 track->mNumSyncSamples = 0; 659 track->mThumbnailSampleSize = 0; 660 track->mThumbnailSampleIndex = -1; 661 track->mMaxSampleSize = 0; 662 track->mAvgChunkSize = 1.0; 663 track->mFirstChunkSize = 0; 664 665 return OK; 666 } 667 668 status_t AVIExtractor::parseStreamFormat(off64_t offset, size_t size) { 669 if (mTracks.isEmpty()) { 670 return ERROR_MALFORMED; 671 } 672 673 Track *track = &mTracks.editItemAt(mTracks.size() - 1); 674 675 if (track->mKind == Track::OTHER) { 676 // We don't support this content, but that's not a parsing error. 677 return OK; 678 } 679 680 bool isVideo = (track->mKind == Track::VIDEO); 681 682 if ((isVideo && size < 40) || (!isVideo && size < 16)) { 683 // Expected a BITMAPINFO or WAVEFORMAT(EX) structure, respectively. 684 return ERROR_MALFORMED; 685 } 686 687 sp<ABuffer> buffer = new ABuffer(size); 688 ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size()); 689 690 if (n < (ssize_t)size) { 691 return n < 0 ? (status_t)n : ERROR_MALFORMED; 692 } 693 694 const uint8_t *data = buffer->data(); 695 696 if (isVideo) { 697 uint32_t width = U32LE_AT(&data[4]); 698 uint32_t height = U32LE_AT(&data[8]); 699 700 track->mMeta->setInt32(kKeyWidth, width); 701 track->mMeta->setInt32(kKeyHeight, height); 702 } else { 703 uint32_t format = U16LE_AT(data); 704 705 if (format == 0x55) { 706 track->mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG); 707 } else { 708 LOGW("Unsupported audio format = 0x%04x", format); 709 } 710 711 uint32_t numChannels = U16LE_AT(&data[2]); 712 uint32_t sampleRate = U32LE_AT(&data[4]); 713 714 track->mMeta->setInt32(kKeyChannelCount, numChannels); 715 track->mMeta->setInt32(kKeySampleRate, sampleRate); 716 } 717 718 return OK; 719 } 720 721 // static 722 bool AVIExtractor::IsCorrectChunkType( 723 ssize_t trackIndex, Track::Kind kind, uint32_t chunkType) { 724 uint32_t chunkBase = chunkType & 0xffff; 725 726 switch (kind) { 727 case Track::VIDEO: 728 { 729 if (chunkBase != FOURCC(0, 0, 'd', 'c') 730 && chunkBase != FOURCC(0, 0, 'd', 'b')) { 731 return false; 732 } 733 break; 734 } 735 736 case Track::AUDIO: 737 { 738 if (chunkBase != FOURCC(0, 0, 'w', 'b')) { 739 return false; 740 } 741 break; 742 } 743 744 default: 745 break; 746 } 747 748 if (trackIndex < 0) { 749 return true; 750 } 751 752 uint8_t hi = chunkType >> 24; 753 uint8_t lo = (chunkType >> 16) & 0xff; 754 755 if (hi < '0' || hi > '9' || lo < '0' || lo > '9') { 756 return false; 757 } 758 759 if (trackIndex != (10 * (hi - '0') + (lo - '0'))) { 760 return false; 761 } 762 763 return true; 764 } 765 766 status_t AVIExtractor::parseIndex(off64_t offset, size_t size) { 767 if ((size % 16) != 0) { 768 return ERROR_MALFORMED; 769 } 770 771 sp<ABuffer> buffer = new ABuffer(size); 772 ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size()); 773 774 if (n < (ssize_t)size) { 775 return n < 0 ? (status_t)n : ERROR_MALFORMED; 776 } 777 778 const uint8_t *data = buffer->data(); 779 780 while (size > 0) { 781 uint32_t chunkType = U32_AT(data); 782 783 uint8_t hi = chunkType >> 24; 784 uint8_t lo = (chunkType >> 16) & 0xff; 785 786 if (hi < '0' || hi > '9' || lo < '0' || lo > '9') { 787 return ERROR_MALFORMED; 788 } 789 790 size_t trackIndex = 10 * (hi - '0') + (lo - '0'); 791 792 if (trackIndex >= mTracks.size()) { 793 return ERROR_MALFORMED; 794 } 795 796 Track *track = &mTracks.editItemAt(trackIndex); 797 798 if (!IsCorrectChunkType(-1, track->mKind, chunkType)) { 799 return ERROR_MALFORMED; 800 } 801 802 if (track->mKind == Track::OTHER) { 803 data += 16; 804 size -= 16; 805 continue; 806 } 807 808 uint32_t flags = U32LE_AT(&data[4]); 809 uint32_t offset = U32LE_AT(&data[8]); 810 uint32_t chunkSize = U32LE_AT(&data[12]); 811 812 if (chunkSize > track->mMaxSampleSize) { 813 track->mMaxSampleSize = chunkSize; 814 } 815 816 track->mSamples.push(); 817 818 SampleInfo *info = 819 &track->mSamples.editItemAt(track->mSamples.size() - 1); 820 821 info->mOffset = offset; 822 info->mIsKey = (flags & 0x10) != 0; 823 824 if (info->mIsKey) { 825 static const size_t kMaxNumSyncSamplesToScan = 20; 826 827 if (track->mNumSyncSamples < kMaxNumSyncSamplesToScan) { 828 if (chunkSize > track->mThumbnailSampleSize) { 829 track->mThumbnailSampleSize = chunkSize; 830 831 track->mThumbnailSampleIndex = 832 track->mSamples.size() - 1; 833 } 834 } 835 836 ++track->mNumSyncSamples; 837 } 838 839 data += 16; 840 size -= 16; 841 } 842 843 if (!mTracks.isEmpty()) { 844 off64_t offset; 845 size_t size; 846 bool isKey; 847 int64_t timeUs; 848 status_t err = getSampleInfo(0, 0, &offset, &size, &isKey, &timeUs); 849 850 if (err != OK) { 851 mOffsetsAreAbsolute = !mOffsetsAreAbsolute; 852 err = getSampleInfo(0, 0, &offset, &size, &isKey, &timeUs); 853 854 if (err != OK) { 855 return err; 856 } 857 } 858 859 LOGV("Chunk offsets are %s", 860 mOffsetsAreAbsolute ? "absolute" : "movie-chunk relative"); 861 } 862 863 for (size_t i = 0; i < mTracks.size(); ++i) { 864 Track *track = &mTracks.editItemAt(i); 865 866 if (track->mBytesPerSample > 0) { 867 // Assume all chunks are roughly the same size for now. 868 869 // Compute the avg. size of the first 128 chunks (if there are 870 // that many), but exclude the size of the first one, since 871 // it may be an outlier. 872 size_t numSamplesToAverage = track->mSamples.size(); 873 if (numSamplesToAverage > 256) { 874 numSamplesToAverage = 256; 875 } 876 877 double avgChunkSize = 0; 878 size_t j; 879 for (j = 0; j <= numSamplesToAverage; ++j) { 880 off64_t offset; 881 size_t size; 882 bool isKey; 883 int64_t dummy; 884 885 status_t err = 886 getSampleInfo( 887 i, j, 888 &offset, &size, &isKey, &dummy); 889 890 if (err != OK) { 891 return err; 892 } 893 894 if (j == 0) { 895 track->mFirstChunkSize = size; 896 continue; 897 } 898 899 avgChunkSize += size; 900 } 901 902 avgChunkSize /= numSamplesToAverage; 903 904 track->mAvgChunkSize = avgChunkSize; 905 } 906 907 int64_t durationUs; 908 CHECK_EQ((status_t)OK, 909 getSampleTime(i, track->mSamples.size() - 1, &durationUs)); 910 911 LOGV("track %d duration = %.2f secs", i, durationUs / 1E6); 912 913 track->mMeta->setInt64(kKeyDuration, durationUs); 914 track->mMeta->setInt32(kKeyMaxInputSize, track->mMaxSampleSize); 915 916 const char *tmp; 917 CHECK(track->mMeta->findCString(kKeyMIMEType, &tmp)); 918 919 AString mime = tmp; 920 921 if (!strncasecmp("video/", mime.c_str(), 6)) { 922 if (track->mThumbnailSampleIndex >= 0) { 923 int64_t thumbnailTimeUs; 924 CHECK_EQ((status_t)OK, 925 getSampleTime(i, track->mThumbnailSampleIndex, 926 &thumbnailTimeUs)); 927 928 track->mMeta->setInt64(kKeyThumbnailTime, thumbnailTimeUs); 929 } 930 931 status_t err = OK; 932 933 if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_MPEG4)) { 934 err = addMPEG4CodecSpecificData(i); 935 } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)) { 936 err = addH264CodecSpecificData(i); 937 } 938 939 if (err != OK) { 940 return err; 941 } 942 } 943 } 944 945 mFoundIndex = true; 946 947 return OK; 948 } 949 950 static size_t GetSizeWidth(size_t x) { 951 size_t n = 1; 952 while (x > 127) { 953 ++n; 954 x >>= 7; 955 } 956 return n; 957 } 958 959 static uint8_t *EncodeSize(uint8_t *dst, size_t x) { 960 while (x > 127) { 961 *dst++ = (x & 0x7f) | 0x80; 962 x >>= 7; 963 } 964 *dst++ = x; 965 return dst; 966 } 967 968 sp<ABuffer> MakeMPEG4VideoCodecSpecificData(const sp<ABuffer> &config) { 969 size_t len1 = config->size() + GetSizeWidth(config->size()) + 1; 970 size_t len2 = len1 + GetSizeWidth(len1) + 1 + 13; 971 size_t len3 = len2 + GetSizeWidth(len2) + 1 + 3; 972 973 sp<ABuffer> csd = new ABuffer(len3); 974 uint8_t *dst = csd->data(); 975 *dst++ = 0x03; 976 dst = EncodeSize(dst, len2 + 3); 977 *dst++ = 0x00; // ES_ID 978 *dst++ = 0x00; 979 *dst++ = 0x00; // streamDependenceFlag, URL_Flag, OCRstreamFlag 980 981 *dst++ = 0x04; 982 dst = EncodeSize(dst, len1 + 13); 983 *dst++ = 0x01; // Video ISO/IEC 14496-2 Simple Profile 984 for (size_t i = 0; i < 12; ++i) { 985 *dst++ = 0x00; 986 } 987 988 *dst++ = 0x05; 989 dst = EncodeSize(dst, config->size()); 990 memcpy(dst, config->data(), config->size()); 991 dst += config->size(); 992 993 // hexdump(csd->data(), csd->size()); 994 995 return csd; 996 } 997 998 status_t AVIExtractor::addMPEG4CodecSpecificData(size_t trackIndex) { 999 Track *track = &mTracks.editItemAt(trackIndex); 1000 1001 off64_t offset; 1002 size_t size; 1003 bool isKey; 1004 int64_t timeUs; 1005 status_t err = 1006 getSampleInfo(trackIndex, 0, &offset, &size, &isKey, &timeUs); 1007 1008 if (err != OK) { 1009 return err; 1010 } 1011 1012 sp<ABuffer> buffer = new ABuffer(size); 1013 ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size()); 1014 1015 if (n < (ssize_t)size) { 1016 return n < 0 ? (status_t)n : ERROR_MALFORMED; 1017 } 1018 1019 // Extract everything up to the first VOP start code from the first 1020 // frame's encoded data and use it to construct an ESDS with the 1021 // codec specific data. 1022 1023 size_t i = 0; 1024 bool found = false; 1025 while (i + 3 < buffer->size()) { 1026 if (!memcmp("\x00\x00\x01\xb6", &buffer->data()[i], 4)) { 1027 found = true; 1028 break; 1029 } 1030 1031 ++i; 1032 } 1033 1034 if (!found) { 1035 return ERROR_MALFORMED; 1036 } 1037 1038 buffer->setRange(0, i); 1039 1040 sp<ABuffer> csd = MakeMPEG4VideoCodecSpecificData(buffer); 1041 track->mMeta->setData(kKeyESDS, kTypeESDS, csd->data(), csd->size()); 1042 1043 return OK; 1044 } 1045 1046 status_t AVIExtractor::addH264CodecSpecificData(size_t trackIndex) { 1047 Track *track = &mTracks.editItemAt(trackIndex); 1048 1049 off64_t offset; 1050 size_t size; 1051 bool isKey; 1052 int64_t timeUs; 1053 1054 // Extract codec specific data from the first non-empty sample. 1055 1056 size_t sampleIndex = 0; 1057 for (;;) { 1058 status_t err = 1059 getSampleInfo( 1060 trackIndex, sampleIndex, &offset, &size, &isKey, &timeUs); 1061 1062 if (err != OK) { 1063 return err; 1064 } 1065 1066 if (size > 0) { 1067 break; 1068 } 1069 1070 ++sampleIndex; 1071 } 1072 1073 sp<ABuffer> buffer = new ABuffer(size); 1074 ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size()); 1075 1076 if (n < (ssize_t)size) { 1077 return n < 0 ? (status_t)n : ERROR_MALFORMED; 1078 } 1079 1080 sp<MetaData> meta = MakeAVCCodecSpecificData(buffer); 1081 1082 if (meta == NULL) { 1083 LOGE("Unable to extract AVC codec specific data"); 1084 return ERROR_MALFORMED; 1085 } 1086 1087 int32_t width, height; 1088 CHECK(meta->findInt32(kKeyWidth, &width)); 1089 CHECK(meta->findInt32(kKeyHeight, &height)); 1090 1091 uint32_t type; 1092 const void *csd; 1093 size_t csdSize; 1094 CHECK(meta->findData(kKeyAVCC, &type, &csd, &csdSize)); 1095 1096 track->mMeta->setInt32(kKeyWidth, width); 1097 track->mMeta->setInt32(kKeyHeight, width); 1098 track->mMeta->setData(kKeyAVCC, type, csd, csdSize); 1099 1100 return OK; 1101 } 1102 1103 status_t AVIExtractor::getSampleInfo( 1104 size_t trackIndex, size_t sampleIndex, 1105 off64_t *offset, size_t *size, bool *isKey, 1106 int64_t *sampleTimeUs) { 1107 if (trackIndex >= mTracks.size()) { 1108 return -ERANGE; 1109 } 1110 1111 const Track &track = mTracks.itemAt(trackIndex); 1112 1113 if (sampleIndex >= track.mSamples.size()) { 1114 return -ERANGE; 1115 } 1116 1117 const SampleInfo &info = track.mSamples.itemAt(sampleIndex); 1118 1119 if (!mOffsetsAreAbsolute) { 1120 *offset = info.mOffset + mMovieOffset + 8; 1121 } else { 1122 *offset = info.mOffset; 1123 } 1124 1125 *size = 0; 1126 1127 uint8_t tmp[8]; 1128 ssize_t n = mDataSource->readAt(*offset, tmp, 8); 1129 1130 if (n < 8) { 1131 return n < 0 ? (status_t)n : (status_t)ERROR_MALFORMED; 1132 } 1133 1134 uint32_t chunkType = U32_AT(tmp); 1135 1136 if (!IsCorrectChunkType(trackIndex, track.mKind, chunkType)) { 1137 return ERROR_MALFORMED; 1138 } 1139 1140 *offset += 8; 1141 *size = U32LE_AT(&tmp[4]); 1142 1143 *isKey = info.mIsKey; 1144 1145 if (track.mBytesPerSample > 0) { 1146 size_t sampleStartInBytes; 1147 if (sampleIndex == 0) { 1148 sampleStartInBytes = 0; 1149 } else { 1150 sampleStartInBytes = 1151 track.mFirstChunkSize + track.mAvgChunkSize * (sampleIndex - 1); 1152 } 1153 1154 sampleIndex = sampleStartInBytes / track.mBytesPerSample; 1155 } 1156 1157 *sampleTimeUs = (sampleIndex * 1000000ll * track.mRate) / track.mScale; 1158 1159 return OK; 1160 } 1161 1162 status_t AVIExtractor::getSampleTime( 1163 size_t trackIndex, size_t sampleIndex, int64_t *sampleTimeUs) { 1164 off64_t offset; 1165 size_t size; 1166 bool isKey; 1167 return getSampleInfo( 1168 trackIndex, sampleIndex, &offset, &size, &isKey, sampleTimeUs); 1169 } 1170 1171 status_t AVIExtractor::getSampleIndexAtTime( 1172 size_t trackIndex, 1173 int64_t timeUs, MediaSource::ReadOptions::SeekMode mode, 1174 size_t *sampleIndex) const { 1175 if (trackIndex >= mTracks.size()) { 1176 return -ERANGE; 1177 } 1178 1179 const Track &track = mTracks.itemAt(trackIndex); 1180 1181 ssize_t closestSampleIndex; 1182 1183 if (track.mBytesPerSample > 0) { 1184 size_t closestByteOffset = 1185 (timeUs * track.mBytesPerSample) 1186 / track.mRate * track.mScale / 1000000ll; 1187 1188 if (closestByteOffset <= track.mFirstChunkSize) { 1189 closestSampleIndex = 0; 1190 } else { 1191 closestSampleIndex = 1192 (closestByteOffset - track.mFirstChunkSize) 1193 / track.mAvgChunkSize; 1194 } 1195 } else { 1196 // Each chunk contains a single sample. 1197 closestSampleIndex = timeUs / track.mRate * track.mScale / 1000000ll; 1198 } 1199 1200 ssize_t numSamples = track.mSamples.size(); 1201 1202 if (closestSampleIndex < 0) { 1203 closestSampleIndex = 0; 1204 } else if (closestSampleIndex >= numSamples) { 1205 closestSampleIndex = numSamples - 1; 1206 } 1207 1208 if (mode == MediaSource::ReadOptions::SEEK_CLOSEST) { 1209 *sampleIndex = closestSampleIndex; 1210 1211 return OK; 1212 } 1213 1214 ssize_t prevSyncSampleIndex = closestSampleIndex; 1215 while (prevSyncSampleIndex >= 0) { 1216 const SampleInfo &info = 1217 track.mSamples.itemAt(prevSyncSampleIndex); 1218 1219 if (info.mIsKey) { 1220 break; 1221 } 1222 1223 --prevSyncSampleIndex; 1224 } 1225 1226 ssize_t nextSyncSampleIndex = closestSampleIndex; 1227 while (nextSyncSampleIndex < numSamples) { 1228 const SampleInfo &info = 1229 track.mSamples.itemAt(nextSyncSampleIndex); 1230 1231 if (info.mIsKey) { 1232 break; 1233 } 1234 1235 ++nextSyncSampleIndex; 1236 } 1237 1238 switch (mode) { 1239 case MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC: 1240 { 1241 *sampleIndex = prevSyncSampleIndex; 1242 1243 return prevSyncSampleIndex >= 0 ? OK : UNKNOWN_ERROR; 1244 } 1245 1246 case MediaSource::ReadOptions::SEEK_NEXT_SYNC: 1247 { 1248 *sampleIndex = nextSyncSampleIndex; 1249 1250 return nextSyncSampleIndex < numSamples ? OK : UNKNOWN_ERROR; 1251 } 1252 1253 case MediaSource::ReadOptions::SEEK_CLOSEST_SYNC: 1254 { 1255 if (prevSyncSampleIndex < 0 && nextSyncSampleIndex >= numSamples) { 1256 return UNKNOWN_ERROR; 1257 } 1258 1259 if (prevSyncSampleIndex < 0) { 1260 *sampleIndex = nextSyncSampleIndex; 1261 return OK; 1262 } 1263 1264 if (nextSyncSampleIndex >= numSamples) { 1265 *sampleIndex = prevSyncSampleIndex; 1266 return OK; 1267 } 1268 1269 size_t dist1 = closestSampleIndex - prevSyncSampleIndex; 1270 size_t dist2 = nextSyncSampleIndex - closestSampleIndex; 1271 1272 *sampleIndex = 1273 (dist1 < dist2) ? prevSyncSampleIndex : nextSyncSampleIndex; 1274 1275 return OK; 1276 } 1277 1278 default: 1279 TRESPASS(); 1280 break; 1281 } 1282 } 1283 1284 bool SniffAVI( 1285 const sp<DataSource> &source, String8 *mimeType, float *confidence, 1286 sp<AMessage> *) { 1287 char tmp[12]; 1288 if (source->readAt(0, tmp, 12) < 12) { 1289 return false; 1290 } 1291 1292 if (!memcmp(tmp, "RIFF", 4) && !memcmp(&tmp[8], "AVI ", 4)) { 1293 mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_AVI); 1294 1295 // Just a tad over the mp3 extractor's confidence, since 1296 // these .avi files may contain .mp3 content that otherwise would 1297 // mistakenly lead to us identifying the entire file as a .mp3 file. 1298 *confidence = 0.21; 1299 1300 return true; 1301 } 1302 1303 return false; 1304 } 1305 1306 } // namespace android 1307