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