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