AVIExtractor.cpp revision c639aad6d8894f57c02e620f52ccf49e51b64866
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 36namespace android { 37 38struct 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 49protected: 50 virtual ~AVISource(); 51 52private: 53 sp<AVIExtractor> mExtractor; 54 size_t mTrackIndex; 55 const AVIExtractor::Track &mTrack; 56 MediaBufferGroup *mBufferGroup; 57 size_t mSampleIndex; 58 59 DISALLOW_EVIL_CONSTRUCTORS(AVISource); 60}; 61 62//////////////////////////////////////////////////////////////////////////////// 63 64AVIExtractor::AVISource::AVISource( 65 const sp<AVIExtractor> &extractor, size_t trackIndex) 66 : mExtractor(extractor), 67 mTrackIndex(trackIndex), 68 mTrack(mExtractor->mTracks.itemAt(trackIndex)), 69 mBufferGroup(NULL) { 70} 71 72AVIExtractor::AVISource::~AVISource() { 73 if (mBufferGroup) { 74 stop(); 75 } 76} 77 78status_t AVIExtractor::AVISource::start(MetaData *params) { 79 CHECK(!mBufferGroup); 80 81 mBufferGroup = new MediaBufferGroup; 82 83 mBufferGroup->add_buffer(new MediaBuffer(mTrack.mMaxSampleSize)); 84 mBufferGroup->add_buffer(new MediaBuffer(mTrack.mMaxSampleSize)); 85 mSampleIndex = 0; 86 87 return OK; 88} 89 90status_t AVIExtractor::AVISource::stop() { 91 CHECK(mBufferGroup); 92 93 delete mBufferGroup; 94 mBufferGroup = NULL; 95 96 return OK; 97} 98 99sp<MetaData> AVIExtractor::AVISource::getFormat() { 100 return mTrack.mMeta; 101} 102 103status_t AVIExtractor::AVISource::read( 104 MediaBuffer **buffer, const ReadOptions *options) { 105 CHECK(mBufferGroup); 106 107 *buffer = NULL; 108 109 int64_t seekTimeUs; 110 ReadOptions::SeekMode seekMode; 111 if (options && options->getSeekTo(&seekTimeUs, &seekMode)) { 112 status_t err = 113 mExtractor->getSampleIndexAtTime( 114 mTrackIndex, seekTimeUs, seekMode, &mSampleIndex); 115 116 if (err != OK) { 117 return ERROR_END_OF_STREAM; 118 } 119 } 120 121 off64_t offset; 122 size_t size; 123 bool isKey; 124 int64_t timeUs; 125 status_t err = mExtractor->getSampleInfo( 126 mTrackIndex, mSampleIndex, &offset, &size, &isKey, &timeUs); 127 128 ++mSampleIndex; 129 130 if (err != OK) { 131 return ERROR_END_OF_STREAM; 132 } 133 134 MediaBuffer *out; 135 CHECK_EQ(mBufferGroup->acquire_buffer(&out), (status_t)OK); 136 137 ssize_t n = mExtractor->mDataSource->readAt(offset, out->data(), size); 138 139 if (n < (ssize_t)size) { 140 return n < 0 ? (status_t)n : (status_t)ERROR_MALFORMED; 141 } 142 143 out->set_range(0, size); 144 145 out->meta_data()->setInt64(kKeyTime, timeUs); 146 147 if (isKey) { 148 out->meta_data()->setInt32(kKeyIsSyncFrame, 1); 149 } 150 151 *buffer = out; 152 153 return OK; 154} 155 156//////////////////////////////////////////////////////////////////////////////// 157 158AVIExtractor::AVIExtractor(const sp<DataSource> &dataSource) 159 : mDataSource(dataSource) { 160 mInitCheck = parseHeaders(); 161 162 if (mInitCheck != OK) { 163 mTracks.clear(); 164 } 165} 166 167AVIExtractor::~AVIExtractor() { 168} 169 170size_t AVIExtractor::countTracks() { 171 return mTracks.size(); 172} 173 174sp<MediaSource> AVIExtractor::getTrack(size_t index) { 175 return index < mTracks.size() ? new AVISource(this, index) : NULL; 176} 177 178sp<MetaData> AVIExtractor::getTrackMetaData( 179 size_t index, uint32_t flags) { 180 return index < mTracks.size() ? mTracks.editItemAt(index).mMeta : NULL; 181} 182 183sp<MetaData> AVIExtractor::getMetaData() { 184 sp<MetaData> meta = new MetaData; 185 186 if (mInitCheck == OK) { 187 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_AVI); 188 } 189 190 return meta; 191} 192 193status_t AVIExtractor::parseHeaders() { 194 mTracks.clear(); 195 mMovieOffset = 0; 196 mFoundIndex = false; 197 mOffsetsAreAbsolute = false; 198 199 ssize_t res = parseChunk(0ll, -1ll); 200 201 if (res < 0) { 202 return (status_t)res; 203 } 204 205 if (mMovieOffset == 0ll || !mFoundIndex) { 206 return ERROR_MALFORMED; 207 } 208 209 return OK; 210} 211 212ssize_t AVIExtractor::parseChunk(off64_t offset, off64_t size, int depth) { 213 if (size >= 0 && size < 8) { 214 return ERROR_MALFORMED; 215 } 216 217 uint8_t tmp[12]; 218 ssize_t n = mDataSource->readAt(offset, tmp, 8); 219 220 if (n < 8) { 221 return (n < 0) ? n : (ssize_t)ERROR_MALFORMED; 222 } 223 224 uint32_t fourcc = U32_AT(tmp); 225 uint32_t chunkSize = U32LE_AT(&tmp[4]); 226 227 if (size >= 0 && chunkSize + 8 > size) { 228 return ERROR_MALFORMED; 229 } 230 231 static const char kPrefix[] = " "; 232 const char *prefix = &kPrefix[strlen(kPrefix) - 2 * depth]; 233 234 if (fourcc == FOURCC('L', 'I', 'S', 'T') 235 || fourcc == FOURCC('R', 'I', 'F', 'F')) { 236 // It's a list of chunks 237 238 if (size >= 0 && size < 12) { 239 return ERROR_MALFORMED; 240 } 241 242 n = mDataSource->readAt(offset + 8, &tmp[8], 4); 243 244 if (n < 4) { 245 return (n < 0) ? n : (ssize_t)ERROR_MALFORMED; 246 } 247 248 uint32_t subFourcc = U32_AT(&tmp[8]); 249 250 LOGV("%s offset 0x%08llx LIST of '%c%c%c%c', size %d", 251 prefix, 252 offset, 253 (char)(subFourcc >> 24), 254 (char)((subFourcc >> 16) & 0xff), 255 (char)((subFourcc >> 8) & 0xff), 256 (char)(subFourcc & 0xff), 257 chunkSize - 4); 258 259 if (subFourcc == FOURCC('m', 'o', 'v', 'i')) { 260 // We're not going to parse this, but will take note of the 261 // offset. 262 263 mMovieOffset = offset; 264 } else { 265 off64_t subOffset = offset + 12; 266 off64_t subOffsetLimit = subOffset + chunkSize - 4; 267 while (subOffset < subOffsetLimit) { 268 ssize_t res = 269 parseChunk(subOffset, subOffsetLimit - subOffset, depth + 1); 270 271 if (res < 0) { 272 return res; 273 } 274 275 subOffset += res; 276 } 277 } 278 } else { 279 LOGV("%s offset 0x%08llx CHUNK '%c%c%c%c'", 280 prefix, 281 offset, 282 (char)(fourcc >> 24), 283 (char)((fourcc >> 16) & 0xff), 284 (char)((fourcc >> 8) & 0xff), 285 (char)(fourcc & 0xff)); 286 287 status_t err = OK; 288 289 switch (fourcc) { 290 case FOURCC('s', 't', 'r', 'h'): 291 { 292 err = parseStreamHeader(offset + 8, chunkSize); 293 break; 294 } 295 296 case FOURCC('s', 't', 'r', 'f'): 297 { 298 err = parseStreamFormat(offset + 8, chunkSize); 299 break; 300 } 301 302 case FOURCC('i', 'd', 'x', '1'): 303 { 304 err = parseIndex(offset + 8, chunkSize); 305 break; 306 } 307 308 default: 309 break; 310 } 311 312 if (err != OK) { 313 return err; 314 } 315 } 316 317 if (chunkSize & 1) { 318 ++chunkSize; 319 } 320 321 return chunkSize + 8; 322} 323 324static const char *GetMIMETypeForHandler(uint32_t handler) { 325 switch (handler) { 326 // Wow... shamelessly copied from 327 // http://wiki.multimedia.cx/index.php?title=ISO_MPEG-4 328 329 case FOURCC('3', 'I', 'V', '2'): 330 case FOURCC('3', 'i', 'v', '2'): 331 case FOURCC('B', 'L', 'Z', '0'): 332 case FOURCC('D', 'I', 'G', 'I'): 333 case FOURCC('D', 'I', 'V', '1'): 334 case FOURCC('d', 'i', 'v', '1'): 335 case FOURCC('D', 'I', 'V', 'X'): 336 case FOURCC('d', 'i', 'v', 'x'): 337 case FOURCC('D', 'X', '5', '0'): 338 case FOURCC('d', 'x', '5', '0'): 339 case FOURCC('D', 'X', 'G', 'M'): 340 case FOURCC('E', 'M', '4', 'A'): 341 case FOURCC('E', 'P', 'H', 'V'): 342 case FOURCC('F', 'M', 'P', '4'): 343 case FOURCC('f', 'm', 'p', '4'): 344 case FOURCC('F', 'V', 'F', 'W'): 345 case FOURCC('H', 'D', 'X', '4'): 346 case FOURCC('h', 'd', 'x', '4'): 347 case FOURCC('M', '4', 'C', 'C'): 348 case FOURCC('M', '4', 'S', '2'): 349 case FOURCC('m', '4', 's', '2'): 350 case FOURCC('M', 'P', '4', 'S'): 351 case FOURCC('m', 'p', '4', 's'): 352 case FOURCC('M', 'P', '4', 'V'): 353 case FOURCC('m', 'p', '4', 'v'): 354 case FOURCC('M', 'V', 'X', 'M'): 355 case FOURCC('R', 'M', 'P', '4'): 356 case FOURCC('S', 'E', 'D', 'G'): 357 case FOURCC('S', 'M', 'P', '4'): 358 case FOURCC('U', 'M', 'P', '4'): 359 case FOURCC('W', 'V', '1', 'F'): 360 case FOURCC('X', 'V', 'I', 'D'): 361 case FOURCC('X', 'v', 'i', 'D'): 362 case FOURCC('x', 'v', 'i', 'd'): 363 case FOURCC('X', 'V', 'I', 'X'): 364 return MEDIA_MIMETYPE_VIDEO_MPEG4; 365 366 // from http://wiki.multimedia.cx/index.php?title=H264 367 case FOURCC('a', 'v', 'c', '1'): 368 case FOURCC('d', 'a', 'v', 'c'): 369 case FOURCC('x', '2', '6', '4'): 370 case FOURCC('v', 's', 's', 'h'): 371 return MEDIA_MIMETYPE_VIDEO_AVC; 372 373 default: 374 return NULL; 375 } 376} 377 378status_t AVIExtractor::parseStreamHeader(off64_t offset, size_t size) { 379 if (size != 56) { 380 return ERROR_MALFORMED; 381 } 382 383 if (mTracks.size() > 99) { 384 return -ERANGE; 385 } 386 387 sp<ABuffer> buffer = new ABuffer(size); 388 ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size()); 389 390 if (n < (ssize_t)size) { 391 return n < 0 ? (status_t)n : ERROR_MALFORMED; 392 } 393 394 const uint8_t *data = buffer->data(); 395 396 uint32_t type = U32_AT(data); 397 uint32_t handler = U32_AT(&data[4]); 398 uint32_t flags = U32LE_AT(&data[8]); 399 400 sp<MetaData> meta = new MetaData; 401 402 uint32_t rate = U32LE_AT(&data[20]); 403 uint32_t scale = U32LE_AT(&data[24]); 404 405 uint32_t sampleSize = U32LE_AT(&data[44]); 406 407 const char *mime = NULL; 408 Track::Kind kind = Track::OTHER; 409 410 if (type == FOURCC('v', 'i', 'd', 's')) { 411 mime = GetMIMETypeForHandler(handler); 412 413 if (mime && strncasecmp(mime, "video/", 6)) { 414 return ERROR_MALFORMED; 415 } 416 417 if (mime == NULL) { 418 LOGW("Unsupported video format '%c%c%c%c'", 419 (char)(handler >> 24), 420 (char)((handler >> 16) & 0xff), 421 (char)((handler >> 8) & 0xff), 422 (char)(handler & 0xff)); 423 } 424 425 kind = Track::VIDEO; 426 } else if (type == FOURCC('a', 'u', 'd', 's')) { 427 if (mime && strncasecmp(mime, "audio/", 6)) { 428 return ERROR_MALFORMED; 429 } 430 431 kind = Track::AUDIO; 432 } 433 434 if (!mime) { 435 mime = "application/octet-stream"; 436 } 437 438 meta->setCString(kKeyMIMEType, mime); 439 440 mTracks.push(); 441 Track *track = &mTracks.editItemAt(mTracks.size() - 1); 442 443 track->mMeta = meta; 444 track->mRate = rate; 445 track->mScale = scale; 446 track->mBytesPerSample = sampleSize; 447 track->mKind = kind; 448 track->mNumSyncSamples = 0; 449 track->mThumbnailSampleSize = 0; 450 track->mThumbnailSampleIndex = -1; 451 track->mMaxSampleSize = 0; 452 453 return OK; 454} 455 456status_t AVIExtractor::parseStreamFormat(off64_t offset, size_t size) { 457 if (mTracks.isEmpty()) { 458 return ERROR_MALFORMED; 459 } 460 461 Track *track = &mTracks.editItemAt(mTracks.size() - 1); 462 463 if (track->mKind == Track::OTHER) { 464 // We don't support this content, but that's not a parsing error. 465 return OK; 466 } 467 468 bool isVideo = (track->mKind == Track::VIDEO); 469 470 if ((isVideo && size < 40) || (!isVideo && size < 18)) { 471 // Expected a BITMAPINFO or WAVEFORMATEX structure, respectively. 472 return ERROR_MALFORMED; 473 } 474 475 sp<ABuffer> buffer = new ABuffer(size); 476 ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size()); 477 478 if (n < (ssize_t)size) { 479 return n < 0 ? (status_t)n : ERROR_MALFORMED; 480 } 481 482 const uint8_t *data = buffer->data(); 483 484 if (isVideo) { 485 uint32_t width = U32LE_AT(&data[4]); 486 uint32_t height = U32LE_AT(&data[8]); 487 488 track->mMeta->setInt32(kKeyWidth, width); 489 track->mMeta->setInt32(kKeyHeight, height); 490 } else { 491 uint32_t format = U16LE_AT(data); 492 493 if (format == 0x55) { 494 track->mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG); 495 } else { 496 LOGW("Unsupported audio format = 0x%04x", format); 497 } 498 499 uint32_t numChannels = U16LE_AT(&data[2]); 500 uint32_t sampleRate = U32LE_AT(&data[4]); 501 502 track->mMeta->setInt32(kKeyChannelCount, numChannels); 503 track->mMeta->setInt32(kKeySampleRate, sampleRate); 504 } 505 506 return OK; 507} 508 509// static 510bool AVIExtractor::IsCorrectChunkType( 511 ssize_t trackIndex, Track::Kind kind, uint32_t chunkType) { 512 uint32_t chunkBase = chunkType & 0xffff; 513 514 switch (kind) { 515 case Track::VIDEO: 516 { 517 if (chunkBase != FOURCC(0, 0, 'd', 'c') 518 && chunkBase != FOURCC(0, 0, 'd', 'b')) { 519 return false; 520 } 521 break; 522 } 523 524 case Track::AUDIO: 525 { 526 if (chunkBase != FOURCC(0, 0, 'w', 'b')) { 527 return false; 528 } 529 break; 530 } 531 532 default: 533 break; 534 } 535 536 if (trackIndex < 0) { 537 return true; 538 } 539 540 uint8_t hi = chunkType >> 24; 541 uint8_t lo = (chunkType >> 16) & 0xff; 542 543 if (hi < '0' || hi > '9' || lo < '0' || lo > '9') { 544 return false; 545 } 546 547 if (trackIndex != (10 * (hi - '0') + (lo - '0'))) { 548 return false; 549 } 550 551 return true; 552} 553 554status_t AVIExtractor::parseIndex(off64_t offset, size_t size) { 555 if ((size % 16) != 0) { 556 return ERROR_MALFORMED; 557 } 558 559 sp<ABuffer> buffer = new ABuffer(size); 560 ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size()); 561 562 if (n < (ssize_t)size) { 563 return n < 0 ? (status_t)n : ERROR_MALFORMED; 564 } 565 566 const uint8_t *data = buffer->data(); 567 568 while (size > 0) { 569 uint32_t chunkType = U32_AT(data); 570 571 uint8_t hi = chunkType >> 24; 572 uint8_t lo = (chunkType >> 16) & 0xff; 573 574 if (hi < '0' || hi > '9' || lo < '0' || lo > '9') { 575 return ERROR_MALFORMED; 576 } 577 578 size_t trackIndex = 10 * (hi - '0') + (lo - '0'); 579 580 if (trackIndex >= mTracks.size()) { 581 return ERROR_MALFORMED; 582 } 583 584 Track *track = &mTracks.editItemAt(trackIndex); 585 586 if (!IsCorrectChunkType(-1, track->mKind, chunkType)) { 587 return ERROR_MALFORMED; 588 } 589 590 if (track->mKind == Track::OTHER) { 591 data += 16; 592 size -= 16; 593 continue; 594 } 595 596 uint32_t flags = U32LE_AT(&data[4]); 597 uint32_t offset = U32LE_AT(&data[8]); 598 uint32_t chunkSize = U32LE_AT(&data[12]); 599 600 if (chunkSize > track->mMaxSampleSize) { 601 track->mMaxSampleSize = chunkSize; 602 } 603 604 track->mSamples.push(); 605 606 SampleInfo *info = 607 &track->mSamples.editItemAt(track->mSamples.size() - 1); 608 609 info->mOffset = offset; 610 info->mIsKey = (flags & 0x10) != 0; 611 612 if (info->mIsKey) { 613 static const size_t kMaxNumSyncSamplesToScan = 20; 614 615 if (track->mNumSyncSamples < kMaxNumSyncSamplesToScan) { 616 if (chunkSize > track->mThumbnailSampleSize) { 617 track->mThumbnailSampleSize = chunkSize; 618 619 track->mThumbnailSampleIndex = 620 track->mSamples.size() - 1; 621 } 622 } 623 624 ++track->mNumSyncSamples; 625 } 626 627 data += 16; 628 size -= 16; 629 } 630 631 if (!mTracks.isEmpty()) { 632 off64_t offset; 633 size_t size; 634 bool isKey; 635 int64_t timeUs; 636 status_t err = getSampleInfo(0, 0, &offset, &size, &isKey, &timeUs); 637 638 if (err != OK) { 639 mOffsetsAreAbsolute = !mOffsetsAreAbsolute; 640 err = getSampleInfo(0, 0, &offset, &size, &isKey, &timeUs); 641 642 if (err != OK) { 643 return err; 644 } 645 } 646 647 LOGV("Chunk offsets are %s", 648 mOffsetsAreAbsolute ? "absolute" : "movie-chunk relative"); 649 } 650 651 for (size_t i = 0; i < mTracks.size(); ++i) { 652 Track *track = &mTracks.editItemAt(i); 653 654 int64_t durationUs; 655 CHECK_EQ((status_t)OK, 656 getSampleTime(i, track->mSamples.size() - 1, &durationUs)); 657 658 LOGV("track %d duration = %.2f secs", i, durationUs / 1E6); 659 660 track->mMeta->setInt64(kKeyDuration, durationUs); 661 track->mMeta->setInt32(kKeyMaxInputSize, track->mMaxSampleSize); 662 663 const char *tmp; 664 CHECK(track->mMeta->findCString(kKeyMIMEType, &tmp)); 665 666 AString mime = tmp; 667 668 if (!strncasecmp("video/", mime.c_str(), 6)) { 669 if (track->mThumbnailSampleIndex >= 0) { 670 int64_t thumbnailTimeUs; 671 CHECK_EQ((status_t)OK, 672 getSampleTime(i, track->mThumbnailSampleIndex, 673 &thumbnailTimeUs)); 674 675 track->mMeta->setInt64(kKeyThumbnailTime, thumbnailTimeUs); 676 } 677 678 status_t err = OK; 679 680 if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_MPEG4)) { 681 err = addMPEG4CodecSpecificData(i); 682 } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)) { 683 err = addH264CodecSpecificData(i); 684 } 685 686 if (err != OK) { 687 return err; 688 } 689 } 690 691 if (track->mBytesPerSample != 0) { 692 // Assume all chunks are the same size for now. 693 694 off64_t offset; 695 size_t size; 696 bool isKey; 697 int64_t sampleTimeUs; 698 CHECK_EQ((status_t)OK, 699 getSampleInfo( 700 i, 0, 701 &offset, &size, &isKey, &sampleTimeUs)); 702 703 track->mRate *= size / track->mBytesPerSample; 704 } 705 } 706 707 mFoundIndex = true; 708 709 return OK; 710} 711 712static size_t GetSizeWidth(size_t x) { 713 size_t n = 1; 714 while (x > 127) { 715 ++n; 716 x >>= 7; 717 } 718 return n; 719} 720 721static uint8_t *EncodeSize(uint8_t *dst, size_t x) { 722 while (x > 127) { 723 *dst++ = (x & 0x7f) | 0x80; 724 x >>= 7; 725 } 726 *dst++ = x; 727 return dst; 728} 729 730sp<ABuffer> MakeMPEG4VideoCodecSpecificData(const sp<ABuffer> &config) { 731 size_t len1 = config->size() + GetSizeWidth(config->size()) + 1; 732 size_t len2 = len1 + GetSizeWidth(len1) + 1 + 13; 733 size_t len3 = len2 + GetSizeWidth(len2) + 1 + 3; 734 735 sp<ABuffer> csd = new ABuffer(len3); 736 uint8_t *dst = csd->data(); 737 *dst++ = 0x03; 738 dst = EncodeSize(dst, len2 + 3); 739 *dst++ = 0x00; // ES_ID 740 *dst++ = 0x00; 741 *dst++ = 0x00; // streamDependenceFlag, URL_Flag, OCRstreamFlag 742 743 *dst++ = 0x04; 744 dst = EncodeSize(dst, len1 + 13); 745 *dst++ = 0x01; // Video ISO/IEC 14496-2 Simple Profile 746 for (size_t i = 0; i < 12; ++i) { 747 *dst++ = 0x00; 748 } 749 750 *dst++ = 0x05; 751 dst = EncodeSize(dst, config->size()); 752 memcpy(dst, config->data(), config->size()); 753 dst += config->size(); 754 755 // hexdump(csd->data(), csd->size()); 756 757 return csd; 758} 759 760status_t AVIExtractor::addMPEG4CodecSpecificData(size_t trackIndex) { 761 Track *track = &mTracks.editItemAt(trackIndex); 762 763 off64_t offset; 764 size_t size; 765 bool isKey; 766 int64_t timeUs; 767 status_t err = 768 getSampleInfo(trackIndex, 0, &offset, &size, &isKey, &timeUs); 769 770 if (err != OK) { 771 return err; 772 } 773 774 sp<ABuffer> buffer = new ABuffer(size); 775 ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size()); 776 777 if (n < (ssize_t)size) { 778 return n < 0 ? (status_t)n : ERROR_MALFORMED; 779 } 780 781 // Extract everything up to the first VOP start code from the first 782 // frame's encoded data and use it to construct an ESDS with the 783 // codec specific data. 784 785 size_t i = 0; 786 bool found = false; 787 while (i + 3 < buffer->size()) { 788 if (!memcmp("\x00\x00\x01\xb6", &buffer->data()[i], 4)) { 789 found = true; 790 break; 791 } 792 793 ++i; 794 } 795 796 if (!found) { 797 return ERROR_MALFORMED; 798 } 799 800 buffer->setRange(0, i); 801 802 sp<ABuffer> csd = MakeMPEG4VideoCodecSpecificData(buffer); 803 track->mMeta->setData(kKeyESDS, kTypeESDS, csd->data(), csd->size()); 804 805 return OK; 806} 807 808status_t AVIExtractor::addH264CodecSpecificData(size_t trackIndex) { 809 Track *track = &mTracks.editItemAt(trackIndex); 810 811 off64_t offset; 812 size_t size; 813 bool isKey; 814 int64_t timeUs; 815 816 // Extract codec specific data from the first non-empty sample. 817 818 size_t sampleIndex = 0; 819 for (;;) { 820 status_t err = 821 getSampleInfo( 822 trackIndex, sampleIndex, &offset, &size, &isKey, &timeUs); 823 824 if (err != OK) { 825 return err; 826 } 827 828 if (size > 0) { 829 break; 830 } 831 832 ++sampleIndex; 833 } 834 835 sp<ABuffer> buffer = new ABuffer(size); 836 ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size()); 837 838 if (n < (ssize_t)size) { 839 return n < 0 ? (status_t)n : ERROR_MALFORMED; 840 } 841 842 sp<MetaData> meta = MakeAVCCodecSpecificData(buffer); 843 844 if (meta == NULL) { 845 LOGE("Unable to extract AVC codec specific data"); 846 return ERROR_MALFORMED; 847 } 848 849 int32_t width, height; 850 CHECK(meta->findInt32(kKeyWidth, &width)); 851 CHECK(meta->findInt32(kKeyHeight, &height)); 852 853 uint32_t type; 854 const void *csd; 855 size_t csdSize; 856 CHECK(meta->findData(kKeyAVCC, &type, &csd, &csdSize)); 857 858 track->mMeta->setInt32(kKeyWidth, width); 859 track->mMeta->setInt32(kKeyHeight, width); 860 track->mMeta->setData(kKeyAVCC, type, csd, csdSize); 861 862 return OK; 863} 864 865status_t AVIExtractor::getSampleInfo( 866 size_t trackIndex, size_t sampleIndex, 867 off64_t *offset, size_t *size, bool *isKey, 868 int64_t *sampleTimeUs) { 869 if (trackIndex >= mTracks.size()) { 870 return -ERANGE; 871 } 872 873 const Track &track = mTracks.itemAt(trackIndex); 874 875 if (sampleIndex >= track.mSamples.size()) { 876 return -ERANGE; 877 } 878 879 const SampleInfo &info = track.mSamples.itemAt(sampleIndex); 880 881 if (!mOffsetsAreAbsolute) { 882 *offset = info.mOffset + mMovieOffset + 8; 883 } else { 884 *offset = info.mOffset; 885 } 886 887 *size = 0; 888 889 uint8_t tmp[8]; 890 ssize_t n = mDataSource->readAt(*offset, tmp, 8); 891 892 if (n < 8) { 893 return n < 0 ? (status_t)n : (status_t)ERROR_MALFORMED; 894 } 895 896 uint32_t chunkType = U32_AT(tmp); 897 898 if (!IsCorrectChunkType(trackIndex, track.mKind, chunkType)) { 899 return ERROR_MALFORMED; 900 } 901 902 *offset += 8; 903 *size = U32LE_AT(&tmp[4]); 904 905 *isKey = info.mIsKey; 906 907 *sampleTimeUs = (sampleIndex * 1000000ll * track.mRate) / track.mScale; 908 909 return OK; 910} 911 912status_t AVIExtractor::getSampleTime( 913 size_t trackIndex, size_t sampleIndex, int64_t *sampleTimeUs) { 914 off64_t offset; 915 size_t size; 916 bool isKey; 917 return getSampleInfo( 918 trackIndex, sampleIndex, &offset, &size, &isKey, sampleTimeUs); 919} 920 921status_t AVIExtractor::getSampleIndexAtTime( 922 size_t trackIndex, 923 int64_t timeUs, MediaSource::ReadOptions::SeekMode mode, 924 size_t *sampleIndex) const { 925 if (trackIndex >= mTracks.size()) { 926 return -ERANGE; 927 } 928 929 const Track &track = mTracks.itemAt(trackIndex); 930 931 ssize_t closestSampleIndex = 932 timeUs / track.mRate * track.mScale / 1000000ll; 933 934 ssize_t numSamples = track.mSamples.size(); 935 936 if (closestSampleIndex < 0) { 937 closestSampleIndex = 0; 938 } else if (closestSampleIndex >= numSamples) { 939 closestSampleIndex = numSamples - 1; 940 } 941 942 if (mode == MediaSource::ReadOptions::SEEK_CLOSEST) { 943 *sampleIndex = closestSampleIndex; 944 945 return OK; 946 } 947 948 ssize_t prevSyncSampleIndex = closestSampleIndex; 949 while (prevSyncSampleIndex >= 0) { 950 const SampleInfo &info = 951 track.mSamples.itemAt(prevSyncSampleIndex); 952 953 if (info.mIsKey) { 954 break; 955 } 956 957 --prevSyncSampleIndex; 958 } 959 960 ssize_t nextSyncSampleIndex = closestSampleIndex; 961 while (nextSyncSampleIndex < numSamples) { 962 const SampleInfo &info = 963 track.mSamples.itemAt(nextSyncSampleIndex); 964 965 if (info.mIsKey) { 966 break; 967 } 968 969 ++nextSyncSampleIndex; 970 } 971 972 switch (mode) { 973 case MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC: 974 { 975 *sampleIndex = prevSyncSampleIndex; 976 977 return prevSyncSampleIndex >= 0 ? OK : UNKNOWN_ERROR; 978 } 979 980 case MediaSource::ReadOptions::SEEK_NEXT_SYNC: 981 { 982 *sampleIndex = nextSyncSampleIndex; 983 984 return nextSyncSampleIndex < numSamples ? OK : UNKNOWN_ERROR; 985 } 986 987 case MediaSource::ReadOptions::SEEK_CLOSEST_SYNC: 988 { 989 if (prevSyncSampleIndex < 0 && nextSyncSampleIndex >= numSamples) { 990 return UNKNOWN_ERROR; 991 } 992 993 if (prevSyncSampleIndex < 0) { 994 *sampleIndex = nextSyncSampleIndex; 995 return OK; 996 } 997 998 if (nextSyncSampleIndex >= numSamples) { 999 *sampleIndex = prevSyncSampleIndex; 1000 return OK; 1001 } 1002 1003 size_t dist1 = closestSampleIndex - prevSyncSampleIndex; 1004 size_t dist2 = nextSyncSampleIndex - closestSampleIndex; 1005 1006 *sampleIndex = 1007 (dist1 < dist2) ? prevSyncSampleIndex : nextSyncSampleIndex; 1008 1009 return OK; 1010 } 1011 1012 default: 1013 TRESPASS(); 1014 break; 1015 } 1016} 1017 1018bool SniffAVI( 1019 const sp<DataSource> &source, String8 *mimeType, float *confidence, 1020 sp<AMessage> *) { 1021 char tmp[12]; 1022 if (source->readAt(0, tmp, 12) < 12) { 1023 return false; 1024 } 1025 1026 if (!memcmp(tmp, "RIFF", 4) && !memcmp(&tmp[8], "AVI ", 4)) { 1027 mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_AVI); 1028 1029 // Just a tad over the mp3 extractor's confidence, since 1030 // these .avi files may contain .mp3 content that otherwise would 1031 // mistakenly lead to us identifying the entire file as a .mp3 file. 1032 *confidence = 0.21; 1033 1034 return true; 1035 } 1036 1037 return false; 1038} 1039 1040} // namespace android 1041