1/* 2 * Copyright (C) 2012 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 "FragmentedMP4Parser" 19#include <utils/Log.h> 20 21#include "include/ESDS.h" 22#include "include/FragmentedMP4Parser.h" 23#include "TrackFragment.h" 24 25 26#include <media/stagefright/foundation/ABuffer.h> 27#include <media/stagefright/foundation/ADebug.h> 28#include <media/stagefright/foundation/AMessage.h> 29#include <media/stagefright/foundation/hexdump.h> 30#include <media/stagefright/MediaDefs.h> 31#include <media/stagefright/MediaErrors.h> 32#include <media/stagefright/Utils.h> 33 34 35namespace android { 36 37static const char *Fourcc2String(uint32_t fourcc) { 38 static char buffer[5]; 39 buffer[4] = '\0'; 40 buffer[0] = fourcc >> 24; 41 buffer[1] = (fourcc >> 16) & 0xff; 42 buffer[2] = (fourcc >> 8) & 0xff; 43 buffer[3] = fourcc & 0xff; 44 45 return buffer; 46} 47 48static const char *IndentString(size_t n) { 49 static const char kSpace[] = " "; 50 return kSpace + sizeof(kSpace) - 2 * n - 1; 51} 52 53// static 54const FragmentedMP4Parser::DispatchEntry FragmentedMP4Parser::kDispatchTable[] = { 55 { FOURCC('m', 'o', 'o', 'v'), 0, NULL }, 56 { FOURCC('t', 'r', 'a', 'k'), FOURCC('m', 'o', 'o', 'v'), NULL }, 57 { FOURCC('u', 'd', 't', 'a'), FOURCC('t', 'r', 'a', 'k'), NULL }, 58 { FOURCC('u', 'd', 't', 'a'), FOURCC('m', 'o', 'o', 'v'), NULL }, 59 { FOURCC('m', 'e', 't', 'a'), FOURCC('u', 'd', 't', 'a'), NULL }, 60 { FOURCC('i', 'l', 's', 't'), FOURCC('m', 'e', 't', 'a'), NULL }, 61 62 { FOURCC('t', 'k', 'h', 'd'), FOURCC('t', 'r', 'a', 'k'), 63 &FragmentedMP4Parser::parseTrackHeader 64 }, 65 66 { FOURCC('m', 'v', 'e', 'x'), FOURCC('m', 'o', 'o', 'v'), NULL }, 67 68 { FOURCC('t', 'r', 'e', 'x'), FOURCC('m', 'v', 'e', 'x'), 69 &FragmentedMP4Parser::parseTrackExtends 70 }, 71 72 { FOURCC('e', 'd', 't', 's'), FOURCC('t', 'r', 'a', 'k'), NULL }, 73 { FOURCC('m', 'd', 'i', 'a'), FOURCC('t', 'r', 'a', 'k'), NULL }, 74 75 { FOURCC('m', 'd', 'h', 'd'), FOURCC('m', 'd', 'i', 'a'), 76 &FragmentedMP4Parser::parseMediaHeader 77 }, 78 79 { FOURCC('h', 'd', 'l', 'r'), FOURCC('m', 'd', 'i', 'a'), 80 &FragmentedMP4Parser::parseMediaHandler 81 }, 82 83 { FOURCC('m', 'i', 'n', 'f'), FOURCC('m', 'd', 'i', 'a'), NULL }, 84 { FOURCC('d', 'i', 'n', 'f'), FOURCC('m', 'i', 'n', 'f'), NULL }, 85 { FOURCC('s', 't', 'b', 'l'), FOURCC('m', 'i', 'n', 'f'), NULL }, 86 { FOURCC('s', 't', 's', 'd'), FOURCC('s', 't', 'b', 'l'), NULL }, 87 88 { FOURCC('s', 't', 's', 'z'), FOURCC('s', 't', 'b', 'l'), 89 &FragmentedMP4Parser::parseSampleSizes }, 90 91 { FOURCC('s', 't', 'z', '2'), FOURCC('s', 't', 'b', 'l'), 92 &FragmentedMP4Parser::parseCompactSampleSizes }, 93 94 { FOURCC('s', 't', 's', 'c'), FOURCC('s', 't', 'b', 'l'), 95 &FragmentedMP4Parser::parseSampleToChunk }, 96 97 { FOURCC('s', 't', 'c', 'o'), FOURCC('s', 't', 'b', 'l'), 98 &FragmentedMP4Parser::parseChunkOffsets }, 99 100 { FOURCC('c', 'o', '6', '4'), FOURCC('s', 't', 'b', 'l'), 101 &FragmentedMP4Parser::parseChunkOffsets64 }, 102 103 { FOURCC('a', 'v', 'c', 'C'), FOURCC('a', 'v', 'c', '1'), 104 &FragmentedMP4Parser::parseAVCCodecSpecificData }, 105 106 { FOURCC('e', 's', 'd', 's'), FOURCC('m', 'p', '4', 'a'), 107 &FragmentedMP4Parser::parseESDSCodecSpecificData }, 108 109 { FOURCC('e', 's', 'd', 's'), FOURCC('m', 'p', '4', 'v'), 110 &FragmentedMP4Parser::parseESDSCodecSpecificData }, 111 112 { FOURCC('m', 'd', 'a', 't'), 0, &FragmentedMP4Parser::parseMediaData }, 113 114 { FOURCC('m', 'o', 'o', 'f'), 0, NULL }, 115 { FOURCC('t', 'r', 'a', 'f'), FOURCC('m', 'o', 'o', 'f'), NULL }, 116 117 { FOURCC('t', 'f', 'h', 'd'), FOURCC('t', 'r', 'a', 'f'), 118 &FragmentedMP4Parser::parseTrackFragmentHeader 119 }, 120 { FOURCC('t', 'r', 'u', 'n'), FOURCC('t', 'r', 'a', 'f'), 121 &FragmentedMP4Parser::parseTrackFragmentRun 122 }, 123 124 { FOURCC('m', 'f', 'r', 'a'), 0, NULL }, 125 126 { FOURCC('s', 'i', 'd', 'x'), 0, &FragmentedMP4Parser::parseSegmentIndex }, 127}; 128 129struct FileSource : public FragmentedMP4Parser::Source { 130 FileSource(const char *filename) 131 : mFile(fopen(filename, "rb")) { 132 CHECK(mFile != NULL); 133 } 134 135 virtual ssize_t readAt(off64_t offset, void *data, size_t size) { 136 fseek(mFile, offset, SEEK_SET); 137 return fread(data, 1, size, mFile); 138 } 139 140 virtual bool isSeekable() { 141 return true; 142 } 143 144 private: 145 FILE *mFile; 146 147 DISALLOW_EVIL_CONSTRUCTORS(FileSource); 148}; 149 150struct ReadTracker : public RefBase { 151 ReadTracker(off64_t size) { 152 allocSize = 1 + size / 8192; // 1 bit per kilobyte 153 bitmap = (char*) calloc(1, allocSize); 154 } 155 virtual ~ReadTracker() { 156 dumpToLog(); 157 free(bitmap); 158 } 159 void mark(off64_t offset, size_t size) { 160 int firstbit = offset / 1024; 161 int lastbit = (offset + size - 1) / 1024; 162 for (int i = firstbit; i <= lastbit; i++) { 163 bitmap[i/8] |= (0x80 >> (i & 7)); 164 } 165 } 166 167 private: 168 void dumpToLog() { 169 // 96 chars per line, each char represents one kilobyte, 1 kb per bit 170 int numlines = allocSize / 12; 171 char buf[97]; 172 char *cur = bitmap; 173 for (int i = 0; i < numlines; i++ && cur) { 174 for (int j = 0; j < 12; j++) { 175 for (int k = 0; k < 8; k++) { 176 buf[(j * 8) + k] = (*cur & (0x80 >> k)) ? 'X' : '.'; 177 } 178 cur++; 179 } 180 buf[96] = '\0'; 181 ALOGI("%5dk: %s", i * 96, buf); 182 } 183 } 184 185 size_t allocSize; 186 char *bitmap; 187}; 188 189struct DataSourceSource : public FragmentedMP4Parser::Source { 190 DataSourceSource(sp<DataSource> &source) 191 : mDataSource(source) { 192 CHECK(mDataSource != NULL); 193#if 0 194 off64_t size; 195 if (source->getSize(&size) == OK) { 196 mReadTracker = new ReadTracker(size); 197 } else { 198 ALOGE("couldn't get data source size"); 199 } 200#endif 201 } 202 203 virtual ssize_t readAt(off64_t offset, void *data, size_t size) { 204 if (mReadTracker != NULL) { 205 mReadTracker->mark(offset, size); 206 } 207 return mDataSource->readAt(offset, data, size); 208 } 209 210 virtual bool isSeekable() { 211 return true; 212 } 213 214 private: 215 sp<DataSource> mDataSource; 216 sp<ReadTracker> mReadTracker; 217 218 DISALLOW_EVIL_CONSTRUCTORS(DataSourceSource); 219}; 220 221FragmentedMP4Parser::FragmentedMP4Parser() 222 : mBufferPos(0), 223 mSuspended(false), 224 mDoneWithMoov(false), 225 mFirstMoofOffset(0), 226 mFinalResult(OK) { 227} 228 229FragmentedMP4Parser::~FragmentedMP4Parser() { 230} 231 232void FragmentedMP4Parser::start(const char *filename) { 233 sp<AMessage> msg = new AMessage(kWhatStart, id()); 234 msg->setObject("source", new FileSource(filename)); 235 msg->post(); 236 ALOGV("Parser::start(%s)", filename); 237} 238 239void FragmentedMP4Parser::start(const sp<Source> &source) { 240 sp<AMessage> msg = new AMessage(kWhatStart, id()); 241 msg->setObject("source", source); 242 msg->post(); 243 ALOGV("Parser::start(Source)"); 244} 245 246void FragmentedMP4Parser::start(sp<DataSource> &source) { 247 sp<AMessage> msg = new AMessage(kWhatStart, id()); 248 msg->setObject("source", new DataSourceSource(source)); 249 msg->post(); 250 ALOGV("Parser::start(DataSource)"); 251} 252 253sp<AMessage> FragmentedMP4Parser::getFormat(bool audio, bool synchronous) { 254 255 while (true) { 256 bool moovDone = mDoneWithMoov; 257 sp<AMessage> msg = new AMessage(kWhatGetFormat, id()); 258 msg->setInt32("audio", audio); 259 260 sp<AMessage> response; 261 status_t err = msg->postAndAwaitResponse(&response); 262 263 if (err != OK) { 264 ALOGV("getFormat post failed: %d", err); 265 return NULL; 266 } 267 268 if (response->findInt32("err", &err) && err != OK) { 269 if (synchronous && err == -EWOULDBLOCK && !moovDone) { 270 resumeIfNecessary(); 271 ALOGV("@getFormat parser not ready yet, retrying"); 272 usleep(10000); 273 continue; 274 } 275 ALOGV("getFormat failed: %d", err); 276 return NULL; 277 } 278 279 sp<AMessage> format; 280 CHECK(response->findMessage("format", &format)); 281 282 ALOGV("returning format %s", format->debugString().c_str()); 283 return format; 284 } 285} 286 287status_t FragmentedMP4Parser::seekTo(bool wantAudio, int64_t timeUs) { 288 sp<AMessage> msg = new AMessage(kWhatSeekTo, id()); 289 msg->setInt32("audio", wantAudio); 290 msg->setInt64("position", timeUs); 291 292 sp<AMessage> response; 293 status_t err = msg->postAndAwaitResponse(&response); 294 return err; 295} 296 297bool FragmentedMP4Parser::isSeekable() const { 298 while (mFirstMoofOffset == 0 && mFinalResult == OK) { 299 usleep(10000); 300 } 301 bool seekable = mSource->isSeekable(); 302 for (size_t i = 0; seekable && i < mTracks.size(); i++) { 303 const TrackInfo *info = &mTracks.valueAt(i); 304 seekable &= !info->mSidx.empty(); 305 } 306 return seekable; 307} 308 309status_t FragmentedMP4Parser::onSeekTo(bool wantAudio, int64_t position) { 310 status_t err = -EINVAL; 311 ssize_t trackIndex = findTrack(wantAudio); 312 if (trackIndex < 0) { 313 err = trackIndex; 314 } else { 315 TrackInfo *info = &mTracks.editValueAt(trackIndex); 316 317 int numSidxEntries = info->mSidx.size(); 318 int64_t totalTime = 0; 319 off_t totalOffset = mFirstMoofOffset; 320 for (int i = 0; i < numSidxEntries; i++) { 321 const SidxEntry *se = &info->mSidx[i]; 322 totalTime += se->mDurationUs; 323 if (totalTime > position) { 324 mBuffer->setRange(0,0); 325 mBufferPos = totalOffset; 326 if (mFinalResult == ERROR_END_OF_STREAM) { 327 mFinalResult = OK; 328 mSuspended = true; // force resume 329 resumeIfNecessary(); 330 } 331 info->mFragments.clear(); 332 info->mDecodingTime = position * info->mMediaTimeScale / 1000000ll; 333 return OK; 334 } 335 totalOffset += se->mSize; 336 } 337 } 338 ALOGV("seekTo out of range"); 339 return err; 340} 341 342status_t FragmentedMP4Parser::dequeueAccessUnit(bool audio, sp<ABuffer> *accessUnit, 343 bool synchronous) { 344 345 while (true) { 346 sp<AMessage> msg = new AMessage(kWhatDequeueAccessUnit, id()); 347 msg->setInt32("audio", audio); 348 349 sp<AMessage> response; 350 status_t err = msg->postAndAwaitResponse(&response); 351 352 if (err != OK) { 353 ALOGV("dequeue fail 1: %d", err); 354 return err; 355 } 356 357 if (response->findInt32("err", &err) && err != OK) { 358 if (synchronous && err == -EWOULDBLOCK) { 359 resumeIfNecessary(); 360 ALOGV("Parser not ready yet, retrying"); 361 usleep(10000); 362 continue; 363 } 364 ALOGV("dequeue fail 2: %d, %d", err, synchronous); 365 return err; 366 } 367 368 CHECK(response->findBuffer("accessUnit", accessUnit)); 369 370 return OK; 371 } 372} 373 374ssize_t FragmentedMP4Parser::findTrack(bool wantAudio) const { 375 for (size_t i = 0; i < mTracks.size(); ++i) { 376 const TrackInfo *info = &mTracks.valueAt(i); 377 378 bool isAudio = 379 info->mMediaHandlerType == FOURCC('s', 'o', 'u', 'n'); 380 381 bool isVideo = 382 info->mMediaHandlerType == FOURCC('v', 'i', 'd', 'e'); 383 384 if ((wantAudio && isAudio) || (!wantAudio && !isAudio)) { 385 if (info->mSampleDescs.empty()) { 386 break; 387 } 388 389 return i; 390 } 391 } 392 393 return -EWOULDBLOCK; 394} 395 396void FragmentedMP4Parser::onMessageReceived(const sp<AMessage> &msg) { 397 switch (msg->what()) { 398 case kWhatStart: 399 { 400 sp<RefBase> obj; 401 CHECK(msg->findObject("source", &obj)); 402 403 mSource = static_cast<Source *>(obj.get()); 404 405 mBuffer = new ABuffer(512 * 1024); 406 mBuffer->setRange(0, 0); 407 408 enter(0ll, 0, 0); 409 410 (new AMessage(kWhatProceed, id()))->post(); 411 break; 412 } 413 414 case kWhatProceed: 415 { 416 CHECK(!mSuspended); 417 418 status_t err = onProceed(); 419 420 if (err == OK) { 421 if (!mSuspended) { 422 msg->post(); 423 } 424 } else if (err != -EAGAIN) { 425 ALOGE("onProceed returned error %d", err); 426 } 427 428 break; 429 } 430 431 case kWhatReadMore: 432 { 433 size_t needed; 434 CHECK(msg->findSize("needed", &needed)); 435 436 memmove(mBuffer->base(), mBuffer->data(), mBuffer->size()); 437 mBufferPos += mBuffer->offset(); 438 mBuffer->setRange(0, mBuffer->size()); 439 440 size_t maxBytesToRead = mBuffer->capacity() - mBuffer->size(); 441 442 if (maxBytesToRead < needed) { 443 ALOGV("resizing buffer."); 444 445 sp<ABuffer> newBuffer = 446 new ABuffer((mBuffer->size() + needed + 1023) & ~1023); 447 memcpy(newBuffer->data(), mBuffer->data(), mBuffer->size()); 448 newBuffer->setRange(0, mBuffer->size()); 449 450 mBuffer = newBuffer; 451 maxBytesToRead = mBuffer->capacity() - mBuffer->size(); 452 } 453 454 CHECK_GE(maxBytesToRead, needed); 455 456 ssize_t n = mSource->readAt( 457 mBufferPos + mBuffer->size(), 458 mBuffer->data() + mBuffer->size(), needed); 459 460 if (n < (ssize_t)needed) { 461 ALOGV("Reached EOF when reading %d @ %d + %d", needed, mBufferPos, mBuffer->size()); 462 if (n < 0) { 463 mFinalResult = n; 464 } else if (n == 0) { 465 mFinalResult = ERROR_END_OF_STREAM; 466 } else { 467 mFinalResult = ERROR_IO; 468 } 469 } else { 470 mBuffer->setRange(0, mBuffer->size() + n); 471 (new AMessage(kWhatProceed, id()))->post(); 472 } 473 474 break; 475 } 476 477 case kWhatGetFormat: 478 { 479 int32_t wantAudio; 480 CHECK(msg->findInt32("audio", &wantAudio)); 481 482 status_t err = -EWOULDBLOCK; 483 sp<AMessage> response = new AMessage; 484 485 ssize_t trackIndex = findTrack(wantAudio); 486 487 if (trackIndex < 0) { 488 err = trackIndex; 489 } else { 490 TrackInfo *info = &mTracks.editValueAt(trackIndex); 491 492 sp<AMessage> format = info->mSampleDescs.itemAt(0).mFormat; 493 if (info->mSidxDuration) { 494 format->setInt64("durationUs", info->mSidxDuration); 495 } else { 496 // this is probably going to be zero. Oh well... 497 format->setInt64("durationUs", 498 1000000ll * info->mDuration / info->mMediaTimeScale); 499 } 500 response->setMessage( 501 "format", format); 502 503 err = OK; 504 } 505 506 response->setInt32("err", err); 507 508 uint32_t replyID; 509 CHECK(msg->senderAwaitsResponse(&replyID)); 510 511 response->postReply(replyID); 512 break; 513 } 514 515 case kWhatDequeueAccessUnit: 516 { 517 int32_t wantAudio; 518 CHECK(msg->findInt32("audio", &wantAudio)); 519 520 status_t err = -EWOULDBLOCK; 521 sp<AMessage> response = new AMessage; 522 523 ssize_t trackIndex = findTrack(wantAudio); 524 525 if (trackIndex < 0) { 526 err = trackIndex; 527 } else { 528 sp<ABuffer> accessUnit; 529 err = onDequeueAccessUnit(trackIndex, &accessUnit); 530 531 if (err == OK) { 532 response->setBuffer("accessUnit", accessUnit); 533 } 534 } 535 536 response->setInt32("err", err); 537 538 uint32_t replyID; 539 CHECK(msg->senderAwaitsResponse(&replyID)); 540 541 response->postReply(replyID); 542 break; 543 } 544 545 case kWhatSeekTo: 546 { 547 ALOGV("kWhatSeekTo"); 548 int32_t wantAudio; 549 CHECK(msg->findInt32("audio", &wantAudio)); 550 int64_t position; 551 CHECK(msg->findInt64("position", &position)); 552 553 status_t err = -EWOULDBLOCK; 554 sp<AMessage> response = new AMessage; 555 556 ssize_t trackIndex = findTrack(wantAudio); 557 558 if (trackIndex < 0) { 559 err = trackIndex; 560 } else { 561 err = onSeekTo(wantAudio, position); 562 } 563 response->setInt32("err", err); 564 uint32_t replyID; 565 CHECK(msg->senderAwaitsResponse(&replyID)); 566 response->postReply(replyID); 567 break; 568 } 569 default: 570 TRESPASS(); 571 } 572} 573 574status_t FragmentedMP4Parser::onProceed() { 575 status_t err; 576 577 if ((err = need(8)) != OK) { 578 return err; 579 } 580 581 uint64_t size = readU32(0); 582 uint32_t type = readU32(4); 583 584 size_t offset = 8; 585 586 if (size == 1) { 587 if ((err = need(16)) != OK) { 588 return err; 589 } 590 591 size = readU64(offset); 592 offset += 8; 593 } 594 595 uint8_t userType[16]; 596 597 if (type == FOURCC('u', 'u', 'i', 'd')) { 598 if ((err = need(offset + 16)) != OK) { 599 return err; 600 } 601 602 memcpy(userType, mBuffer->data() + offset, 16); 603 offset += 16; 604 } 605 606 CHECK(!mStack.isEmpty()); 607 uint32_t ptype = mStack.itemAt(mStack.size() - 1).mType; 608 609 static const size_t kNumDispatchers = 610 sizeof(kDispatchTable) / sizeof(kDispatchTable[0]); 611 612 size_t i; 613 for (i = 0; i < kNumDispatchers; ++i) { 614 if (kDispatchTable[i].mType == type 615 && kDispatchTable[i].mParentType == ptype) { 616 break; 617 } 618 } 619 620 // SampleEntry boxes are container boxes that start with a variable 621 // amount of data depending on the media handler type. 622 // We don't look inside 'hint' type SampleEntry boxes. 623 624 bool isSampleEntryBox = 625 (ptype == FOURCC('s', 't', 's', 'd')) 626 && editTrack(mCurrentTrackID)->mMediaHandlerType 627 != FOURCC('h', 'i', 'n', 't'); 628 629 if ((i < kNumDispatchers && kDispatchTable[i].mHandler == 0) 630 || isSampleEntryBox || ptype == FOURCC('i', 'l', 's', 't')) { 631 // This is a container box. 632 if (type == FOURCC('m', 'o', 'o', 'f')) { 633 if (mFirstMoofOffset == 0) { 634 ALOGV("first moof @ %08x", mBufferPos + offset); 635 mFirstMoofOffset = mBufferPos + offset - 8; // point at the size 636 } 637 } 638 if (type == FOURCC('m', 'e', 't', 'a')) { 639 if ((err = need(offset + 4)) < OK) { 640 return err; 641 } 642 643 if (readU32(offset) != 0) { 644 return -EINVAL; 645 } 646 647 offset += 4; 648 } else if (type == FOURCC('s', 't', 's', 'd')) { 649 if ((err = need(offset + 8)) < OK) { 650 return err; 651 } 652 653 if (readU32(offset) != 0) { 654 return -EINVAL; 655 } 656 657 if (readU32(offset + 4) == 0) { 658 // We need at least some entries. 659 return -EINVAL; 660 } 661 662 offset += 8; 663 } else if (isSampleEntryBox) { 664 size_t headerSize; 665 666 switch (editTrack(mCurrentTrackID)->mMediaHandlerType) { 667 case FOURCC('v', 'i', 'd', 'e'): 668 { 669 // 8 bytes SampleEntry + 70 bytes VisualSampleEntry 670 headerSize = 78; 671 break; 672 } 673 674 case FOURCC('s', 'o', 'u', 'n'): 675 { 676 // 8 bytes SampleEntry + 20 bytes AudioSampleEntry 677 headerSize = 28; 678 break; 679 } 680 681 case FOURCC('m', 'e', 't', 'a'): 682 { 683 headerSize = 8; // 8 bytes SampleEntry 684 break; 685 } 686 687 default: 688 TRESPASS(); 689 } 690 691 if (offset + headerSize > size) { 692 return -EINVAL; 693 } 694 695 if ((err = need(offset + headerSize)) != OK) { 696 return err; 697 } 698 699 switch (editTrack(mCurrentTrackID)->mMediaHandlerType) { 700 case FOURCC('v', 'i', 'd', 'e'): 701 { 702 err = parseVisualSampleEntry( 703 type, offset, offset + headerSize); 704 break; 705 } 706 707 case FOURCC('s', 'o', 'u', 'n'): 708 { 709 err = parseAudioSampleEntry( 710 type, offset, offset + headerSize); 711 break; 712 } 713 714 case FOURCC('m', 'e', 't', 'a'): 715 { 716 err = OK; 717 break; 718 } 719 720 default: 721 TRESPASS(); 722 } 723 724 if (err != OK) { 725 return err; 726 } 727 728 offset += headerSize; 729 } 730 731 skip(offset); 732 733 ALOGV("%sentering box of type '%s'", 734 IndentString(mStack.size()), Fourcc2String(type)); 735 736 enter(mBufferPos - offset, type, size - offset); 737 } else { 738 if (!fitsContainer(size)) { 739 return -EINVAL; 740 } 741 742 if (i < kNumDispatchers && kDispatchTable[i].mHandler != 0) { 743 // We have a handler for this box type. 744 745 if ((err = need(size)) != OK) { 746 return err; 747 } 748 749 ALOGV("%sparsing box of type '%s'", 750 IndentString(mStack.size()), Fourcc2String(type)); 751 752 if ((err = (this->*kDispatchTable[i].mHandler)( 753 type, offset, size)) != OK) { 754 return err; 755 } 756 } else { 757 // Unknown box type 758 759 ALOGV("%sskipping box of type '%s', size %llu", 760 IndentString(mStack.size()), 761 Fourcc2String(type), size); 762 763 } 764 765 skip(size); 766 } 767 768 return OK; 769} 770 771// static 772int FragmentedMP4Parser::CompareSampleLocation( 773 const SampleInfo &sample, const MediaDataInfo &mdatInfo) { 774 if (sample.mOffset + sample.mSize < mdatInfo.mOffset) { 775 return -1; 776 } 777 778 if (sample.mOffset >= mdatInfo.mOffset + mdatInfo.mBuffer->size()) { 779 return 1; 780 } 781 782 // Otherwise make sure the sample is completely contained within this 783 // media data block. 784 785 CHECK_GE(sample.mOffset, mdatInfo.mOffset); 786 787 CHECK_LE(sample.mOffset + sample.mSize, 788 mdatInfo.mOffset + mdatInfo.mBuffer->size()); 789 790 return 0; 791} 792 793void FragmentedMP4Parser::resumeIfNecessary() { 794 if (!mSuspended) { 795 return; 796 } 797 798 ALOGV("resuming."); 799 800 mSuspended = false; 801 (new AMessage(kWhatProceed, id()))->post(); 802} 803 804status_t FragmentedMP4Parser::getSample( 805 TrackInfo *info, sp<TrackFragment> *fragment, SampleInfo *sampleInfo) { 806 for (;;) { 807 if (info->mFragments.empty()) { 808 if (mFinalResult != OK) { 809 return mFinalResult; 810 } 811 812 resumeIfNecessary(); 813 return -EWOULDBLOCK; 814 } 815 816 *fragment = *info->mFragments.begin(); 817 818 status_t err = (*fragment)->getSample(sampleInfo); 819 820 if (err == OK) { 821 return OK; 822 } else if (err != ERROR_END_OF_STREAM) { 823 return err; 824 } 825 826 // Really, end of this fragment... 827 828 info->mFragments.erase(info->mFragments.begin()); 829 } 830} 831 832status_t FragmentedMP4Parser::onDequeueAccessUnit( 833 size_t trackIndex, sp<ABuffer> *accessUnit) { 834 TrackInfo *info = &mTracks.editValueAt(trackIndex); 835 836 sp<TrackFragment> fragment; 837 SampleInfo sampleInfo; 838 status_t err = getSample(info, &fragment, &sampleInfo); 839 840 if (err == -EWOULDBLOCK) { 841 resumeIfNecessary(); 842 return err; 843 } else if (err != OK) { 844 return err; 845 } 846 847 err = -EWOULDBLOCK; 848 849 bool checkDroppable = false; 850 851 for (size_t i = 0; i < mMediaData.size(); ++i) { 852 const MediaDataInfo &mdatInfo = mMediaData.itemAt(i); 853 854 int cmp = CompareSampleLocation(sampleInfo, mdatInfo); 855 856 if (cmp < 0 && !mSource->isSeekable()) { 857 return -EPIPE; 858 } else if (cmp == 0) { 859 if (i > 0) { 860 checkDroppable = true; 861 } 862 863 err = makeAccessUnit(info, sampleInfo, mdatInfo, accessUnit); 864 break; 865 } 866 } 867 868 if (err != OK) { 869 return err; 870 } 871 872 fragment->advance(); 873 874 if (!mMediaData.empty() && checkDroppable) { 875 size_t numDroppable = 0; 876 bool done = false; 877 878 // XXX FIXME: if one of the tracks is not advanced (e.g. if you play an audio+video 879 // file with sf2), then mMediaData will not be pruned and keeps growing 880 for (size_t i = 0; !done && i < mMediaData.size(); ++i) { 881 const MediaDataInfo &mdatInfo = mMediaData.itemAt(i); 882 883 for (size_t j = 0; j < mTracks.size(); ++j) { 884 TrackInfo *info = &mTracks.editValueAt(j); 885 886 sp<TrackFragment> fragment; 887 SampleInfo sampleInfo; 888 err = getSample(info, &fragment, &sampleInfo); 889 890 if (err != OK) { 891 done = true; 892 break; 893 } 894 895 int cmp = CompareSampleLocation(sampleInfo, mdatInfo); 896 897 if (cmp <= 0) { 898 done = true; 899 break; 900 } 901 } 902 903 if (!done) { 904 ++numDroppable; 905 } 906 } 907 908 if (numDroppable > 0) { 909 mMediaData.removeItemsAt(0, numDroppable); 910 911 if (mMediaData.size() < 5) { 912 resumeIfNecessary(); 913 } 914 } 915 } 916 917 return err; 918} 919 920static size_t parseNALSize(size_t nalLengthSize, const uint8_t *data) { 921 switch (nalLengthSize) { 922 case 1: 923 return *data; 924 case 2: 925 return U16_AT(data); 926 case 3: 927 return ((size_t)data[0] << 16) | U16_AT(&data[1]); 928 case 4: 929 return U32_AT(data); 930 } 931 932 // This cannot happen, mNALLengthSize springs to life by adding 1 to 933 // a 2-bit integer. 934 TRESPASS(); 935 936 return 0; 937} 938 939status_t FragmentedMP4Parser::makeAccessUnit( 940 TrackInfo *info, 941 const SampleInfo &sample, 942 const MediaDataInfo &mdatInfo, 943 sp<ABuffer> *accessUnit) { 944 if (sample.mSampleDescIndex < 1 945 || sample.mSampleDescIndex > info->mSampleDescs.size()) { 946 return ERROR_MALFORMED; 947 } 948 949 int64_t presentationTimeUs = 950 1000000ll * sample.mPresentationTime / info->mMediaTimeScale; 951 952 const SampleDescription &sampleDesc = 953 info->mSampleDescs.itemAt(sample.mSampleDescIndex - 1); 954 955 size_t nalLengthSize; 956 if (!sampleDesc.mFormat->findSize("nal-length-size", &nalLengthSize)) { 957 *accessUnit = new ABuffer(sample.mSize); 958 959 memcpy((*accessUnit)->data(), 960 mdatInfo.mBuffer->data() + (sample.mOffset - mdatInfo.mOffset), 961 sample.mSize); 962 963 (*accessUnit)->meta()->setInt64("timeUs", presentationTimeUs); 964 return OK; 965 } 966 967 const uint8_t *srcPtr = 968 mdatInfo.mBuffer->data() + (sample.mOffset - mdatInfo.mOffset); 969 970 for (int i = 0; i < 2 ; ++i) { 971 size_t srcOffset = 0; 972 size_t dstOffset = 0; 973 974 while (srcOffset < sample.mSize) { 975 if (srcOffset + nalLengthSize > sample.mSize) { 976 return ERROR_MALFORMED; 977 } 978 979 size_t nalSize = parseNALSize(nalLengthSize, &srcPtr[srcOffset]); 980 srcOffset += nalLengthSize; 981 982 if (srcOffset + nalSize > sample.mSize) { 983 return ERROR_MALFORMED; 984 } 985 986 if (i == 1) { 987 memcpy((*accessUnit)->data() + dstOffset, 988 "\x00\x00\x00\x01", 989 4); 990 991 memcpy((*accessUnit)->data() + dstOffset + 4, 992 srcPtr + srcOffset, 993 nalSize); 994 } 995 996 srcOffset += nalSize; 997 dstOffset += nalSize + 4; 998 } 999 1000 if (i == 0) { 1001 (*accessUnit) = new ABuffer(dstOffset); 1002 (*accessUnit)->meta()->setInt64( 1003 "timeUs", presentationTimeUs); 1004 } 1005 } 1006 1007 return OK; 1008} 1009 1010status_t FragmentedMP4Parser::need(size_t size) { 1011 if (!fitsContainer(size)) { 1012 return -EINVAL; 1013 } 1014 1015 if (size <= mBuffer->size()) { 1016 return OK; 1017 } 1018 1019 sp<AMessage> msg = new AMessage(kWhatReadMore, id()); 1020 msg->setSize("needed", size - mBuffer->size()); 1021 msg->post(); 1022 1023 // ALOGV("need(%d) returning -EAGAIN, only have %d", size, mBuffer->size()); 1024 1025 return -EAGAIN; 1026} 1027 1028void FragmentedMP4Parser::enter(off64_t offset, uint32_t type, uint64_t size) { 1029 Container container; 1030 container.mOffset = offset; 1031 container.mType = type; 1032 container.mExtendsToEOF = (size == 0); 1033 container.mBytesRemaining = size; 1034 1035 mStack.push(container); 1036} 1037 1038bool FragmentedMP4Parser::fitsContainer(uint64_t size) const { 1039 CHECK(!mStack.isEmpty()); 1040 const Container &container = mStack.itemAt(mStack.size() - 1); 1041 1042 return container.mExtendsToEOF || size <= container.mBytesRemaining; 1043} 1044 1045uint16_t FragmentedMP4Parser::readU16(size_t offset) { 1046 CHECK_LE(offset + 2, mBuffer->size()); 1047 1048 const uint8_t *ptr = mBuffer->data() + offset; 1049 return (ptr[0] << 8) | ptr[1]; 1050} 1051 1052uint32_t FragmentedMP4Parser::readU32(size_t offset) { 1053 CHECK_LE(offset + 4, mBuffer->size()); 1054 1055 const uint8_t *ptr = mBuffer->data() + offset; 1056 return (ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | ptr[3]; 1057} 1058 1059uint64_t FragmentedMP4Parser::readU64(size_t offset) { 1060 return (((uint64_t)readU32(offset)) << 32) | readU32(offset + 4); 1061} 1062 1063void FragmentedMP4Parser::skip(off_t distance) { 1064 CHECK(!mStack.isEmpty()); 1065 for (size_t i = mStack.size(); i-- > 0;) { 1066 Container *container = &mStack.editItemAt(i); 1067 if (!container->mExtendsToEOF) { 1068 CHECK_LE(distance, (off_t)container->mBytesRemaining); 1069 1070 container->mBytesRemaining -= distance; 1071 1072 if (container->mBytesRemaining == 0) { 1073 ALOGV("%sleaving box of type '%s'", 1074 IndentString(mStack.size() - 1), 1075 Fourcc2String(container->mType)); 1076 1077#if 0 1078 if (container->mType == FOURCC('s', 't', 's', 'd')) { 1079 TrackInfo *trackInfo = editTrack(mCurrentTrackID); 1080 for (size_t i = 0; 1081 i < trackInfo->mSampleDescs.size(); ++i) { 1082 ALOGI("format #%d: %s", 1083 i, 1084 trackInfo->mSampleDescs.itemAt(i) 1085 .mFormat->debugString().c_str()); 1086 } 1087 } 1088#endif 1089 1090 if (container->mType == FOURCC('s', 't', 'b', 'l')) { 1091 TrackInfo *trackInfo = editTrack(mCurrentTrackID); 1092 1093 trackInfo->mStaticFragment->signalCompletion(); 1094 1095 CHECK(trackInfo->mFragments.empty()); 1096 trackInfo->mFragments.push_back(trackInfo->mStaticFragment); 1097 trackInfo->mStaticFragment.clear(); 1098 } else if (container->mType == FOURCC('t', 'r', 'a', 'f')) { 1099 TrackInfo *trackInfo = 1100 editTrack(mTrackFragmentHeaderInfo.mTrackID); 1101 1102 const sp<TrackFragment> &fragment = 1103 *--trackInfo->mFragments.end(); 1104 1105 static_cast<DynamicTrackFragment *>( 1106 fragment.get())->signalCompletion(); 1107 } else if (container->mType == FOURCC('m', 'o', 'o', 'v')) { 1108 mDoneWithMoov = true; 1109 } 1110 1111 container = NULL; 1112 mStack.removeItemsAt(i); 1113 } 1114 } 1115 } 1116 1117 if (distance < (off_t)mBuffer->size()) { 1118 mBuffer->setRange(mBuffer->offset() + distance, mBuffer->size() - distance); 1119 mBufferPos += distance; 1120 return; 1121 } 1122 1123 mBuffer->setRange(0, 0); 1124 mBufferPos += distance; 1125} 1126 1127status_t FragmentedMP4Parser::parseTrackHeader( 1128 uint32_t type, size_t offset, uint64_t size) { 1129 if (offset + 4 > size) { 1130 return -EINVAL; 1131 } 1132 1133 uint32_t flags = readU32(offset); 1134 1135 uint32_t version = flags >> 24; 1136 flags &= 0xffffff; 1137 1138 uint32_t trackID; 1139 uint64_t duration; 1140 1141 if (version == 1) { 1142 if (offset + 36 > size) { 1143 return -EINVAL; 1144 } 1145 1146 trackID = readU32(offset + 20); 1147 duration = readU64(offset + 28); 1148 1149 offset += 36; 1150 } else if (version == 0) { 1151 if (offset + 24 > size) { 1152 return -EINVAL; 1153 } 1154 1155 trackID = readU32(offset + 12); 1156 duration = readU32(offset + 20); 1157 1158 offset += 24; 1159 } else { 1160 return -EINVAL; 1161 } 1162 1163 TrackInfo *info = editTrack(trackID, true /* createIfNecessary */); 1164 info->mFlags = flags; 1165 info->mDuration = duration; 1166 if (info->mDuration == 0xffffffff) { 1167 // ffmpeg sets this to -1, which is incorrect. 1168 info->mDuration = 0; 1169 } 1170 1171 info->mStaticFragment = new StaticTrackFragment; 1172 1173 mCurrentTrackID = trackID; 1174 1175 return OK; 1176} 1177 1178status_t FragmentedMP4Parser::parseMediaHeader( 1179 uint32_t type, size_t offset, uint64_t size) { 1180 if (offset + 4 > size) { 1181 return -EINVAL; 1182 } 1183 1184 uint32_t versionAndFlags = readU32(offset); 1185 1186 if (versionAndFlags & 0xffffff) { 1187 return ERROR_MALFORMED; 1188 } 1189 1190 uint32_t version = versionAndFlags >> 24; 1191 1192 TrackInfo *info = editTrack(mCurrentTrackID); 1193 1194 if (version == 1) { 1195 if (offset + 4 + 32 > size) { 1196 return -EINVAL; 1197 } 1198 info->mMediaTimeScale = U32_AT(mBuffer->data() + offset + 20); 1199 } else if (version == 0) { 1200 if (offset + 4 + 20 > size) { 1201 return -EINVAL; 1202 } 1203 info->mMediaTimeScale = U32_AT(mBuffer->data() + offset + 12); 1204 } else { 1205 return ERROR_MALFORMED; 1206 } 1207 1208 return OK; 1209} 1210 1211status_t FragmentedMP4Parser::parseMediaHandler( 1212 uint32_t type, size_t offset, uint64_t size) { 1213 if (offset + 12 > size) { 1214 return -EINVAL; 1215 } 1216 1217 if (readU32(offset) != 0) { 1218 return -EINVAL; 1219 } 1220 1221 uint32_t handlerType = readU32(offset + 8); 1222 1223 switch (handlerType) { 1224 case FOURCC('v', 'i', 'd', 'e'): 1225 case FOURCC('s', 'o', 'u', 'n'): 1226 case FOURCC('h', 'i', 'n', 't'): 1227 case FOURCC('m', 'e', 't', 'a'): 1228 break; 1229 1230 default: 1231 return -EINVAL; 1232 } 1233 1234 editTrack(mCurrentTrackID)->mMediaHandlerType = handlerType; 1235 1236 return OK; 1237} 1238 1239status_t FragmentedMP4Parser::parseVisualSampleEntry( 1240 uint32_t type, size_t offset, uint64_t size) { 1241 if (offset + 78 > size) { 1242 return -EINVAL; 1243 } 1244 1245 TrackInfo *trackInfo = editTrack(mCurrentTrackID); 1246 1247 trackInfo->mSampleDescs.push(); 1248 SampleDescription *sampleDesc = 1249 &trackInfo->mSampleDescs.editItemAt( 1250 trackInfo->mSampleDescs.size() - 1); 1251 1252 sampleDesc->mType = type; 1253 sampleDesc->mDataRefIndex = readU16(offset + 6); 1254 1255 sp<AMessage> format = new AMessage; 1256 1257 switch (type) { 1258 case FOURCC('a', 'v', 'c', '1'): 1259 format->setString("mime", MEDIA_MIMETYPE_VIDEO_AVC); 1260 break; 1261 case FOURCC('m', 'p', '4', 'v'): 1262 format->setString("mime", MEDIA_MIMETYPE_VIDEO_MPEG4); 1263 break; 1264 case FOURCC('s', '2', '6', '3'): 1265 case FOURCC('h', '2', '6', '3'): 1266 case FOURCC('H', '2', '6', '3'): 1267 format->setString("mime", MEDIA_MIMETYPE_VIDEO_H263); 1268 break; 1269 default: 1270 format->setString("mime", "application/octet-stream"); 1271 break; 1272 } 1273 1274 format->setInt32("width", readU16(offset + 8 + 16)); 1275 format->setInt32("height", readU16(offset + 8 + 18)); 1276 1277 sampleDesc->mFormat = format; 1278 1279 return OK; 1280} 1281 1282status_t FragmentedMP4Parser::parseAudioSampleEntry( 1283 uint32_t type, size_t offset, uint64_t size) { 1284 if (offset + 28 > size) { 1285 return -EINVAL; 1286 } 1287 1288 TrackInfo *trackInfo = editTrack(mCurrentTrackID); 1289 1290 trackInfo->mSampleDescs.push(); 1291 SampleDescription *sampleDesc = 1292 &trackInfo->mSampleDescs.editItemAt( 1293 trackInfo->mSampleDescs.size() - 1); 1294 1295 sampleDesc->mType = type; 1296 sampleDesc->mDataRefIndex = readU16(offset + 6); 1297 1298 sp<AMessage> format = new AMessage; 1299 1300 format->setInt32("channel-count", readU16(offset + 8 + 8)); 1301 format->setInt32("sample-size", readU16(offset + 8 + 10)); 1302 format->setInt32("sample-rate", readU32(offset + 8 + 16) / 65536.0f); 1303 1304 switch (type) { 1305 case FOURCC('m', 'p', '4', 'a'): 1306 format->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC); 1307 break; 1308 1309 case FOURCC('s', 'a', 'm', 'r'): 1310 format->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_NB); 1311 format->setInt32("channel-count", 1); 1312 format->setInt32("sample-rate", 8000); 1313 break; 1314 1315 case FOURCC('s', 'a', 'w', 'b'): 1316 format->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_WB); 1317 format->setInt32("channel-count", 1); 1318 format->setInt32("sample-rate", 16000); 1319 break; 1320 default: 1321 format->setString("mime", "application/octet-stream"); 1322 break; 1323 } 1324 1325 sampleDesc->mFormat = format; 1326 1327 return OK; 1328} 1329 1330static void addCodecSpecificData( 1331 const sp<AMessage> &format, int32_t index, 1332 const void *data, size_t size, 1333 bool insertStartCode = false) { 1334 sp<ABuffer> csd = new ABuffer(insertStartCode ? size + 4 : size); 1335 1336 memcpy(csd->data() + (insertStartCode ? 4 : 0), data, size); 1337 1338 if (insertStartCode) { 1339 memcpy(csd->data(), "\x00\x00\x00\x01", 4); 1340 } 1341 1342 csd->meta()->setInt32("csd", true); 1343 csd->meta()->setInt64("timeUs", 0ll); 1344 1345 format->setBuffer(StringPrintf("csd-%d", index).c_str(), csd); 1346} 1347 1348status_t FragmentedMP4Parser::parseSampleSizes( 1349 uint32_t type, size_t offset, uint64_t size) { 1350 return editTrack(mCurrentTrackID)->mStaticFragment->parseSampleSizes( 1351 this, type, offset, size); 1352} 1353 1354status_t FragmentedMP4Parser::parseCompactSampleSizes( 1355 uint32_t type, size_t offset, uint64_t size) { 1356 return editTrack(mCurrentTrackID)->mStaticFragment->parseCompactSampleSizes( 1357 this, type, offset, size); 1358} 1359 1360status_t FragmentedMP4Parser::parseSampleToChunk( 1361 uint32_t type, size_t offset, uint64_t size) { 1362 return editTrack(mCurrentTrackID)->mStaticFragment->parseSampleToChunk( 1363 this, type, offset, size); 1364} 1365 1366status_t FragmentedMP4Parser::parseChunkOffsets( 1367 uint32_t type, size_t offset, uint64_t size) { 1368 return editTrack(mCurrentTrackID)->mStaticFragment->parseChunkOffsets( 1369 this, type, offset, size); 1370} 1371 1372status_t FragmentedMP4Parser::parseChunkOffsets64( 1373 uint32_t type, size_t offset, uint64_t size) { 1374 return editTrack(mCurrentTrackID)->mStaticFragment->parseChunkOffsets64( 1375 this, type, offset, size); 1376} 1377 1378status_t FragmentedMP4Parser::parseAVCCodecSpecificData( 1379 uint32_t type, size_t offset, uint64_t size) { 1380 TrackInfo *trackInfo = editTrack(mCurrentTrackID); 1381 1382 SampleDescription *sampleDesc = 1383 &trackInfo->mSampleDescs.editItemAt( 1384 trackInfo->mSampleDescs.size() - 1); 1385 1386 if (sampleDesc->mType != FOURCC('a', 'v', 'c', '1')) { 1387 return -EINVAL; 1388 } 1389 1390 const uint8_t *ptr = mBuffer->data() + offset; 1391 1392 size -= offset; 1393 offset = 0; 1394 1395 if (size < 7 || ptr[0] != 0x01) { 1396 return ERROR_MALFORMED; 1397 } 1398 1399 sampleDesc->mFormat->setSize("nal-length-size", 1 + (ptr[4] & 3)); 1400 1401 size_t numSPS = ptr[5] & 31; 1402 1403 ptr += 6; 1404 size -= 6; 1405 1406 for (size_t i = 0; i < numSPS; ++i) { 1407 if (size < 2) { 1408 return ERROR_MALFORMED; 1409 } 1410 1411 size_t length = U16_AT(ptr); 1412 1413 ptr += 2; 1414 size -= 2; 1415 1416 if (size < length) { 1417 return ERROR_MALFORMED; 1418 } 1419 1420 addCodecSpecificData( 1421 sampleDesc->mFormat, i, ptr, length, 1422 true /* insertStartCode */); 1423 1424 ptr += length; 1425 size -= length; 1426 } 1427 1428 if (size < 1) { 1429 return ERROR_MALFORMED; 1430 } 1431 1432 size_t numPPS = *ptr; 1433 ++ptr; 1434 --size; 1435 1436 for (size_t i = 0; i < numPPS; ++i) { 1437 if (size < 2) { 1438 return ERROR_MALFORMED; 1439 } 1440 1441 size_t length = U16_AT(ptr); 1442 1443 ptr += 2; 1444 size -= 2; 1445 1446 if (size < length) { 1447 return ERROR_MALFORMED; 1448 } 1449 1450 addCodecSpecificData( 1451 sampleDesc->mFormat, numSPS + i, ptr, length, 1452 true /* insertStartCode */); 1453 1454 ptr += length; 1455 size -= length; 1456 } 1457 1458 return OK; 1459} 1460 1461status_t FragmentedMP4Parser::parseESDSCodecSpecificData( 1462 uint32_t type, size_t offset, uint64_t size) { 1463 TrackInfo *trackInfo = editTrack(mCurrentTrackID); 1464 1465 SampleDescription *sampleDesc = 1466 &trackInfo->mSampleDescs.editItemAt( 1467 trackInfo->mSampleDescs.size() - 1); 1468 1469 if (sampleDesc->mType != FOURCC('m', 'p', '4', 'a') 1470 && sampleDesc->mType != FOURCC('m', 'p', '4', 'v')) { 1471 return -EINVAL; 1472 } 1473 1474 const uint8_t *ptr = mBuffer->data() + offset; 1475 1476 size -= offset; 1477 offset = 0; 1478 1479 if (size < 4) { 1480 return -EINVAL; 1481 } 1482 1483 if (U32_AT(ptr) != 0) { 1484 return -EINVAL; 1485 } 1486 1487 ptr += 4; 1488 size -=4; 1489 1490 ESDS esds(ptr, size); 1491 1492 uint8_t objectTypeIndication; 1493 if (esds.getObjectTypeIndication(&objectTypeIndication) != OK) { 1494 return ERROR_MALFORMED; 1495 } 1496 1497 const uint8_t *csd; 1498 size_t csd_size; 1499 if (esds.getCodecSpecificInfo( 1500 (const void **)&csd, &csd_size) != OK) { 1501 return ERROR_MALFORMED; 1502 } 1503 1504 addCodecSpecificData(sampleDesc->mFormat, 0, csd, csd_size); 1505 1506 if (sampleDesc->mType != FOURCC('m', 'p', '4', 'a')) { 1507 return OK; 1508 } 1509 1510 if (csd_size == 0) { 1511 // There's no further information, i.e. no codec specific data 1512 // Let's assume that the information provided in the mpeg4 headers 1513 // is accurate and hope for the best. 1514 1515 return OK; 1516 } 1517 1518 if (csd_size < 2) { 1519 return ERROR_MALFORMED; 1520 } 1521 1522 uint32_t objectType = csd[0] >> 3; 1523 1524 if (objectType == 31) { 1525 return ERROR_UNSUPPORTED; 1526 } 1527 1528 uint32_t freqIndex = (csd[0] & 7) << 1 | (csd[1] >> 7); 1529 int32_t sampleRate = 0; 1530 int32_t numChannels = 0; 1531 if (freqIndex == 15) { 1532 if (csd_size < 5) { 1533 return ERROR_MALFORMED; 1534 } 1535 1536 sampleRate = (csd[1] & 0x7f) << 17 1537 | csd[2] << 9 1538 | csd[3] << 1 1539 | (csd[4] >> 7); 1540 1541 numChannels = (csd[4] >> 3) & 15; 1542 } else { 1543 static uint32_t kSamplingRate[] = { 1544 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 1545 16000, 12000, 11025, 8000, 7350 1546 }; 1547 1548 if (freqIndex == 13 || freqIndex == 14) { 1549 return ERROR_MALFORMED; 1550 } 1551 1552 sampleRate = kSamplingRate[freqIndex]; 1553 numChannels = (csd[1] >> 3) & 15; 1554 } 1555 1556 if (numChannels == 0) { 1557 return ERROR_UNSUPPORTED; 1558 } 1559 1560 sampleDesc->mFormat->setInt32("sample-rate", sampleRate); 1561 sampleDesc->mFormat->setInt32("channel-count", numChannels); 1562 1563 return OK; 1564} 1565 1566status_t FragmentedMP4Parser::parseMediaData( 1567 uint32_t type, size_t offset, uint64_t size) { 1568 ALOGV("skipping 'mdat' chunk at offsets 0x%08lx-0x%08llx.", 1569 mBufferPos + offset, mBufferPos + size); 1570 1571 sp<ABuffer> buffer = new ABuffer(size - offset); 1572 memcpy(buffer->data(), mBuffer->data() + offset, size - offset); 1573 1574 mMediaData.push(); 1575 MediaDataInfo *info = &mMediaData.editItemAt(mMediaData.size() - 1); 1576 info->mBuffer = buffer; 1577 info->mOffset = mBufferPos + offset; 1578 1579 if (mMediaData.size() > 10) { 1580 ALOGV("suspending for now."); 1581 mSuspended = true; 1582 } 1583 1584 return OK; 1585} 1586 1587status_t FragmentedMP4Parser::parseSegmentIndex( 1588 uint32_t type, size_t offset, uint64_t size) { 1589 ALOGV("sidx box type %d, offset %d, size %d", type, int(offset), int(size)); 1590// AString sidxstr; 1591// hexdump(mBuffer->data() + offset, size, 0 /* indent */, &sidxstr); 1592// ALOGV("raw sidx:"); 1593// ALOGV("%s", sidxstr.c_str()); 1594 if (offset + 12 > size) { 1595 return -EINVAL; 1596 } 1597 1598 uint32_t flags = readU32(offset); 1599 1600 uint32_t version = flags >> 24; 1601 flags &= 0xffffff; 1602 1603 ALOGV("sidx version %d", version); 1604 1605 uint32_t referenceId = readU32(offset + 4); 1606 uint32_t timeScale = readU32(offset + 8); 1607 ALOGV("sidx refid/timescale: %d/%d", referenceId, timeScale); 1608 1609 uint64_t earliestPresentationTime; 1610 uint64_t firstOffset; 1611 1612 offset += 12; 1613 1614 if (version == 0) { 1615 if (offset + 8 > size) { 1616 return -EINVAL; 1617 } 1618 earliestPresentationTime = readU32(offset); 1619 firstOffset = readU32(offset + 4); 1620 offset += 8; 1621 } else { 1622 if (offset + 16 > size) { 1623 return -EINVAL; 1624 } 1625 earliestPresentationTime = readU64(offset); 1626 firstOffset = readU64(offset + 8); 1627 offset += 16; 1628 } 1629 ALOGV("sidx pres/off: %Ld/%Ld", earliestPresentationTime, firstOffset); 1630 1631 if (offset + 4 > size) { 1632 return -EINVAL; 1633 } 1634 if (readU16(offset) != 0) { // reserved 1635 return -EINVAL; 1636 } 1637 int32_t referenceCount = readU16(offset + 2); 1638 offset += 4; 1639 ALOGV("refcount: %d", referenceCount); 1640 1641 if (offset + referenceCount * 12 > size) { 1642 return -EINVAL; 1643 } 1644 1645 TrackInfo *info = editTrack(mCurrentTrackID); 1646 uint64_t total_duration = 0; 1647 for (int i = 0; i < referenceCount; i++) { 1648 uint32_t d1 = readU32(offset); 1649 uint32_t d2 = readU32(offset + 4); 1650 uint32_t d3 = readU32(offset + 8); 1651 1652 if (d1 & 0x80000000) { 1653 ALOGW("sub-sidx boxes not supported yet"); 1654 } 1655 bool sap = d3 & 0x80000000; 1656 bool saptype = d3 >> 28; 1657 if (!sap || saptype > 2) { 1658 ALOGW("not a stream access point, or unsupported type"); 1659 } 1660 total_duration += d2; 1661 offset += 12; 1662 ALOGV(" item %d, %08x %08x %08x", i, d1, d2, d3); 1663 SidxEntry se; 1664 se.mSize = d1 & 0x7fffffff; 1665 se.mDurationUs = 1000000LL * d2 / timeScale; 1666 info->mSidx.add(se); 1667 } 1668 1669 info->mSidxDuration = total_duration * 1000000 / timeScale; 1670 ALOGV("duration: %lld", info->mSidxDuration); 1671 return OK; 1672} 1673 1674status_t FragmentedMP4Parser::parseTrackExtends( 1675 uint32_t type, size_t offset, uint64_t size) { 1676 if (offset + 24 > size) { 1677 return -EINVAL; 1678 } 1679 1680 if (readU32(offset) != 0) { 1681 return -EINVAL; 1682 } 1683 1684 uint32_t trackID = readU32(offset + 4); 1685 1686 TrackInfo *info = editTrack(trackID, true /* createIfNecessary */); 1687 info->mDefaultSampleDescriptionIndex = readU32(offset + 8); 1688 info->mDefaultSampleDuration = readU32(offset + 12); 1689 info->mDefaultSampleSize = readU32(offset + 16); 1690 info->mDefaultSampleFlags = readU32(offset + 20); 1691 1692 return OK; 1693} 1694 1695FragmentedMP4Parser::TrackInfo *FragmentedMP4Parser::editTrack( 1696 uint32_t trackID, bool createIfNecessary) { 1697 ssize_t i = mTracks.indexOfKey(trackID); 1698 1699 if (i >= 0) { 1700 return &mTracks.editValueAt(i); 1701 } 1702 1703 if (!createIfNecessary) { 1704 return NULL; 1705 } 1706 1707 TrackInfo info; 1708 info.mTrackID = trackID; 1709 info.mFlags = 0; 1710 info.mDuration = 0xffffffff; 1711 info.mSidxDuration = 0; 1712 info.mMediaTimeScale = 0; 1713 info.mMediaHandlerType = 0; 1714 info.mDefaultSampleDescriptionIndex = 0; 1715 info.mDefaultSampleDuration = 0; 1716 info.mDefaultSampleSize = 0; 1717 info.mDefaultSampleFlags = 0; 1718 1719 info.mDecodingTime = 0; 1720 1721 mTracks.add(trackID, info); 1722 return &mTracks.editValueAt(mTracks.indexOfKey(trackID)); 1723} 1724 1725status_t FragmentedMP4Parser::parseTrackFragmentHeader( 1726 uint32_t type, size_t offset, uint64_t size) { 1727 if (offset + 8 > size) { 1728 return -EINVAL; 1729 } 1730 1731 uint32_t flags = readU32(offset); 1732 1733 if (flags & 0xff000000) { 1734 return -EINVAL; 1735 } 1736 1737 mTrackFragmentHeaderInfo.mFlags = flags; 1738 1739 mTrackFragmentHeaderInfo.mTrackID = readU32(offset + 4); 1740 offset += 8; 1741 1742 if (flags & TrackFragmentHeaderInfo::kBaseDataOffsetPresent) { 1743 if (offset + 8 > size) { 1744 return -EINVAL; 1745 } 1746 1747 mTrackFragmentHeaderInfo.mBaseDataOffset = readU64(offset); 1748 offset += 8; 1749 } 1750 1751 if (flags & TrackFragmentHeaderInfo::kSampleDescriptionIndexPresent) { 1752 if (offset + 4 > size) { 1753 return -EINVAL; 1754 } 1755 1756 mTrackFragmentHeaderInfo.mSampleDescriptionIndex = readU32(offset); 1757 offset += 4; 1758 } 1759 1760 if (flags & TrackFragmentHeaderInfo::kDefaultSampleDurationPresent) { 1761 if (offset + 4 > size) { 1762 return -EINVAL; 1763 } 1764 1765 mTrackFragmentHeaderInfo.mDefaultSampleDuration = readU32(offset); 1766 offset += 4; 1767 } 1768 1769 if (flags & TrackFragmentHeaderInfo::kDefaultSampleSizePresent) { 1770 if (offset + 4 > size) { 1771 return -EINVAL; 1772 } 1773 1774 mTrackFragmentHeaderInfo.mDefaultSampleSize = readU32(offset); 1775 offset += 4; 1776 } 1777 1778 if (flags & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent) { 1779 if (offset + 4 > size) { 1780 return -EINVAL; 1781 } 1782 1783 mTrackFragmentHeaderInfo.mDefaultSampleFlags = readU32(offset); 1784 offset += 4; 1785 } 1786 1787 if (!(flags & TrackFragmentHeaderInfo::kBaseDataOffsetPresent)) { 1788 // This should point to the position of the first byte of the 1789 // enclosing 'moof' container for the first track and 1790 // the end of the data of the preceding fragment for subsequent 1791 // tracks. 1792 1793 CHECK_GE(mStack.size(), 2u); 1794 1795 mTrackFragmentHeaderInfo.mBaseDataOffset = 1796 mStack.itemAt(mStack.size() - 2).mOffset; 1797 1798 // XXX TODO: This does not do the right thing for the 2nd and 1799 // subsequent tracks yet. 1800 } 1801 1802 mTrackFragmentHeaderInfo.mDataOffset = 1803 mTrackFragmentHeaderInfo.mBaseDataOffset; 1804 1805 TrackInfo *trackInfo = editTrack(mTrackFragmentHeaderInfo.mTrackID); 1806 1807 if (trackInfo->mFragments.empty() 1808 || (*trackInfo->mFragments.begin())->complete()) { 1809 trackInfo->mFragments.push_back(new DynamicTrackFragment); 1810 } 1811 1812 return OK; 1813} 1814 1815status_t FragmentedMP4Parser::parseTrackFragmentRun( 1816 uint32_t type, size_t offset, uint64_t size) { 1817 if (offset + 8 > size) { 1818 return -EINVAL; 1819 } 1820 1821 enum { 1822 kDataOffsetPresent = 0x01, 1823 kFirstSampleFlagsPresent = 0x04, 1824 kSampleDurationPresent = 0x100, 1825 kSampleSizePresent = 0x200, 1826 kSampleFlagsPresent = 0x400, 1827 kSampleCompositionTimeOffsetPresent = 0x800, 1828 }; 1829 1830 uint32_t flags = readU32(offset); 1831 1832 if (flags & 0xff000000) { 1833 return -EINVAL; 1834 } 1835 1836 if ((flags & kFirstSampleFlagsPresent) && (flags & kSampleFlagsPresent)) { 1837 // These two shall not be used together. 1838 return -EINVAL; 1839 } 1840 1841 uint32_t sampleCount = readU32(offset + 4); 1842 offset += 8; 1843 1844 uint64_t dataOffset = mTrackFragmentHeaderInfo.mDataOffset; 1845 1846 uint32_t firstSampleFlags = 0; 1847 1848 if (flags & kDataOffsetPresent) { 1849 if (offset + 4 > size) { 1850 return -EINVAL; 1851 } 1852 1853 int32_t dataOffsetDelta = (int32_t)readU32(offset); 1854 1855 dataOffset = mTrackFragmentHeaderInfo.mBaseDataOffset + dataOffsetDelta; 1856 1857 offset += 4; 1858 } 1859 1860 if (flags & kFirstSampleFlagsPresent) { 1861 if (offset + 4 > size) { 1862 return -EINVAL; 1863 } 1864 1865 firstSampleFlags = readU32(offset); 1866 offset += 4; 1867 } 1868 1869 TrackInfo *info = editTrack(mTrackFragmentHeaderInfo.mTrackID); 1870 1871 if (info == NULL) { 1872 return -EINVAL; 1873 } 1874 1875 uint32_t sampleDuration = 0, sampleSize = 0, sampleFlags = 0, 1876 sampleCtsOffset = 0; 1877 1878 size_t bytesPerSample = 0; 1879 if (flags & kSampleDurationPresent) { 1880 bytesPerSample += 4; 1881 } else if (mTrackFragmentHeaderInfo.mFlags 1882 & TrackFragmentHeaderInfo::kDefaultSampleDurationPresent) { 1883 sampleDuration = mTrackFragmentHeaderInfo.mDefaultSampleDuration; 1884 } else { 1885 sampleDuration = info->mDefaultSampleDuration; 1886 } 1887 1888 if (flags & kSampleSizePresent) { 1889 bytesPerSample += 4; 1890 } else if (mTrackFragmentHeaderInfo.mFlags 1891 & TrackFragmentHeaderInfo::kDefaultSampleSizePresent) { 1892 sampleSize = mTrackFragmentHeaderInfo.mDefaultSampleSize; 1893 } else { 1894 sampleSize = info->mDefaultSampleSize; 1895 } 1896 1897 if (flags & kSampleFlagsPresent) { 1898 bytesPerSample += 4; 1899 } else if (mTrackFragmentHeaderInfo.mFlags 1900 & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent) { 1901 sampleFlags = mTrackFragmentHeaderInfo.mDefaultSampleFlags; 1902 } else { 1903 sampleFlags = info->mDefaultSampleFlags; 1904 } 1905 1906 if (flags & kSampleCompositionTimeOffsetPresent) { 1907 bytesPerSample += 4; 1908 } else { 1909 sampleCtsOffset = 0; 1910 } 1911 1912 if (offset + sampleCount * bytesPerSample > size) { 1913 return -EINVAL; 1914 } 1915 1916 uint32_t sampleDescIndex = 1917 (mTrackFragmentHeaderInfo.mFlags 1918 & TrackFragmentHeaderInfo::kSampleDescriptionIndexPresent) 1919 ? mTrackFragmentHeaderInfo.mSampleDescriptionIndex 1920 : info->mDefaultSampleDescriptionIndex; 1921 1922 for (uint32_t i = 0; i < sampleCount; ++i) { 1923 if (flags & kSampleDurationPresent) { 1924 sampleDuration = readU32(offset); 1925 offset += 4; 1926 } 1927 1928 if (flags & kSampleSizePresent) { 1929 sampleSize = readU32(offset); 1930 offset += 4; 1931 } 1932 1933 if (flags & kSampleFlagsPresent) { 1934 sampleFlags = readU32(offset); 1935 offset += 4; 1936 } 1937 1938 if (flags & kSampleCompositionTimeOffsetPresent) { 1939 sampleCtsOffset = readU32(offset); 1940 offset += 4; 1941 } 1942 1943 ALOGV("adding sample at offset 0x%08llx, size %u, duration %u, " 1944 "sampleDescIndex=%u, flags 0x%08x", 1945 dataOffset, sampleSize, sampleDuration, 1946 sampleDescIndex, 1947 (flags & kFirstSampleFlagsPresent) && i == 0 1948 ? firstSampleFlags : sampleFlags); 1949 1950 const sp<TrackFragment> &fragment = *--info->mFragments.end(); 1951 1952 uint32_t decodingTime = info->mDecodingTime; 1953 info->mDecodingTime += sampleDuration; 1954 uint32_t presentationTime = decodingTime + sampleCtsOffset; 1955 1956 static_cast<DynamicTrackFragment *>( 1957 fragment.get())->addSample( 1958 dataOffset, 1959 sampleSize, 1960 presentationTime, 1961 sampleDescIndex, 1962 ((flags & kFirstSampleFlagsPresent) && i == 0) 1963 ? firstSampleFlags : sampleFlags); 1964 1965 dataOffset += sampleSize; 1966 } 1967 1968 mTrackFragmentHeaderInfo.mDataOffset = dataOffset; 1969 1970 return OK; 1971} 1972 1973void FragmentedMP4Parser::copyBuffer( 1974 sp<ABuffer> *dst, size_t offset, uint64_t size, size_t extra) const { 1975 sp<ABuffer> buf = new ABuffer(size + extra); 1976 memcpy(buf->data(), mBuffer->data() + offset, size); 1977 1978 *dst = buf; 1979} 1980 1981} // namespace android 1982