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