MPEG4Extractor.cpp revision e46b7be812d68e49710b34048662cbf18e2a6550
1/* 2 * Copyright (C) 2009 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_TAG "MPEG4Extractor" 18#include <utils/Log.h> 19 20#include <arpa/inet.h> 21 22#undef NDEBUG 23#include <assert.h> 24 25#include <ctype.h> 26#include <stdint.h> 27#include <stdlib.h> 28#include <string.h> 29 30#include <media/stagefright/DataSource.h> 31#include <media/stagefright/MPEG4Extractor.h> 32#include <media/stagefright/MediaBuffer.h> 33#include <media/stagefright/MediaBufferGroup.h> 34#include <media/stagefright/MediaSource.h> 35#include <media/stagefright/MetaData.h> 36#include <media/stagefright/SampleTable.h> 37#include <media/stagefright/Utils.h> 38#include <utils/String8.h> 39 40namespace android { 41 42class MPEG4Source : public MediaSource { 43public: 44 // Caller retains ownership of both "dataSource" and "sampleTable". 45 MPEG4Source(const sp<MetaData> &format, DataSource *dataSource, 46 SampleTable *sampleTable); 47 48 virtual ~MPEG4Source(); 49 50 virtual status_t start(MetaData *params = NULL); 51 virtual status_t stop(); 52 53 virtual sp<MetaData> getFormat(); 54 55 virtual status_t read( 56 MediaBuffer **buffer, const ReadOptions *options = NULL); 57 58private: 59 sp<MetaData> mFormat; 60 DataSource *mDataSource; 61 int32_t mTimescale; 62 SampleTable *mSampleTable; 63 uint32_t mCurrentSampleIndex; 64 65 bool mIsAVC; 66 bool mStarted; 67 68 MediaBufferGroup *mGroup; 69 70 MediaBuffer *mBuffer; 71 size_t mBufferOffset; 72 size_t mBufferSizeRemaining; 73 74 bool mNeedsNALFraming; 75 76 MPEG4Source(const MPEG4Source &); 77 MPEG4Source &operator=(const MPEG4Source &); 78}; 79 80static void hexdump(const void *_data, size_t size) { 81 const uint8_t *data = (const uint8_t *)_data; 82 size_t offset = 0; 83 while (offset < size) { 84 printf("0x%04x ", offset); 85 86 size_t n = size - offset; 87 if (n > 16) { 88 n = 16; 89 } 90 91 for (size_t i = 0; i < 16; ++i) { 92 if (i == 8) { 93 printf(" "); 94 } 95 96 if (offset + i < size) { 97 printf("%02x ", data[offset + i]); 98 } else { 99 printf(" "); 100 } 101 } 102 103 printf(" "); 104 105 for (size_t i = 0; i < n; ++i) { 106 if (isprint(data[offset + i])) { 107 printf("%c", data[offset + i]); 108 } else { 109 printf("."); 110 } 111 } 112 113 printf("\n"); 114 115 offset += 16; 116 } 117} 118 119static const char *const FourCC2MIME(uint32_t fourcc) { 120 switch (fourcc) { 121 case FOURCC('m', 'p', '4', 'a'): 122 return "audio/mp4a-latm"; 123 124 case FOURCC('s', 'a', 'm', 'r'): 125 return "audio/3gpp"; 126 127 case FOURCC('m', 'p', '4', 'v'): 128 return "video/mp4v-es"; 129 130 case FOURCC('s', '2', '6', '3'): 131 return "video/3gpp"; 132 133 case FOURCC('a', 'v', 'c', '1'): 134 return "video/avc"; 135 136 default: 137 assert(!"should not be here."); 138 return NULL; 139 } 140} 141 142MPEG4Extractor::MPEG4Extractor(DataSource *source) 143 : mDataSource(source), 144 mHaveMetadata(false), 145 mFirstTrack(NULL), 146 mLastTrack(NULL) { 147} 148 149MPEG4Extractor::~MPEG4Extractor() { 150 Track *track = mFirstTrack; 151 while (track) { 152 Track *next = track->next; 153 154 delete track->sampleTable; 155 track->sampleTable = NULL; 156 157 delete track; 158 track = next; 159 } 160 mFirstTrack = mLastTrack = NULL; 161 162 delete mDataSource; 163 mDataSource = NULL; 164} 165 166status_t MPEG4Extractor::countTracks(int *num_tracks) { 167 status_t err; 168 if ((err = readMetaData()) != OK) { 169 return err; 170 } 171 172 *num_tracks = 0; 173 Track *track = mFirstTrack; 174 while (track) { 175 ++*num_tracks; 176 track = track->next; 177 } 178 179 return OK; 180} 181 182sp<MetaData> MPEG4Extractor::getTrackMetaData(int index) { 183 if (index < 0) { 184 return NULL; 185 } 186 187 status_t err; 188 if ((err = readMetaData()) != OK) { 189 return NULL; 190 } 191 192 Track *track = mFirstTrack; 193 while (index > 0) { 194 if (track == NULL) { 195 return NULL; 196 } 197 198 track = track->next; 199 --index; 200 } 201 202 return track->meta; 203} 204 205status_t MPEG4Extractor::readMetaData() { 206 if (mHaveMetadata) { 207 return OK; 208 } 209 210 off_t offset = 0; 211 status_t err; 212 while ((err = parseChunk(&offset, 0)) == OK) { 213 } 214 215 if (mHaveMetadata) { 216 return OK; 217 } 218 219 return err; 220} 221 222static void MakeFourCCString(uint32_t x, char *s) { 223 s[0] = x >> 24; 224 s[1] = (x >> 16) & 0xff; 225 s[2] = (x >> 8) & 0xff; 226 s[3] = x & 0xff; 227 s[4] = '\0'; 228} 229 230status_t MPEG4Extractor::parseChunk(off_t *offset, int depth) { 231 uint32_t hdr[2]; 232 if (mDataSource->read_at(*offset, hdr, 8) < 8) { 233 return ERROR_IO; 234 } 235 uint64_t chunk_size = ntohl(hdr[0]); 236 uint32_t chunk_type = ntohl(hdr[1]); 237 off_t data_offset = *offset + 8; 238 239 if (chunk_size == 1) { 240 if (mDataSource->read_at(*offset + 8, &chunk_size, 8) < 8) { 241 return ERROR_IO; 242 } 243 chunk_size = ntoh64(chunk_size); 244 data_offset += 8; 245 } 246 247 char chunk[5]; 248 MakeFourCCString(chunk_type, chunk); 249 250#if 0 251 static const char kWhitespace[] = " "; 252 const char *indent = &kWhitespace[sizeof(kWhitespace) - 1 - 2 * depth]; 253 printf("%sfound chunk '%s' of size %lld\n", indent, chunk, chunk_size); 254 255 char buffer[256]; 256 if (chunk_size <= sizeof(buffer)) { 257 if (mDataSource->read_at(*offset, buffer, chunk_size) < chunk_size) { 258 return ERROR_IO; 259 } 260 261 hexdump(buffer, chunk_size); 262 } 263#endif 264 265 off_t chunk_data_size = *offset + chunk_size - data_offset; 266 267 switch(chunk_type) { 268 case FOURCC('m', 'o', 'o', 'v'): 269 case FOURCC('t', 'r', 'a', 'k'): 270 case FOURCC('m', 'd', 'i', 'a'): 271 case FOURCC('m', 'i', 'n', 'f'): 272 case FOURCC('d', 'i', 'n', 'f'): 273 case FOURCC('s', 't', 'b', 'l'): 274 case FOURCC('m', 'v', 'e', 'x'): 275 case FOURCC('m', 'o', 'o', 'f'): 276 case FOURCC('t', 'r', 'a', 'f'): 277 case FOURCC('m', 'f', 'r', 'a'): 278 case FOURCC('s', 'k', 'i' ,'p'): 279 { 280 off_t stop_offset = *offset + chunk_size; 281 *offset = data_offset; 282 while (*offset < stop_offset) { 283 status_t err = parseChunk(offset, depth + 1); 284 if (err != OK) { 285 return err; 286 } 287 } 288 assert(*offset == stop_offset); 289 290 if (chunk_type == FOURCC('m', 'o', 'o', 'v')) { 291 mHaveMetadata = true; 292 293 return UNKNOWN_ERROR; // Return a dummy error. 294 } 295 break; 296 } 297 298 case FOURCC('t', 'k', 'h', 'd'): 299 { 300 assert(chunk_data_size >= 4); 301 302 uint8_t version; 303 if (mDataSource->read_at(data_offset, &version, 1) < 1) { 304 return ERROR_IO; 305 } 306 307 uint64_t ctime, mtime, duration; 308 int32_t id; 309 uint32_t width, height; 310 311 if (version == 1) { 312 if (chunk_data_size != 36 + 60) { 313 return ERROR_MALFORMED; 314 } 315 316 uint8_t buffer[36 + 60]; 317 if (mDataSource->read_at( 318 data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) { 319 return ERROR_IO; 320 } 321 322 ctime = U64_AT(&buffer[4]); 323 mtime = U64_AT(&buffer[12]); 324 id = U32_AT(&buffer[20]); 325 duration = U64_AT(&buffer[28]); 326 width = U32_AT(&buffer[88]); 327 height = U32_AT(&buffer[92]); 328 } else if (version == 0) { 329 if (chunk_data_size != 24 + 60) { 330 return ERROR_MALFORMED; 331 } 332 333 uint8_t buffer[24 + 60]; 334 if (mDataSource->read_at( 335 data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) { 336 return ERROR_IO; 337 } 338 ctime = U32_AT(&buffer[4]); 339 mtime = U32_AT(&buffer[8]); 340 id = U32_AT(&buffer[12]); 341 duration = U32_AT(&buffer[20]); 342 width = U32_AT(&buffer[76]); 343 height = U32_AT(&buffer[80]); 344 } 345 346 Track *track = new Track; 347 track->next = NULL; 348 if (mLastTrack) { 349 mLastTrack->next = track; 350 } else { 351 mFirstTrack = track; 352 } 353 mLastTrack = track; 354 355 track->meta = new MetaData; 356 track->timescale = 0; 357 track->sampleTable = new SampleTable(mDataSource); 358 track->meta->setCString(kKeyMIMEType, "application/octet-stream"); 359 360 *offset += chunk_size; 361 break; 362 } 363 364 case FOURCC('m', 'd', 'h', 'd'): 365 { 366 if (chunk_data_size < 4) { 367 return ERROR_MALFORMED; 368 } 369 370 uint8_t version; 371 if (mDataSource->read_at( 372 data_offset, &version, sizeof(version)) 373 < (ssize_t)sizeof(version)) { 374 return ERROR_IO; 375 } 376 377 off_t timescale_offset; 378 379 if (version == 1) { 380 timescale_offset = data_offset + 4 + 16; 381 } else if (version == 0) { 382 timescale_offset = data_offset + 4 + 8; 383 } else { 384 return ERROR_IO; 385 } 386 387 uint32_t timescale; 388 if (mDataSource->read_at( 389 timescale_offset, ×cale, sizeof(timescale)) 390 < (ssize_t)sizeof(timescale)) { 391 return ERROR_IO; 392 } 393 394 mLastTrack->timescale = ntohl(timescale); 395 mLastTrack->meta->setInt32(kKeyTimeScale, mLastTrack->timescale); 396 397 int64_t duration; 398 if (version == 1) { 399 if (mDataSource->read_at( 400 timescale_offset + 4, &duration, sizeof(duration)) 401 < (ssize_t)sizeof(duration)) { 402 return ERROR_IO; 403 } 404 duration = ntoh64(duration); 405 } else { 406 int32_t duration32; 407 if (mDataSource->read_at( 408 timescale_offset + 4, &duration32, sizeof(duration32)) 409 < (ssize_t)sizeof(duration32)) { 410 return ERROR_IO; 411 } 412 duration = ntohl(duration32); 413 } 414 mLastTrack->meta->setInt32(kKeyDuration, duration); 415 416 *offset += chunk_size; 417 break; 418 } 419 420 case FOURCC('h', 'd', 'l', 'r'): 421 { 422 if (chunk_data_size < 25) { 423 return ERROR_MALFORMED; 424 } 425 426 uint8_t buffer[24]; 427 if (mDataSource->read_at(data_offset, buffer, 24) < 24) { 428 return ERROR_IO; 429 } 430 431 if (U32_AT(buffer) != 0) { 432 // Should be version 0, flags 0. 433 return ERROR_MALFORMED; 434 } 435 436 if (U32_AT(&buffer[4]) != 0) { 437 // pre_defined should be 0. 438 return ERROR_MALFORMED; 439 } 440 441 mHandlerType = U32_AT(&buffer[8]); 442 *offset += chunk_size; 443 break; 444 } 445 446 case FOURCC('s', 't', 's', 'd'): 447 { 448 if (chunk_data_size < 8) { 449 return ERROR_MALFORMED; 450 } 451 452 uint8_t buffer[8]; 453 assert(chunk_data_size >= (off_t)sizeof(buffer)); 454 if (mDataSource->read_at( 455 data_offset, buffer, 8) < 8) { 456 return ERROR_IO; 457 } 458 459 if (U32_AT(buffer) != 0) { 460 // Should be version 0, flags 0. 461 return ERROR_MALFORMED; 462 } 463 464 uint32_t entry_count = U32_AT(&buffer[4]); 465 466 if (entry_count > 1) { 467 // For now we only support a single type of media per track. 468 return ERROR_UNSUPPORTED; 469 } 470 471 off_t stop_offset = *offset + chunk_size; 472 *offset = data_offset + 8; 473 for (uint32_t i = 0; i < entry_count; ++i) { 474 status_t err = parseChunk(offset, depth + 1); 475 if (err != OK) { 476 return err; 477 } 478 } 479 assert(*offset == stop_offset); 480 break; 481 } 482 483 case FOURCC('m', 'p', '4', 'a'): 484 case FOURCC('s', 'a', 'm', 'r'): 485 { 486 if (mHandlerType != FOURCC('s', 'o', 'u', 'n')) { 487 return ERROR_MALFORMED; 488 } 489 490 uint8_t buffer[8 + 20]; 491 if (chunk_data_size < (ssize_t)sizeof(buffer)) { 492 // Basic AudioSampleEntry size. 493 return ERROR_MALFORMED; 494 } 495 496 if (mDataSource->read_at( 497 data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) { 498 return ERROR_IO; 499 } 500 501 uint16_t data_ref_index = U16_AT(&buffer[6]); 502 uint16_t num_channels = U16_AT(&buffer[16]); 503 504 if (!strcasecmp("audio/3gpp", FourCC2MIME(chunk_type))) { 505 // AMR audio is always mono. 506 num_channels = 1; 507 } 508 509 uint16_t sample_size = U16_AT(&buffer[18]); 510 uint32_t sample_rate = U32_AT(&buffer[24]) >> 16; 511 512 printf("*** coding='%s' %d channels, size %d, rate %d\n", 513 chunk, num_channels, sample_size, sample_rate); 514 515 mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type)); 516 mLastTrack->meta->setInt32(kKeyChannelCount, num_channels); 517 mLastTrack->meta->setInt32(kKeySampleRate, sample_rate); 518 519 off_t stop_offset = *offset + chunk_size; 520 *offset = data_offset + sizeof(buffer); 521 while (*offset < stop_offset) { 522 status_t err = parseChunk(offset, depth + 1); 523 if (err != OK) { 524 return err; 525 } 526 } 527 assert(*offset == stop_offset); 528 break; 529 } 530 531 case FOURCC('m', 'p', '4', 'v'): 532 case FOURCC('s', '2', '6', '3'): 533 case FOURCC('a', 'v', 'c', '1'): 534 { 535 if (mHandlerType != FOURCC('v', 'i', 'd', 'e')) { 536 return ERROR_MALFORMED; 537 } 538 539 uint8_t buffer[78]; 540 if (chunk_data_size < (ssize_t)sizeof(buffer)) { 541 // Basic VideoSampleEntry size. 542 return ERROR_MALFORMED; 543 } 544 545 if (mDataSource->read_at( 546 data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) { 547 return ERROR_IO; 548 } 549 550 uint16_t data_ref_index = U16_AT(&buffer[6]); 551 uint16_t width = U16_AT(&buffer[6 + 18]); 552 uint16_t height = U16_AT(&buffer[6 + 20]); 553 554 printf("*** coding='%s' width=%d height=%d\n", 555 chunk, width, height); 556 557 mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type)); 558 mLastTrack->meta->setInt32(kKeyWidth, width); 559 mLastTrack->meta->setInt32(kKeyHeight, height); 560 561 off_t stop_offset = *offset + chunk_size; 562 *offset = data_offset + sizeof(buffer); 563 while (*offset < stop_offset) { 564 status_t err = parseChunk(offset, depth + 1); 565 if (err != OK) { 566 return err; 567 } 568 } 569 assert(*offset == stop_offset); 570 break; 571 } 572 573 case FOURCC('s', 't', 'c', 'o'): 574 case FOURCC('c', 'o', '6', '4'): 575 { 576 status_t err = 577 mLastTrack->sampleTable->setChunkOffsetParams( 578 chunk_type, data_offset, chunk_data_size); 579 580 if (err != OK) { 581 return err; 582 } 583 584 *offset += chunk_size; 585 break; 586 } 587 588 case FOURCC('s', 't', 's', 'c'): 589 { 590 status_t err = 591 mLastTrack->sampleTable->setSampleToChunkParams( 592 data_offset, chunk_data_size); 593 594 if (err != OK) { 595 return err; 596 } 597 598 *offset += chunk_size; 599 break; 600 } 601 602 case FOURCC('s', 't', 's', 'z'): 603 case FOURCC('s', 't', 'z', '2'): 604 { 605 status_t err = 606 mLastTrack->sampleTable->setSampleSizeParams( 607 chunk_type, data_offset, chunk_data_size); 608 609 if (err != OK) { 610 return err; 611 } 612 613 *offset += chunk_size; 614 break; 615 } 616 617 case FOURCC('s', 't', 't', 's'): 618 { 619 status_t err = 620 mLastTrack->sampleTable->setTimeToSampleParams( 621 data_offset, chunk_data_size); 622 623 if (err != OK) { 624 return err; 625 } 626 627 *offset += chunk_size; 628 break; 629 } 630 631 case FOURCC('s', 't', 's', 's'): 632 { 633 status_t err = 634 mLastTrack->sampleTable->setSyncSampleParams( 635 data_offset, chunk_data_size); 636 637 if (err != OK) { 638 return err; 639 } 640 641 *offset += chunk_size; 642 break; 643 } 644 645 case FOURCC('e', 's', 'd', 's'): 646 { 647 if (chunk_data_size < 4) { 648 return ERROR_MALFORMED; 649 } 650 651 uint8_t buffer[256]; 652 if (chunk_data_size > (off_t)sizeof(buffer)) { 653 return ERROR_BUFFER_TOO_SMALL; 654 } 655 656 if (mDataSource->read_at( 657 data_offset, buffer, chunk_data_size) < chunk_data_size) { 658 return ERROR_IO; 659 } 660 661 if (U32_AT(buffer) != 0) { 662 // Should be version 0, flags 0. 663 return ERROR_MALFORMED; 664 } 665 666 mLastTrack->meta->setData( 667 kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4); 668 669 *offset += chunk_size; 670 break; 671 } 672 673 case FOURCC('a', 'v', 'c', 'C'): 674 { 675 char buffer[256]; 676 if (chunk_data_size > (off_t)sizeof(buffer)) { 677 return ERROR_BUFFER_TOO_SMALL; 678 } 679 680 if (mDataSource->read_at( 681 data_offset, buffer, chunk_data_size) < chunk_data_size) { 682 return ERROR_IO; 683 } 684 685 mLastTrack->meta->setData( 686 kKeyAVCC, kTypeAVCC, buffer, chunk_data_size); 687 688 *offset += chunk_size; 689 break; 690 } 691 692 default: 693 { 694 *offset += chunk_size; 695 break; 696 } 697 } 698 699 return OK; 700} 701 702status_t MPEG4Extractor::getTrack(int index, MediaSource **source) { 703 *source = NULL; 704 705 if (index < 0) { 706 return ERROR_OUT_OF_RANGE; 707 } 708 709 status_t err; 710 if ((err = readMetaData()) != OK) { 711 return err; 712 } 713 714 Track *track = mFirstTrack; 715 while (index > 0) { 716 if (track == NULL) { 717 return ERROR_OUT_OF_RANGE; 718 } 719 720 track = track->next; 721 --index; 722 } 723 724 *source = new MPEG4Source( 725 track->meta, mDataSource, track->sampleTable); 726 727 return OK; 728} 729 730//////////////////////////////////////////////////////////////////////////////// 731 732MPEG4Source::MPEG4Source( 733 const sp<MetaData> &format, 734 DataSource *dataSource, SampleTable *sampleTable) 735 : mFormat(format), 736 mDataSource(dataSource), 737 mTimescale(0), 738 mSampleTable(sampleTable), 739 mCurrentSampleIndex(0), 740 mIsAVC(false), 741 mStarted(false), 742 mGroup(NULL), 743 mBuffer(NULL), 744 mBufferOffset(0), 745 mBufferSizeRemaining(0), 746 mNeedsNALFraming(false) { 747 const char *mime; 748 bool success = mFormat->findCString(kKeyMIMEType, &mime); 749 assert(success); 750 751 success = mFormat->findInt32(kKeyTimeScale, &mTimescale); 752 assert(success); 753 754 mIsAVC = !strcasecmp(mime, "video/avc"); 755} 756 757MPEG4Source::~MPEG4Source() { 758 if (mStarted) { 759 stop(); 760 } 761} 762 763status_t MPEG4Source::start(MetaData *params) { 764 assert(!mStarted); 765 766 int32_t val; 767 if (mIsAVC && params && params->findInt32(kKeyNeedsNALFraming, &val) 768 && val != 0) { 769 mNeedsNALFraming = true; 770 } else { 771 mNeedsNALFraming = false; 772 } 773 774 mGroup = new MediaBufferGroup; 775 776 size_t max_size; 777 status_t err = mSampleTable->getMaxSampleSize(&max_size); 778 assert(err == OK); 779 780 // Add padding for de-framing of AVC content just in case. 781 mGroup->add_buffer(new MediaBuffer(max_size + 2)); 782 783 mStarted = true; 784 785 return OK; 786} 787 788status_t MPEG4Source::stop() { 789 assert(mStarted); 790 791 if (mBuffer != NULL) { 792 mBuffer->release(); 793 mBuffer = NULL; 794 } 795 796 delete mGroup; 797 mGroup = NULL; 798 799 mStarted = false; 800 mCurrentSampleIndex = 0; 801 802 return OK; 803} 804 805sp<MetaData> MPEG4Source::getFormat() { 806 return mFormat; 807} 808 809status_t MPEG4Source::read( 810 MediaBuffer **out, const ReadOptions *options) { 811 assert(mStarted); 812 813 *out = NULL; 814 815 int64_t seekTimeUs; 816 if (options && options->getSeekTo(&seekTimeUs)) { 817 uint32_t sampleIndex; 818 status_t err = mSampleTable->findClosestSample( 819 seekTimeUs * mTimescale / 1000000, 820 &sampleIndex, SampleTable::kSyncSample_Flag); 821 822 if (err != OK) { 823 return err; 824 } 825 826 mCurrentSampleIndex = sampleIndex; 827 if (mBuffer != NULL) { 828 mBuffer->release(); 829 mBuffer = NULL; 830 } 831 832 // fall through 833 } 834 835 if (mBuffer == NULL) { 836 off_t offset; 837 size_t size; 838 status_t err = mSampleTable->getSampleOffsetAndSize( 839 mCurrentSampleIndex, &offset, &size); 840 841 if (err != OK) { 842 return err; 843 } 844 845 uint32_t dts; 846 err = mSampleTable->getDecodingTime(mCurrentSampleIndex, &dts); 847 848 if (err != OK) { 849 return err; 850 } 851 852 err = mGroup->acquire_buffer(&mBuffer); 853 if (err != OK) { 854 assert(mBuffer == NULL); 855 return err; 856 } 857 858 assert(mBuffer->size() + 2 >= size); 859 860 ssize_t num_bytes_read = 861 mDataSource->read_at(offset, (uint8_t *)mBuffer->data() + 2, size); 862 863 if (num_bytes_read < (ssize_t)size) { 864 mBuffer->release(); 865 mBuffer = NULL; 866 867 return err; 868 } 869 870 mBuffer->set_range(2, size); 871 mBuffer->meta_data()->clear(); 872 mBuffer->meta_data()->setInt32(kKeyTimeUnits, dts); 873 mBuffer->meta_data()->setInt32(kKeyTimeScale, mTimescale); 874 875 ++mCurrentSampleIndex; 876 877 mBufferOffset = 2; 878 mBufferSizeRemaining = size; 879 } 880 881 if (!mIsAVC) { 882 *out = mBuffer; 883 mBuffer = NULL; 884 885 return OK; 886 } 887 888 uint8_t *data = (uint8_t *)mBuffer->data() + mBufferOffset; 889 assert(mBufferSizeRemaining >= 2); 890 891 size_t nal_length = (data[0] << 8) | data[1]; 892 assert(mBufferSizeRemaining >= 2 + nal_length); 893 894 if (mNeedsNALFraming) { 895 // Insert marker. 896 data[-2] = data[-1] = data[0] = 0; 897 data[1] = 1; 898 899 mBuffer->set_range(mBufferOffset - 2, nal_length + 4); 900 } else { 901 mBuffer->set_range(mBufferOffset + 2, nal_length); 902 } 903 904 mBufferOffset += nal_length + 2; 905 mBufferSizeRemaining -= nal_length + 2; 906 907 if (mBufferSizeRemaining > 0) { 908 *out = mBuffer->clone(); 909 } else { 910 *out = mBuffer; 911 mBuffer = NULL; 912 } 913 914 return OK; 915} 916 917bool SniffMPEG4(DataSource *source, String8 *mimeType, float *confidence) { 918 uint8_t header[8]; 919 920 ssize_t n = source->read_at(4, header, sizeof(header)); 921 if (n < (ssize_t)sizeof(header)) { 922 return false; 923 } 924 925 if (!memcmp(header, "ftyp3gp", 7) || !memcmp(header, "ftypmp42", 8) 926 || !memcmp(header, "ftypisom", 8) || !memcmp(header, "ftypM4V ", 8)) { 927 *mimeType = "video/mp4"; 928 *confidence = 0.1; 929 930 return true; 931 } 932 933 return false; 934} 935 936} // namespace android 937 938