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_NDEBUG 0 18 #define LOG_TAG "MPEG4Writer" 19 #include <utils/Log.h> 20 21 #include <arpa/inet.h> 22 23 #include <pthread.h> 24 #include <sys/prctl.h> 25 26 #include <media/stagefright/foundation/ADebug.h> 27 #include <media/stagefright/MPEG4Writer.h> 28 #include <media/stagefright/MediaBuffer.h> 29 #include <media/stagefright/MetaData.h> 30 #include <media/stagefright/MediaDefs.h> 31 #include <media/stagefright/MediaErrors.h> 32 #include <media/stagefright/MediaSource.h> 33 #include <media/stagefright/Utils.h> 34 #include <media/mediarecorder.h> 35 #include <cutils/properties.h> 36 #include <sys/types.h> 37 #include <sys/stat.h> 38 #include <fcntl.h> 39 #include <unistd.h> 40 41 #include "include/ESDS.h" 42 43 namespace android { 44 45 static const int64_t kMax32BitFileSize = 0x007fffffffLL; 46 static const uint8_t kNalUnitTypeSeqParamSet = 0x07; 47 static const uint8_t kNalUnitTypePicParamSet = 0x08; 48 static const int64_t kInitialDelayTimeUs = 700000LL; 49 50 class MPEG4Writer::Track { 51 public: 52 Track(MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId); 53 54 ~Track(); 55 56 status_t start(MetaData *params); 57 status_t stop(); 58 status_t pause(); 59 bool reachedEOS(); 60 61 int64_t getDurationUs() const; 62 int64_t getEstimatedTrackSizeBytes() const; 63 void writeTrackHeader(bool use32BitOffset = true); 64 void bufferChunk(int64_t timestampUs); 65 bool isAvc() const { return mIsAvc; } 66 bool isAudio() const { return mIsAudio; } 67 bool isMPEG4() const { return mIsMPEG4; } 68 void addChunkOffset(off64_t offset); 69 int32_t getTrackId() const { return mTrackId; } 70 status_t dump(int fd, const Vector<String16>& args) const; 71 72 private: 73 enum { 74 kMaxCttsOffsetTimeUs = 1000000LL, // 1 second 75 kSampleArraySize = 1000, 76 }; 77 78 MPEG4Writer *mOwner; 79 sp<MetaData> mMeta; 80 sp<MediaSource> mSource; 81 volatile bool mDone; 82 volatile bool mPaused; 83 volatile bool mResumed; 84 volatile bool mStarted; 85 bool mIsAvc; 86 bool mIsAudio; 87 bool mIsMPEG4; 88 int32_t mTrackId; 89 int64_t mTrackDurationUs; 90 int64_t mMaxChunkDurationUs; 91 92 bool mIsRealTimeRecording; 93 int64_t mMaxTimeStampUs; 94 int64_t mEstimatedTrackSizeBytes; 95 int64_t mMdatSizeBytes; 96 int32_t mTimeScale; 97 98 pthread_t mThread; 99 100 /* 101 * mNumSamples is used to track the total number of samples in 102 * mSampleSizes List. 103 * 104 * A linked list of fixed sized array is used here to reduce the time 105 * to write out stsz box. 106 */ 107 uint32_t mNumSamples; 108 uint32_t* mCurrentSampleSizeArr; 109 List<uint32_t *> mSampleSizes; 110 bool mSamplesHaveSameSize; 111 112 List<MediaBuffer *> mChunkSamples; 113 114 size_t mNumStcoTableEntries; 115 List<off64_t> mChunkOffsets; 116 117 size_t mNumStscTableEntries; 118 struct StscTableEntry { 119 120 StscTableEntry(uint32_t chunk, uint32_t samples, uint32_t id) 121 : firstChunk(chunk), 122 samplesPerChunk(samples), 123 sampleDescriptionId(id) {} 124 125 uint32_t firstChunk; 126 uint32_t samplesPerChunk; 127 uint32_t sampleDescriptionId; 128 }; 129 List<StscTableEntry> mStscTableEntries; 130 131 size_t mNumStssTableEntries; 132 List<int32_t> mStssTableEntries; 133 134 struct SttsTableEntry { 135 136 SttsTableEntry(uint32_t count, uint32_t duration) 137 : sampleCount(count), sampleDuration(duration) {} 138 139 uint32_t sampleCount; 140 uint32_t sampleDuration; // time scale based 141 }; 142 size_t mNumSttsTableEntries; 143 List<SttsTableEntry> mSttsTableEntries; 144 145 struct CttsTableEntry { 146 CttsTableEntry(uint32_t count, int32_t timescaledDur) 147 : sampleCount(count), sampleDuration(timescaledDur) {} 148 149 uint32_t sampleCount; 150 uint32_t sampleDuration; // time scale based 151 }; 152 size_t mNumCttsTableEntries; 153 List<CttsTableEntry> mCttsTableEntries; 154 int64_t mMinCttsOffsetTimeUs; 155 int64_t mMaxCttsOffsetTimeUs; 156 157 // Sequence parameter set or picture parameter set 158 struct AVCParamSet { 159 AVCParamSet(uint16_t length, const uint8_t *data) 160 : mLength(length), mData(data) {} 161 162 uint16_t mLength; 163 const uint8_t *mData; 164 }; 165 List<AVCParamSet> mSeqParamSets; 166 List<AVCParamSet> mPicParamSets; 167 uint8_t mProfileIdc; 168 uint8_t mProfileCompatible; 169 uint8_t mLevelIdc; 170 171 void *mCodecSpecificData; 172 size_t mCodecSpecificDataSize; 173 bool mGotAllCodecSpecificData; 174 bool mTrackingProgressStatus; 175 176 bool mReachedEOS; 177 int64_t mStartTimestampUs; 178 int64_t mStartTimeRealUs; 179 int64_t mFirstSampleTimeRealUs; 180 int64_t mPreviousTrackTimeUs; 181 int64_t mTrackEveryTimeDurationUs; 182 183 // Update the audio track's drift information. 184 void updateDriftTime(const sp<MetaData>& meta); 185 186 int32_t getStartTimeOffsetScaledTime() const; 187 188 static void *ThreadWrapper(void *me); 189 status_t threadEntry(); 190 191 const uint8_t *parseParamSet( 192 const uint8_t *data, size_t length, int type, size_t *paramSetLen); 193 194 status_t makeAVCCodecSpecificData(const uint8_t *data, size_t size); 195 status_t copyAVCCodecSpecificData(const uint8_t *data, size_t size); 196 status_t parseAVCCodecSpecificData(const uint8_t *data, size_t size); 197 198 // Track authoring progress status 199 void trackProgressStatus(int64_t timeUs, status_t err = OK); 200 void initTrackingProgressStatus(MetaData *params); 201 202 void getCodecSpecificDataFromInputFormatIfPossible(); 203 204 // Determine the track time scale 205 // If it is an audio track, try to use the sampling rate as 206 // the time scale; however, if user chooses the overwrite 207 // value, the user-supplied time scale will be used. 208 void setTimeScale(); 209 210 // Simple validation on the codec specific data 211 status_t checkCodecSpecificData() const; 212 int32_t mRotation; 213 214 void updateTrackSizeEstimate(); 215 void addOneStscTableEntry(size_t chunkId, size_t sampleId); 216 void addOneStssTableEntry(size_t sampleId); 217 218 // Duration is time scale based 219 void addOneSttsTableEntry(size_t sampleCount, int32_t timescaledDur); 220 void addOneCttsTableEntry(size_t sampleCount, int32_t timescaledDur); 221 222 bool isTrackMalFormed() const; 223 void sendTrackSummary(bool hasMultipleTracks); 224 225 // Write the boxes 226 void writeStcoBox(bool use32BitOffset); 227 void writeStscBox(); 228 void writeStszBox(); 229 void writeStssBox(); 230 void writeSttsBox(); 231 void writeCttsBox(); 232 void writeD263Box(); 233 void writePaspBox(); 234 void writeAvccBox(); 235 void writeUrlBox(); 236 void writeDrefBox(); 237 void writeDinfBox(); 238 void writeDamrBox(); 239 void writeMdhdBox(time_t now); 240 void writeSmhdBox(); 241 void writeVmhdBox(); 242 void writeHdlrBox(); 243 void writeTkhdBox(time_t now); 244 void writeMp4aEsdsBox(); 245 void writeMp4vEsdsBox(); 246 void writeAudioFourCCBox(); 247 void writeVideoFourCCBox(); 248 void writeStblBox(bool use32BitOffset); 249 250 Track(const Track &); 251 Track &operator=(const Track &); 252 }; 253 254 MPEG4Writer::MPEG4Writer(const char *filename) 255 : mFd(-1), 256 mInitCheck(NO_INIT), 257 mUse4ByteNalLength(true), 258 mUse32BitOffset(true), 259 mIsFileSizeLimitExplicitlyRequested(false), 260 mPaused(false), 261 mStarted(false), 262 mWriterThreadStarted(false), 263 mOffset(0), 264 mMdatOffset(0), 265 mEstimatedMoovBoxSize(0), 266 mInterleaveDurationUs(1000000), 267 mLatitudex10000(0), 268 mLongitudex10000(0), 269 mAreGeoTagsAvailable(false), 270 mStartTimeOffsetMs(-1) { 271 272 mFd = open(filename, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR); 273 if (mFd >= 0) { 274 mInitCheck = OK; 275 } 276 } 277 278 MPEG4Writer::MPEG4Writer(int fd) 279 : mFd(dup(fd)), 280 mInitCheck(mFd < 0? NO_INIT: OK), 281 mUse4ByteNalLength(true), 282 mUse32BitOffset(true), 283 mIsFileSizeLimitExplicitlyRequested(false), 284 mPaused(false), 285 mStarted(false), 286 mWriterThreadStarted(false), 287 mOffset(0), 288 mMdatOffset(0), 289 mEstimatedMoovBoxSize(0), 290 mInterleaveDurationUs(1000000), 291 mLatitudex10000(0), 292 mLongitudex10000(0), 293 mAreGeoTagsAvailable(false), 294 mStartTimeOffsetMs(-1) { 295 } 296 297 MPEG4Writer::~MPEG4Writer() { 298 reset(); 299 300 while (!mTracks.empty()) { 301 List<Track *>::iterator it = mTracks.begin(); 302 delete *it; 303 (*it) = NULL; 304 mTracks.erase(it); 305 } 306 mTracks.clear(); 307 } 308 309 status_t MPEG4Writer::dump( 310 int fd, const Vector<String16>& args) { 311 const size_t SIZE = 256; 312 char buffer[SIZE]; 313 String8 result; 314 snprintf(buffer, SIZE, " MPEG4Writer %p\n", this); 315 result.append(buffer); 316 snprintf(buffer, SIZE, " mStarted: %s\n", mStarted? "true": "false"); 317 result.append(buffer); 318 ::write(fd, result.string(), result.size()); 319 for (List<Track *>::iterator it = mTracks.begin(); 320 it != mTracks.end(); ++it) { 321 (*it)->dump(fd, args); 322 } 323 return OK; 324 } 325 326 status_t MPEG4Writer::Track::dump( 327 int fd, const Vector<String16>& args) const { 328 const size_t SIZE = 256; 329 char buffer[SIZE]; 330 String8 result; 331 snprintf(buffer, SIZE, " %s track\n", mIsAudio? "Audio": "Video"); 332 result.append(buffer); 333 snprintf(buffer, SIZE, " reached EOS: %s\n", 334 mReachedEOS? "true": "false"); 335 result.append(buffer); 336 ::write(fd, result.string(), result.size()); 337 return OK; 338 } 339 340 status_t MPEG4Writer::addSource(const sp<MediaSource> &source) { 341 Mutex::Autolock l(mLock); 342 if (mStarted) { 343 ALOGE("Attempt to add source AFTER recording is started"); 344 return UNKNOWN_ERROR; 345 } 346 Track *track = new Track(this, source, mTracks.size()); 347 mTracks.push_back(track); 348 349 return OK; 350 } 351 352 status_t MPEG4Writer::startTracks(MetaData *params) { 353 for (List<Track *>::iterator it = mTracks.begin(); 354 it != mTracks.end(); ++it) { 355 status_t err = (*it)->start(params); 356 357 if (err != OK) { 358 for (List<Track *>::iterator it2 = mTracks.begin(); 359 it2 != it; ++it2) { 360 (*it2)->stop(); 361 } 362 363 return err; 364 } 365 } 366 return OK; 367 } 368 369 int64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) { 370 // This implementation is highly experimental/heurisitic. 371 // 372 // Statistical analysis shows that metadata usually accounts 373 // for a small portion of the total file size, usually < 0.6%. 374 375 // The default MIN_MOOV_BOX_SIZE is set to 0.6% x 1MB / 2, 376 // where 1MB is the common file size limit for MMS application. 377 // The default MAX _MOOV_BOX_SIZE value is based on about 3 378 // minute video recording with a bit rate about 3 Mbps, because 379 // statistics also show that most of the video captured are going 380 // to be less than 3 minutes. 381 382 // If the estimation is wrong, we will pay the price of wasting 383 // some reserved space. This should not happen so often statistically. 384 static const int32_t factor = mUse32BitOffset? 1: 2; 385 static const int64_t MIN_MOOV_BOX_SIZE = 3 * 1024; // 3 KB 386 static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000); 387 int64_t size = MIN_MOOV_BOX_SIZE; 388 389 // Max file size limit is set 390 if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) { 391 size = mMaxFileSizeLimitBytes * 6 / 1000; 392 } 393 394 // Max file duration limit is set 395 if (mMaxFileDurationLimitUs != 0) { 396 if (bitRate > 0) { 397 int64_t size2 = 398 ((mMaxFileDurationLimitUs * bitRate * 6) / 1000 / 8000000); 399 if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) { 400 // When both file size and duration limits are set, 401 // we use the smaller limit of the two. 402 if (size > size2) { 403 size = size2; 404 } 405 } else { 406 // Only max file duration limit is set 407 size = size2; 408 } 409 } 410 } 411 412 if (size < MIN_MOOV_BOX_SIZE) { 413 size = MIN_MOOV_BOX_SIZE; 414 } 415 416 // Any long duration recording will be probably end up with 417 // non-streamable mp4 file. 418 if (size > MAX_MOOV_BOX_SIZE) { 419 size = MAX_MOOV_BOX_SIZE; 420 } 421 422 ALOGI("limits: %lld/%lld bytes/us, bit rate: %d bps and the estimated" 423 " moov size %lld bytes", 424 mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size); 425 return factor * size; 426 } 427 428 status_t MPEG4Writer::start(MetaData *param) { 429 if (mInitCheck != OK) { 430 return UNKNOWN_ERROR; 431 } 432 433 /* 434 * Check mMaxFileSizeLimitBytes at the beginning 435 * since mMaxFileSizeLimitBytes may be implicitly 436 * changed later for 32-bit file offset even if 437 * user does not ask to set it explicitly. 438 */ 439 if (mMaxFileSizeLimitBytes != 0) { 440 mIsFileSizeLimitExplicitlyRequested = true; 441 } 442 443 int32_t use64BitOffset; 444 if (param && 445 param->findInt32(kKey64BitFileOffset, &use64BitOffset) && 446 use64BitOffset) { 447 mUse32BitOffset = false; 448 } 449 450 if (mUse32BitOffset) { 451 // Implicit 32 bit file size limit 452 if (mMaxFileSizeLimitBytes == 0) { 453 mMaxFileSizeLimitBytes = kMax32BitFileSize; 454 } 455 456 // If file size is set to be larger than the 32 bit file 457 // size limit, treat it as an error. 458 if (mMaxFileSizeLimitBytes > kMax32BitFileSize) { 459 ALOGW("32-bit file size limit (%lld bytes) too big. " 460 "It is changed to %lld bytes", 461 mMaxFileSizeLimitBytes, kMax32BitFileSize); 462 mMaxFileSizeLimitBytes = kMax32BitFileSize; 463 } 464 } 465 466 int32_t use2ByteNalLength; 467 if (param && 468 param->findInt32(kKey2ByteNalLength, &use2ByteNalLength) && 469 use2ByteNalLength) { 470 mUse4ByteNalLength = false; 471 } 472 473 mStartTimestampUs = -1; 474 475 if (mStarted) { 476 if (mPaused) { 477 mPaused = false; 478 return startTracks(param); 479 } 480 return OK; 481 } 482 483 if (!param || 484 !param->findInt32(kKeyTimeScale, &mTimeScale)) { 485 mTimeScale = 1000; 486 } 487 CHECK_GT(mTimeScale, 0); 488 ALOGV("movie time scale: %d", mTimeScale); 489 490 mStreamableFile = true; 491 mWriteMoovBoxToMemory = false; 492 mMoovBoxBuffer = NULL; 493 mMoovBoxBufferOffset = 0; 494 495 writeFtypBox(param); 496 497 mFreeBoxOffset = mOffset; 498 499 if (mEstimatedMoovBoxSize == 0) { 500 int32_t bitRate = -1; 501 if (param) { 502 param->findInt32(kKeyBitRate, &bitRate); 503 } 504 mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate); 505 } 506 CHECK_GE(mEstimatedMoovBoxSize, 8); 507 lseek64(mFd, mFreeBoxOffset, SEEK_SET); 508 writeInt32(mEstimatedMoovBoxSize); 509 write("free", 4); 510 511 mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize; 512 mOffset = mMdatOffset; 513 lseek64(mFd, mMdatOffset, SEEK_SET); 514 if (mUse32BitOffset) { 515 write("????mdat", 8); 516 } else { 517 write("\x00\x00\x00\x01mdat????????", 16); 518 } 519 520 status_t err = startWriterThread(); 521 if (err != OK) { 522 return err; 523 } 524 525 err = startTracks(param); 526 if (err != OK) { 527 return err; 528 } 529 530 mStarted = true; 531 return OK; 532 } 533 534 bool MPEG4Writer::use32BitFileOffset() const { 535 return mUse32BitOffset; 536 } 537 538 status_t MPEG4Writer::pause() { 539 if (mInitCheck != OK) { 540 return OK; 541 } 542 mPaused = true; 543 status_t err = OK; 544 for (List<Track *>::iterator it = mTracks.begin(); 545 it != mTracks.end(); ++it) { 546 status_t status = (*it)->pause(); 547 if (status != OK) { 548 err = status; 549 } 550 } 551 return err; 552 } 553 554 void MPEG4Writer::stopWriterThread() { 555 ALOGD("Stopping writer thread"); 556 if (!mWriterThreadStarted) { 557 return; 558 } 559 560 { 561 Mutex::Autolock autolock(mLock); 562 563 mDone = true; 564 mChunkReadyCondition.signal(); 565 } 566 567 void *dummy; 568 pthread_join(mThread, &dummy); 569 mWriterThreadStarted = false; 570 ALOGD("Writer thread stopped"); 571 } 572 573 /* 574 * MP4 file standard defines a composition matrix: 575 * | a b u | 576 * | c d v | 577 * | x y w | 578 * 579 * the element in the matrix is stored in the following 580 * order: {a, b, u, c, d, v, x, y, w}, 581 * where a, b, c, d, x, and y is in 16.16 format, while 582 * u, v and w is in 2.30 format. 583 */ 584 void MPEG4Writer::writeCompositionMatrix(int degrees) { 585 ALOGV("writeCompositionMatrix"); 586 uint32_t a = 0x00010000; 587 uint32_t b = 0; 588 uint32_t c = 0; 589 uint32_t d = 0x00010000; 590 switch (degrees) { 591 case 0: 592 break; 593 case 90: 594 a = 0; 595 b = 0x00010000; 596 c = 0xFFFF0000; 597 d = 0; 598 break; 599 case 180: 600 a = 0xFFFF0000; 601 d = 0xFFFF0000; 602 break; 603 case 270: 604 a = 0; 605 b = 0xFFFF0000; 606 c = 0x00010000; 607 d = 0; 608 break; 609 default: 610 CHECK(!"Should never reach this unknown rotation"); 611 break; 612 } 613 614 writeInt32(a); // a 615 writeInt32(b); // b 616 writeInt32(0); // u 617 writeInt32(c); // c 618 writeInt32(d); // d 619 writeInt32(0); // v 620 writeInt32(0); // x 621 writeInt32(0); // y 622 writeInt32(0x40000000); // w 623 } 624 625 void MPEG4Writer::release() { 626 close(mFd); 627 mFd = -1; 628 mInitCheck = NO_INIT; 629 mStarted = false; 630 } 631 632 status_t MPEG4Writer::reset() { 633 if (mInitCheck != OK) { 634 return OK; 635 } else { 636 if (!mWriterThreadStarted || 637 !mStarted) { 638 if (mWriterThreadStarted) { 639 stopWriterThread(); 640 } 641 release(); 642 return OK; 643 } 644 } 645 646 status_t err = OK; 647 int64_t maxDurationUs = 0; 648 int64_t minDurationUs = 0x7fffffffffffffffLL; 649 for (List<Track *>::iterator it = mTracks.begin(); 650 it != mTracks.end(); ++it) { 651 status_t status = (*it)->stop(); 652 if (err == OK && status != OK) { 653 err = status; 654 } 655 656 int64_t durationUs = (*it)->getDurationUs(); 657 if (durationUs > maxDurationUs) { 658 maxDurationUs = durationUs; 659 } 660 if (durationUs < minDurationUs) { 661 minDurationUs = durationUs; 662 } 663 } 664 665 if (mTracks.size() > 1) { 666 ALOGD("Duration from tracks range is [%lld, %lld] us", 667 minDurationUs, maxDurationUs); 668 } 669 670 stopWriterThread(); 671 672 // Do not write out movie header on error. 673 if (err != OK) { 674 release(); 675 return err; 676 } 677 678 // Fix up the size of the 'mdat' chunk. 679 if (mUse32BitOffset) { 680 lseek64(mFd, mMdatOffset, SEEK_SET); 681 int32_t size = htonl(static_cast<int32_t>(mOffset - mMdatOffset)); 682 ::write(mFd, &size, 4); 683 } else { 684 lseek64(mFd, mMdatOffset + 8, SEEK_SET); 685 int64_t size = mOffset - mMdatOffset; 686 size = hton64(size); 687 ::write(mFd, &size, 8); 688 } 689 lseek64(mFd, mOffset, SEEK_SET); 690 691 const off64_t moovOffset = mOffset; 692 mWriteMoovBoxToMemory = true; 693 mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize); 694 mMoovBoxBufferOffset = 0; 695 CHECK(mMoovBoxBuffer != NULL); 696 writeMoovBox(maxDurationUs); 697 698 mWriteMoovBoxToMemory = false; 699 if (mStreamableFile) { 700 CHECK_LE(mMoovBoxBufferOffset + 8, mEstimatedMoovBoxSize); 701 702 // Moov box 703 lseek64(mFd, mFreeBoxOffset, SEEK_SET); 704 mOffset = mFreeBoxOffset; 705 write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset); 706 707 // Free box 708 lseek64(mFd, mOffset, SEEK_SET); 709 writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset); 710 write("free", 4); 711 712 // Free temp memory 713 free(mMoovBoxBuffer); 714 mMoovBoxBuffer = NULL; 715 mMoovBoxBufferOffset = 0; 716 } else { 717 ALOGI("The mp4 file will not be streamable."); 718 } 719 720 CHECK(mBoxes.empty()); 721 722 release(); 723 return err; 724 } 725 726 void MPEG4Writer::writeMvhdBox(int64_t durationUs) { 727 time_t now = time(NULL); 728 beginBox("mvhd"); 729 writeInt32(0); // version=0, flags=0 730 writeInt32(now); // creation time 731 writeInt32(now); // modification time 732 writeInt32(mTimeScale); // mvhd timescale 733 int32_t duration = (durationUs * mTimeScale + 5E5) / 1E6; 734 writeInt32(duration); 735 writeInt32(0x10000); // rate: 1.0 736 writeInt16(0x100); // volume 737 writeInt16(0); // reserved 738 writeInt32(0); // reserved 739 writeInt32(0); // reserved 740 writeCompositionMatrix(0); // matrix 741 writeInt32(0); // predefined 742 writeInt32(0); // predefined 743 writeInt32(0); // predefined 744 writeInt32(0); // predefined 745 writeInt32(0); // predefined 746 writeInt32(0); // predefined 747 writeInt32(mTracks.size() + 1); // nextTrackID 748 endBox(); // mvhd 749 } 750 751 void MPEG4Writer::writeMoovBox(int64_t durationUs) { 752 beginBox("moov"); 753 writeMvhdBox(durationUs); 754 if (mAreGeoTagsAvailable) { 755 writeUdtaBox(); 756 } 757 int32_t id = 1; 758 for (List<Track *>::iterator it = mTracks.begin(); 759 it != mTracks.end(); ++it, ++id) { 760 (*it)->writeTrackHeader(mUse32BitOffset); 761 } 762 endBox(); // moov 763 } 764 765 void MPEG4Writer::writeFtypBox(MetaData *param) { 766 beginBox("ftyp"); 767 768 int32_t fileType; 769 if (param && param->findInt32(kKeyFileType, &fileType) && 770 fileType != OUTPUT_FORMAT_MPEG_4) { 771 writeFourcc("3gp4"); 772 } else { 773 writeFourcc("isom"); 774 } 775 776 writeInt32(0); 777 writeFourcc("isom"); 778 writeFourcc("3gp4"); 779 endBox(); 780 } 781 782 static bool isTestModeEnabled() { 783 #if (PROPERTY_VALUE_MAX < 5) 784 #error "PROPERTY_VALUE_MAX must be at least 5" 785 #endif 786 787 // Test mode is enabled only if rw.media.record.test system 788 // property is enabled. 789 char value[PROPERTY_VALUE_MAX]; 790 if (property_get("rw.media.record.test", value, NULL) && 791 (!strcasecmp(value, "true") || !strcasecmp(value, "1"))) { 792 return true; 793 } 794 return false; 795 } 796 797 void MPEG4Writer::sendSessionSummary() { 798 // Send session summary only if test mode is enabled 799 if (!isTestModeEnabled()) { 800 return; 801 } 802 803 for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 804 it != mChunkInfos.end(); ++it) { 805 int trackNum = it->mTrack->getTrackId() << 28; 806 notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 807 trackNum | MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS, 808 it->mMaxInterChunkDurUs); 809 } 810 } 811 812 status_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) { 813 mInterleaveDurationUs = durationUs; 814 return OK; 815 } 816 817 void MPEG4Writer::lock() { 818 mLock.lock(); 819 } 820 821 void MPEG4Writer::unlock() { 822 mLock.unlock(); 823 } 824 825 off64_t MPEG4Writer::addSample_l(MediaBuffer *buffer) { 826 off64_t old_offset = mOffset; 827 828 ::write(mFd, 829 (const uint8_t *)buffer->data() + buffer->range_offset(), 830 buffer->range_length()); 831 832 mOffset += buffer->range_length(); 833 834 return old_offset; 835 } 836 837 static void StripStartcode(MediaBuffer *buffer) { 838 if (buffer->range_length() < 4) { 839 return; 840 } 841 842 const uint8_t *ptr = 843 (const uint8_t *)buffer->data() + buffer->range_offset(); 844 845 if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) { 846 buffer->set_range( 847 buffer->range_offset() + 4, buffer->range_length() - 4); 848 } 849 } 850 851 off64_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) { 852 off64_t old_offset = mOffset; 853 854 size_t length = buffer->range_length(); 855 856 if (mUse4ByteNalLength) { 857 uint8_t x = length >> 24; 858 ::write(mFd, &x, 1); 859 x = (length >> 16) & 0xff; 860 ::write(mFd, &x, 1); 861 x = (length >> 8) & 0xff; 862 ::write(mFd, &x, 1); 863 x = length & 0xff; 864 ::write(mFd, &x, 1); 865 866 ::write(mFd, 867 (const uint8_t *)buffer->data() + buffer->range_offset(), 868 length); 869 870 mOffset += length + 4; 871 } else { 872 CHECK_LT(length, 65536); 873 874 uint8_t x = length >> 8; 875 ::write(mFd, &x, 1); 876 x = length & 0xff; 877 ::write(mFd, &x, 1); 878 ::write(mFd, (const uint8_t *)buffer->data() + buffer->range_offset(), length); 879 mOffset += length + 2; 880 } 881 882 return old_offset; 883 } 884 885 size_t MPEG4Writer::write( 886 const void *ptr, size_t size, size_t nmemb) { 887 888 const size_t bytes = size * nmemb; 889 if (mWriteMoovBoxToMemory) { 890 // This happens only when we write the moov box at the end of 891 // recording, not for each output video/audio frame we receive. 892 off64_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes; 893 if (moovBoxSize > mEstimatedMoovBoxSize) { 894 for (List<off64_t>::iterator it = mBoxes.begin(); 895 it != mBoxes.end(); ++it) { 896 (*it) += mOffset; 897 } 898 lseek64(mFd, mOffset, SEEK_SET); 899 ::write(mFd, mMoovBoxBuffer, mMoovBoxBufferOffset); 900 ::write(mFd, ptr, size * nmemb); 901 mOffset += (bytes + mMoovBoxBufferOffset); 902 free(mMoovBoxBuffer); 903 mMoovBoxBuffer = NULL; 904 mMoovBoxBufferOffset = 0; 905 mWriteMoovBoxToMemory = false; 906 mStreamableFile = false; 907 } else { 908 memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes); 909 mMoovBoxBufferOffset += bytes; 910 } 911 } else { 912 ::write(mFd, ptr, size * nmemb); 913 mOffset += bytes; 914 } 915 return bytes; 916 } 917 918 void MPEG4Writer::beginBox(const char *fourcc) { 919 CHECK_EQ(strlen(fourcc), 4); 920 921 mBoxes.push_back(mWriteMoovBoxToMemory? 922 mMoovBoxBufferOffset: mOffset); 923 924 writeInt32(0); 925 writeFourcc(fourcc); 926 } 927 928 void MPEG4Writer::endBox() { 929 CHECK(!mBoxes.empty()); 930 931 off64_t offset = *--mBoxes.end(); 932 mBoxes.erase(--mBoxes.end()); 933 934 if (mWriteMoovBoxToMemory) { 935 int32_t x = htonl(mMoovBoxBufferOffset - offset); 936 memcpy(mMoovBoxBuffer + offset, &x, 4); 937 } else { 938 lseek64(mFd, offset, SEEK_SET); 939 writeInt32(mOffset - offset); 940 mOffset -= 4; 941 lseek64(mFd, mOffset, SEEK_SET); 942 } 943 } 944 945 void MPEG4Writer::writeInt8(int8_t x) { 946 write(&x, 1, 1); 947 } 948 949 void MPEG4Writer::writeInt16(int16_t x) { 950 x = htons(x); 951 write(&x, 1, 2); 952 } 953 954 void MPEG4Writer::writeInt32(int32_t x) { 955 x = htonl(x); 956 write(&x, 1, 4); 957 } 958 959 void MPEG4Writer::writeInt64(int64_t x) { 960 x = hton64(x); 961 write(&x, 1, 8); 962 } 963 964 void MPEG4Writer::writeCString(const char *s) { 965 size_t n = strlen(s); 966 write(s, 1, n + 1); 967 } 968 969 void MPEG4Writer::writeFourcc(const char *s) { 970 CHECK_EQ(strlen(s), 4); 971 write(s, 1, 4); 972 } 973 974 975 // Written in +/-DD.DDDD format 976 void MPEG4Writer::writeLatitude(int degreex10000) { 977 bool isNegative = (degreex10000 < 0); 978 char sign = isNegative? '-': '+'; 979 980 // Handle the whole part 981 char str[9]; 982 int wholePart = degreex10000 / 10000; 983 if (wholePart == 0) { 984 snprintf(str, 5, "%c%.2d.", sign, wholePart); 985 } else { 986 snprintf(str, 5, "%+.2d.", wholePart); 987 } 988 989 // Handle the fractional part 990 int fractionalPart = degreex10000 - (wholePart * 10000); 991 if (fractionalPart < 0) { 992 fractionalPart = -fractionalPart; 993 } 994 snprintf(&str[4], 5, "%.4d", fractionalPart); 995 996 // Do not write the null terminator 997 write(str, 1, 8); 998 } 999 1000 // Written in +/- DDD.DDDD format 1001 void MPEG4Writer::writeLongitude(int degreex10000) { 1002 bool isNegative = (degreex10000 < 0); 1003 char sign = isNegative? '-': '+'; 1004 1005 // Handle the whole part 1006 char str[10]; 1007 int wholePart = degreex10000 / 10000; 1008 if (wholePart == 0) { 1009 snprintf(str, 6, "%c%.3d.", sign, wholePart); 1010 } else { 1011 snprintf(str, 6, "%+.3d.", wholePart); 1012 } 1013 1014 // Handle the fractional part 1015 int fractionalPart = degreex10000 - (wholePart * 10000); 1016 if (fractionalPart < 0) { 1017 fractionalPart = -fractionalPart; 1018 } 1019 snprintf(&str[5], 5, "%.4d", fractionalPart); 1020 1021 // Do not write the null terminator 1022 write(str, 1, 9); 1023 } 1024 1025 /* 1026 * Geodata is stored according to ISO-6709 standard. 1027 * latitudex10000 is latitude in degrees times 10000, and 1028 * longitudex10000 is longitude in degrees times 10000. 1029 * The range for the latitude is in [-90, +90], and 1030 * The range for the longitude is in [-180, +180] 1031 */ 1032 status_t MPEG4Writer::setGeoData(int latitudex10000, int longitudex10000) { 1033 // Is latitude or longitude out of range? 1034 if (latitudex10000 < -900000 || latitudex10000 > 900000 || 1035 longitudex10000 < -1800000 || longitudex10000 > 1800000) { 1036 return BAD_VALUE; 1037 } 1038 1039 mLatitudex10000 = latitudex10000; 1040 mLongitudex10000 = longitudex10000; 1041 mAreGeoTagsAvailable = true; 1042 return OK; 1043 } 1044 1045 void MPEG4Writer::write(const void *data, size_t size) { 1046 write(data, 1, size); 1047 } 1048 1049 bool MPEG4Writer::isFileStreamable() const { 1050 return mStreamableFile; 1051 } 1052 1053 bool MPEG4Writer::exceedsFileSizeLimit() { 1054 // No limit 1055 if (mMaxFileSizeLimitBytes == 0) { 1056 return false; 1057 } 1058 1059 int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize); 1060 for (List<Track *>::iterator it = mTracks.begin(); 1061 it != mTracks.end(); ++it) { 1062 nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes(); 1063 } 1064 1065 // Be conservative in the estimate: do not exceed 95% of 1066 // the target file limit. For small target file size limit, though, 1067 // this will not help. 1068 return (nTotalBytesEstimate >= (95 * mMaxFileSizeLimitBytes) / 100); 1069 } 1070 1071 bool MPEG4Writer::exceedsFileDurationLimit() { 1072 // No limit 1073 if (mMaxFileDurationLimitUs == 0) { 1074 return false; 1075 } 1076 1077 for (List<Track *>::iterator it = mTracks.begin(); 1078 it != mTracks.end(); ++it) { 1079 if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) { 1080 return true; 1081 } 1082 } 1083 return false; 1084 } 1085 1086 bool MPEG4Writer::reachedEOS() { 1087 bool allDone = true; 1088 for (List<Track *>::iterator it = mTracks.begin(); 1089 it != mTracks.end(); ++it) { 1090 if (!(*it)->reachedEOS()) { 1091 allDone = false; 1092 break; 1093 } 1094 } 1095 1096 return allDone; 1097 } 1098 1099 void MPEG4Writer::setStartTimestampUs(int64_t timeUs) { 1100 ALOGI("setStartTimestampUs: %lld", timeUs); 1101 CHECK_GE(timeUs, 0ll); 1102 Mutex::Autolock autoLock(mLock); 1103 if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) { 1104 mStartTimestampUs = timeUs; 1105 ALOGI("Earliest track starting time: %lld", mStartTimestampUs); 1106 } 1107 } 1108 1109 int64_t MPEG4Writer::getStartTimestampUs() { 1110 Mutex::Autolock autoLock(mLock); 1111 return mStartTimestampUs; 1112 } 1113 1114 size_t MPEG4Writer::numTracks() { 1115 Mutex::Autolock autolock(mLock); 1116 return mTracks.size(); 1117 } 1118 1119 //////////////////////////////////////////////////////////////////////////////// 1120 1121 MPEG4Writer::Track::Track( 1122 MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId) 1123 : mOwner(owner), 1124 mMeta(source->getFormat()), 1125 mSource(source), 1126 mDone(false), 1127 mPaused(false), 1128 mResumed(false), 1129 mStarted(false), 1130 mTrackId(trackId), 1131 mTrackDurationUs(0), 1132 mEstimatedTrackSizeBytes(0), 1133 mSamplesHaveSameSize(true), 1134 mCodecSpecificData(NULL), 1135 mCodecSpecificDataSize(0), 1136 mGotAllCodecSpecificData(false), 1137 mReachedEOS(false), 1138 mRotation(0) { 1139 getCodecSpecificDataFromInputFormatIfPossible(); 1140 1141 const char *mime; 1142 mMeta->findCString(kKeyMIMEType, &mime); 1143 mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); 1144 mIsAudio = !strncasecmp(mime, "audio/", 6); 1145 mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) || 1146 !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC); 1147 1148 setTimeScale(); 1149 } 1150 1151 void MPEG4Writer::Track::updateTrackSizeEstimate() { 1152 1153 int64_t stcoBoxSizeBytes = mOwner->use32BitFileOffset() 1154 ? mNumStcoTableEntries * 4 1155 : mNumStcoTableEntries * 8; 1156 1157 int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mNumSamples * 4); 1158 1159 mEstimatedTrackSizeBytes = mMdatSizeBytes; // media data size 1160 if (!mOwner->isFileStreamable()) { 1161 // Reserved free space is not large enough to hold 1162 // all meta data and thus wasted. 1163 mEstimatedTrackSizeBytes += mNumStscTableEntries * 12 + // stsc box size 1164 mNumStssTableEntries * 4 + // stss box size 1165 mNumSttsTableEntries * 8 + // stts box size 1166 mNumCttsTableEntries * 8 + // ctts box size 1167 stcoBoxSizeBytes + // stco box size 1168 stszBoxSizeBytes; // stsz box size 1169 } 1170 } 1171 1172 void MPEG4Writer::Track::addOneStscTableEntry( 1173 size_t chunkId, size_t sampleId) { 1174 1175 StscTableEntry stscEntry(chunkId, sampleId, 1); 1176 mStscTableEntries.push_back(stscEntry); 1177 ++mNumStscTableEntries; 1178 } 1179 1180 void MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) { 1181 mStssTableEntries.push_back(sampleId); 1182 ++mNumStssTableEntries; 1183 } 1184 1185 void MPEG4Writer::Track::addOneSttsTableEntry( 1186 size_t sampleCount, int32_t duration) { 1187 1188 if (duration == 0) { 1189 ALOGW("0-duration samples found: %d", sampleCount); 1190 } 1191 SttsTableEntry sttsEntry(sampleCount, duration); 1192 mSttsTableEntries.push_back(sttsEntry); 1193 ++mNumSttsTableEntries; 1194 } 1195 1196 void MPEG4Writer::Track::addOneCttsTableEntry( 1197 size_t sampleCount, int32_t duration) { 1198 1199 if (mIsAudio) { 1200 return; 1201 } 1202 CttsTableEntry cttsEntry(sampleCount, duration); 1203 mCttsTableEntries.push_back(cttsEntry); 1204 ++mNumCttsTableEntries; 1205 } 1206 1207 void MPEG4Writer::Track::addChunkOffset(off64_t offset) { 1208 ++mNumStcoTableEntries; 1209 mChunkOffsets.push_back(offset); 1210 } 1211 1212 void MPEG4Writer::Track::setTimeScale() { 1213 ALOGV("setTimeScale"); 1214 // Default time scale 1215 mTimeScale = 90000; 1216 1217 if (mIsAudio) { 1218 // Use the sampling rate as the default time scale for audio track. 1219 int32_t sampleRate; 1220 bool success = mMeta->findInt32(kKeySampleRate, &sampleRate); 1221 CHECK(success); 1222 mTimeScale = sampleRate; 1223 } 1224 1225 // If someone would like to overwrite the timescale, use user-supplied value. 1226 int32_t timeScale; 1227 if (mMeta->findInt32(kKeyTimeScale, &timeScale)) { 1228 mTimeScale = timeScale; 1229 } 1230 1231 CHECK_GT(mTimeScale, 0); 1232 } 1233 1234 void MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() { 1235 const char *mime; 1236 CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 1237 1238 if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 1239 uint32_t type; 1240 const void *data; 1241 size_t size; 1242 if (mMeta->findData(kKeyAVCC, &type, &data, &size)) { 1243 mCodecSpecificData = malloc(size); 1244 mCodecSpecificDataSize = size; 1245 memcpy(mCodecSpecificData, data, size); 1246 mGotAllCodecSpecificData = true; 1247 } 1248 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) 1249 || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 1250 uint32_t type; 1251 const void *data; 1252 size_t size; 1253 if (mMeta->findData(kKeyESDS, &type, &data, &size)) { 1254 ESDS esds(data, size); 1255 if (esds.getCodecSpecificInfo(&data, &size) == OK) { 1256 mCodecSpecificData = malloc(size); 1257 mCodecSpecificDataSize = size; 1258 memcpy(mCodecSpecificData, data, size); 1259 mGotAllCodecSpecificData = true; 1260 } 1261 } 1262 } 1263 } 1264 1265 MPEG4Writer::Track::~Track() { 1266 stop(); 1267 1268 if (mCodecSpecificData != NULL) { 1269 free(mCodecSpecificData); 1270 mCodecSpecificData = NULL; 1271 } 1272 1273 while (!mSampleSizes.empty()) { 1274 List<uint32_t *>::iterator it = mSampleSizes.begin(); 1275 delete[] (*it); 1276 mSampleSizes.erase(it); 1277 } 1278 } 1279 1280 void MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) { 1281 ALOGV("initTrackingProgressStatus"); 1282 mPreviousTrackTimeUs = -1; 1283 mTrackingProgressStatus = false; 1284 mTrackEveryTimeDurationUs = 0; 1285 { 1286 int64_t timeUs; 1287 if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) { 1288 ALOGV("Receive request to track progress status for every %lld us", timeUs); 1289 mTrackEveryTimeDurationUs = timeUs; 1290 mTrackingProgressStatus = true; 1291 } 1292 } 1293 } 1294 1295 // static 1296 void *MPEG4Writer::ThreadWrapper(void *me) { 1297 ALOGV("ThreadWrapper: %p", me); 1298 MPEG4Writer *writer = static_cast<MPEG4Writer *>(me); 1299 writer->threadFunc(); 1300 return NULL; 1301 } 1302 1303 void MPEG4Writer::bufferChunk(const Chunk& chunk) { 1304 ALOGV("bufferChunk: %p", chunk.mTrack); 1305 Mutex::Autolock autolock(mLock); 1306 CHECK_EQ(mDone, false); 1307 1308 for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 1309 it != mChunkInfos.end(); ++it) { 1310 1311 if (chunk.mTrack == it->mTrack) { // Found owner 1312 it->mChunks.push_back(chunk); 1313 mChunkReadyCondition.signal(); 1314 return; 1315 } 1316 } 1317 1318 CHECK(!"Received a chunk for a unknown track"); 1319 } 1320 1321 void MPEG4Writer::writeChunkToFile(Chunk* chunk) { 1322 ALOGV("writeChunkToFile: %lld from %s track", 1323 chunk->mTimeStampUs, chunk->mTrack->isAudio()? "audio": "video"); 1324 1325 int32_t isFirstSample = true; 1326 while (!chunk->mSamples.empty()) { 1327 List<MediaBuffer *>::iterator it = chunk->mSamples.begin(); 1328 1329 off64_t offset = chunk->mTrack->isAvc() 1330 ? addLengthPrefixedSample_l(*it) 1331 : addSample_l(*it); 1332 1333 if (isFirstSample) { 1334 chunk->mTrack->addChunkOffset(offset); 1335 isFirstSample = false; 1336 } 1337 1338 (*it)->release(); 1339 (*it) = NULL; 1340 chunk->mSamples.erase(it); 1341 } 1342 chunk->mSamples.clear(); 1343 } 1344 1345 void MPEG4Writer::writeAllChunks() { 1346 ALOGV("writeAllChunks"); 1347 size_t outstandingChunks = 0; 1348 Chunk chunk; 1349 while (findChunkToWrite(&chunk)) { 1350 writeChunkToFile(&chunk); 1351 ++outstandingChunks; 1352 } 1353 1354 sendSessionSummary(); 1355 1356 mChunkInfos.clear(); 1357 ALOGD("%d chunks are written in the last batch", outstandingChunks); 1358 } 1359 1360 bool MPEG4Writer::findChunkToWrite(Chunk *chunk) { 1361 ALOGV("findChunkToWrite"); 1362 1363 int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL; 1364 Track *track = NULL; 1365 for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 1366 it != mChunkInfos.end(); ++it) { 1367 if (!it->mChunks.empty()) { 1368 List<Chunk>::iterator chunkIt = it->mChunks.begin(); 1369 if (chunkIt->mTimeStampUs < minTimestampUs) { 1370 minTimestampUs = chunkIt->mTimeStampUs; 1371 track = it->mTrack; 1372 } 1373 } 1374 } 1375 1376 if (track == NULL) { 1377 ALOGV("Nothing to be written after all"); 1378 return false; 1379 } 1380 1381 if (mIsFirstChunk) { 1382 mIsFirstChunk = false; 1383 } 1384 1385 for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 1386 it != mChunkInfos.end(); ++it) { 1387 if (it->mTrack == track) { 1388 *chunk = *(it->mChunks.begin()); 1389 it->mChunks.erase(it->mChunks.begin()); 1390 CHECK_EQ(chunk->mTrack, track); 1391 1392 int64_t interChunkTimeUs = 1393 chunk->mTimeStampUs - it->mPrevChunkTimestampUs; 1394 if (interChunkTimeUs > it->mPrevChunkTimestampUs) { 1395 it->mMaxInterChunkDurUs = interChunkTimeUs; 1396 } 1397 1398 return true; 1399 } 1400 } 1401 1402 return false; 1403 } 1404 1405 void MPEG4Writer::threadFunc() { 1406 ALOGV("threadFunc"); 1407 1408 prctl(PR_SET_NAME, (unsigned long)"MPEG4Writer", 0, 0, 0); 1409 1410 Mutex::Autolock autoLock(mLock); 1411 while (!mDone) { 1412 Chunk chunk; 1413 bool chunkFound = false; 1414 1415 while (!mDone && !(chunkFound = findChunkToWrite(&chunk))) { 1416 mChunkReadyCondition.wait(mLock); 1417 } 1418 1419 // Actual write without holding the lock in order to 1420 // reduce the blocking time for media track threads. 1421 if (chunkFound) { 1422 mLock.unlock(); 1423 writeChunkToFile(&chunk); 1424 mLock.lock(); 1425 } 1426 } 1427 1428 writeAllChunks(); 1429 } 1430 1431 status_t MPEG4Writer::startWriterThread() { 1432 ALOGV("startWriterThread"); 1433 1434 mDone = false; 1435 mIsFirstChunk = true; 1436 mDriftTimeUs = 0; 1437 for (List<Track *>::iterator it = mTracks.begin(); 1438 it != mTracks.end(); ++it) { 1439 ChunkInfo info; 1440 info.mTrack = *it; 1441 info.mPrevChunkTimestampUs = 0; 1442 info.mMaxInterChunkDurUs = 0; 1443 mChunkInfos.push_back(info); 1444 } 1445 1446 pthread_attr_t attr; 1447 pthread_attr_init(&attr); 1448 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 1449 pthread_create(&mThread, &attr, ThreadWrapper, this); 1450 pthread_attr_destroy(&attr); 1451 mWriterThreadStarted = true; 1452 return OK; 1453 } 1454 1455 1456 status_t MPEG4Writer::Track::start(MetaData *params) { 1457 if (!mDone && mPaused) { 1458 mPaused = false; 1459 mResumed = true; 1460 return OK; 1461 } 1462 1463 int64_t startTimeUs; 1464 if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) { 1465 startTimeUs = 0; 1466 } 1467 mStartTimeRealUs = startTimeUs; 1468 1469 int32_t rotationDegrees; 1470 if (!mIsAudio && params && params->findInt32(kKeyRotation, &rotationDegrees)) { 1471 mRotation = rotationDegrees; 1472 } 1473 1474 mIsRealTimeRecording = true; 1475 { 1476 int32_t isNotRealTime; 1477 if (params && params->findInt32(kKeyNotRealTime, &isNotRealTime)) { 1478 mIsRealTimeRecording = (isNotRealTime == 0); 1479 } 1480 } 1481 1482 initTrackingProgressStatus(params); 1483 1484 sp<MetaData> meta = new MetaData; 1485 if (mIsRealTimeRecording && mOwner->numTracks() > 1) { 1486 /* 1487 * This extra delay of accepting incoming audio/video signals 1488 * helps to align a/v start time at the beginning of a recording 1489 * session, and it also helps eliminate the "recording" sound for 1490 * camcorder applications. 1491 * 1492 * If client does not set the start time offset, we fall back to 1493 * use the default initial delay value. 1494 */ 1495 int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL; 1496 if (startTimeOffsetUs < 0) { // Start time offset was not set 1497 startTimeOffsetUs = kInitialDelayTimeUs; 1498 } 1499 startTimeUs += startTimeOffsetUs; 1500 ALOGI("Start time offset: %lld us", startTimeOffsetUs); 1501 } 1502 1503 meta->setInt64(kKeyTime, startTimeUs); 1504 1505 status_t err = mSource->start(meta.get()); 1506 if (err != OK) { 1507 mDone = mReachedEOS = true; 1508 return err; 1509 } 1510 1511 pthread_attr_t attr; 1512 pthread_attr_init(&attr); 1513 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 1514 1515 mDone = false; 1516 mStarted = true; 1517 mTrackDurationUs = 0; 1518 mReachedEOS = false; 1519 mEstimatedTrackSizeBytes = 0; 1520 mNumStcoTableEntries = 0; 1521 mNumStssTableEntries = 0; 1522 mNumStscTableEntries = 0; 1523 mNumSttsTableEntries = 0; 1524 mNumCttsTableEntries = 0; 1525 mMdatSizeBytes = 0; 1526 1527 mMaxChunkDurationUs = 0; 1528 1529 pthread_create(&mThread, &attr, ThreadWrapper, this); 1530 pthread_attr_destroy(&attr); 1531 1532 return OK; 1533 } 1534 1535 status_t MPEG4Writer::Track::pause() { 1536 mPaused = true; 1537 return OK; 1538 } 1539 1540 status_t MPEG4Writer::Track::stop() { 1541 ALOGD("Stopping %s track", mIsAudio? "Audio": "Video"); 1542 if (!mStarted) { 1543 ALOGE("Stop() called but track is not started"); 1544 return ERROR_END_OF_STREAM; 1545 } 1546 1547 if (mDone) { 1548 return OK; 1549 } 1550 mDone = true; 1551 1552 void *dummy; 1553 pthread_join(mThread, &dummy); 1554 1555 status_t err = (status_t) dummy; 1556 1557 ALOGD("Stopping %s track source", mIsAudio? "Audio": "Video"); 1558 { 1559 status_t status = mSource->stop(); 1560 if (err == OK && status != OK && status != ERROR_END_OF_STREAM) { 1561 err = status; 1562 } 1563 } 1564 1565 ALOGD("%s track stopped", mIsAudio? "Audio": "Video"); 1566 return err; 1567 } 1568 1569 bool MPEG4Writer::Track::reachedEOS() { 1570 return mReachedEOS; 1571 } 1572 1573 // static 1574 void *MPEG4Writer::Track::ThreadWrapper(void *me) { 1575 Track *track = static_cast<Track *>(me); 1576 1577 status_t err = track->threadEntry(); 1578 return (void *) err; 1579 } 1580 1581 static void getNalUnitType(uint8_t byte, uint8_t* type) { 1582 ALOGV("getNalUnitType: %d", byte); 1583 1584 // nal_unit_type: 5-bit unsigned integer 1585 *type = (byte & 0x1F); 1586 } 1587 1588 static const uint8_t *findNextStartCode( 1589 const uint8_t *data, size_t length) { 1590 1591 ALOGV("findNextStartCode: %p %d", data, length); 1592 1593 size_t bytesLeft = length; 1594 while (bytesLeft > 4 && 1595 memcmp("\x00\x00\x00\x01", &data[length - bytesLeft], 4)) { 1596 --bytesLeft; 1597 } 1598 if (bytesLeft <= 4) { 1599 bytesLeft = 0; // Last parameter set 1600 } 1601 return &data[length - bytesLeft]; 1602 } 1603 1604 const uint8_t *MPEG4Writer::Track::parseParamSet( 1605 const uint8_t *data, size_t length, int type, size_t *paramSetLen) { 1606 1607 ALOGV("parseParamSet"); 1608 CHECK(type == kNalUnitTypeSeqParamSet || 1609 type == kNalUnitTypePicParamSet); 1610 1611 const uint8_t *nextStartCode = findNextStartCode(data, length); 1612 *paramSetLen = nextStartCode - data; 1613 if (*paramSetLen == 0) { 1614 ALOGE("Param set is malformed, since its length is 0"); 1615 return NULL; 1616 } 1617 1618 AVCParamSet paramSet(*paramSetLen, data); 1619 if (type == kNalUnitTypeSeqParamSet) { 1620 if (*paramSetLen < 4) { 1621 ALOGE("Seq parameter set malformed"); 1622 return NULL; 1623 } 1624 if (mSeqParamSets.empty()) { 1625 mProfileIdc = data[1]; 1626 mProfileCompatible = data[2]; 1627 mLevelIdc = data[3]; 1628 } else { 1629 if (mProfileIdc != data[1] || 1630 mProfileCompatible != data[2] || 1631 mLevelIdc != data[3]) { 1632 ALOGE("Inconsistent profile/level found in seq parameter sets"); 1633 return NULL; 1634 } 1635 } 1636 mSeqParamSets.push_back(paramSet); 1637 } else { 1638 mPicParamSets.push_back(paramSet); 1639 } 1640 return nextStartCode; 1641 } 1642 1643 status_t MPEG4Writer::Track::copyAVCCodecSpecificData( 1644 const uint8_t *data, size_t size) { 1645 ALOGV("copyAVCCodecSpecificData"); 1646 1647 // 2 bytes for each of the parameter set length field 1648 // plus the 7 bytes for the header 1649 if (size < 4 + 7) { 1650 ALOGE("Codec specific data length too short: %d", size); 1651 return ERROR_MALFORMED; 1652 } 1653 1654 mCodecSpecificDataSize = size; 1655 mCodecSpecificData = malloc(size); 1656 memcpy(mCodecSpecificData, data, size); 1657 return OK; 1658 } 1659 1660 status_t MPEG4Writer::Track::parseAVCCodecSpecificData( 1661 const uint8_t *data, size_t size) { 1662 1663 ALOGV("parseAVCCodecSpecificData"); 1664 // Data starts with a start code. 1665 // SPS and PPS are separated with start codes. 1666 // Also, SPS must come before PPS 1667 uint8_t type = kNalUnitTypeSeqParamSet; 1668 bool gotSps = false; 1669 bool gotPps = false; 1670 const uint8_t *tmp = data; 1671 const uint8_t *nextStartCode = data; 1672 size_t bytesLeft = size; 1673 size_t paramSetLen = 0; 1674 mCodecSpecificDataSize = 0; 1675 while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) { 1676 getNalUnitType(*(tmp + 4), &type); 1677 if (type == kNalUnitTypeSeqParamSet) { 1678 if (gotPps) { 1679 ALOGE("SPS must come before PPS"); 1680 return ERROR_MALFORMED; 1681 } 1682 if (!gotSps) { 1683 gotSps = true; 1684 } 1685 nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 1686 } else if (type == kNalUnitTypePicParamSet) { 1687 if (!gotSps) { 1688 ALOGE("SPS must come before PPS"); 1689 return ERROR_MALFORMED; 1690 } 1691 if (!gotPps) { 1692 gotPps = true; 1693 } 1694 nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 1695 } else { 1696 ALOGE("Only SPS and PPS Nal units are expected"); 1697 return ERROR_MALFORMED; 1698 } 1699 1700 if (nextStartCode == NULL) { 1701 return ERROR_MALFORMED; 1702 } 1703 1704 // Move on to find the next parameter set 1705 bytesLeft -= nextStartCode - tmp; 1706 tmp = nextStartCode; 1707 mCodecSpecificDataSize += (2 + paramSetLen); 1708 } 1709 1710 { 1711 // Check on the number of seq parameter sets 1712 size_t nSeqParamSets = mSeqParamSets.size(); 1713 if (nSeqParamSets == 0) { 1714 ALOGE("Cound not find sequence parameter set"); 1715 return ERROR_MALFORMED; 1716 } 1717 1718 if (nSeqParamSets > 0x1F) { 1719 ALOGE("Too many seq parameter sets (%d) found", nSeqParamSets); 1720 return ERROR_MALFORMED; 1721 } 1722 } 1723 1724 { 1725 // Check on the number of pic parameter sets 1726 size_t nPicParamSets = mPicParamSets.size(); 1727 if (nPicParamSets == 0) { 1728 ALOGE("Cound not find picture parameter set"); 1729 return ERROR_MALFORMED; 1730 } 1731 if (nPicParamSets > 0xFF) { 1732 ALOGE("Too many pic parameter sets (%d) found", nPicParamSets); 1733 return ERROR_MALFORMED; 1734 } 1735 } 1736 // FIXME: 1737 // Add chromat_format_idc, bit depth values, etc for AVC/h264 high profile and above 1738 // and remove #if 0 1739 #if 0 1740 { 1741 // Check on the profiles 1742 // These profiles requires additional parameter set extensions 1743 if (mProfileIdc == 100 || mProfileIdc == 110 || 1744 mProfileIdc == 122 || mProfileIdc == 144) { 1745 ALOGE("Sorry, no support for profile_idc: %d!", mProfileIdc); 1746 return BAD_VALUE; 1747 } 1748 } 1749 #endif 1750 return OK; 1751 } 1752 1753 status_t MPEG4Writer::Track::makeAVCCodecSpecificData( 1754 const uint8_t *data, size_t size) { 1755 1756 if (mCodecSpecificData != NULL) { 1757 ALOGE("Already have codec specific data"); 1758 return ERROR_MALFORMED; 1759 } 1760 1761 if (size < 4) { 1762 ALOGE("Codec specific data length too short: %d", size); 1763 return ERROR_MALFORMED; 1764 } 1765 1766 // Data is in the form of AVCCodecSpecificData 1767 if (memcmp("\x00\x00\x00\x01", data, 4)) { 1768 return copyAVCCodecSpecificData(data, size); 1769 } 1770 1771 if (parseAVCCodecSpecificData(data, size) != OK) { 1772 return ERROR_MALFORMED; 1773 } 1774 1775 // ISO 14496-15: AVC file format 1776 mCodecSpecificDataSize += 7; // 7 more bytes in the header 1777 mCodecSpecificData = malloc(mCodecSpecificDataSize); 1778 uint8_t *header = (uint8_t *)mCodecSpecificData; 1779 header[0] = 1; // version 1780 header[1] = mProfileIdc; // profile indication 1781 header[2] = mProfileCompatible; // profile compatibility 1782 header[3] = mLevelIdc; 1783 1784 // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne 1785 if (mOwner->useNalLengthFour()) { 1786 header[4] = 0xfc | 3; // length size == 4 bytes 1787 } else { 1788 header[4] = 0xfc | 1; // length size == 2 bytes 1789 } 1790 1791 // 3-bit '111' followed by 5-bit numSequenceParameterSets 1792 int nSequenceParamSets = mSeqParamSets.size(); 1793 header[5] = 0xe0 | nSequenceParamSets; 1794 header += 6; 1795 for (List<AVCParamSet>::iterator it = mSeqParamSets.begin(); 1796 it != mSeqParamSets.end(); ++it) { 1797 // 16-bit sequence parameter set length 1798 uint16_t seqParamSetLength = it->mLength; 1799 header[0] = seqParamSetLength >> 8; 1800 header[1] = seqParamSetLength & 0xff; 1801 1802 // SPS NAL unit (sequence parameter length bytes) 1803 memcpy(&header[2], it->mData, seqParamSetLength); 1804 header += (2 + seqParamSetLength); 1805 } 1806 1807 // 8-bit nPictureParameterSets 1808 int nPictureParamSets = mPicParamSets.size(); 1809 header[0] = nPictureParamSets; 1810 header += 1; 1811 for (List<AVCParamSet>::iterator it = mPicParamSets.begin(); 1812 it != mPicParamSets.end(); ++it) { 1813 // 16-bit picture parameter set length 1814 uint16_t picParamSetLength = it->mLength; 1815 header[0] = picParamSetLength >> 8; 1816 header[1] = picParamSetLength & 0xff; 1817 1818 // PPS Nal unit (picture parameter set length bytes) 1819 memcpy(&header[2], it->mData, picParamSetLength); 1820 header += (2 + picParamSetLength); 1821 } 1822 1823 return OK; 1824 } 1825 1826 /* 1827 * Updates the drift time from the audio track so that 1828 * the video track can get the updated drift time information 1829 * from the file writer. The fluctuation of the drift time of the audio 1830 * encoding path is smoothed out with a simple filter by giving a larger 1831 * weight to more recently drift time. The filter coefficients, 0.5 and 0.5, 1832 * are heuristically determined. 1833 */ 1834 void MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) { 1835 int64_t driftTimeUs = 0; 1836 if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) { 1837 int64_t prevDriftTimeUs = mOwner->getDriftTimeUs(); 1838 int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1; 1839 mOwner->setDriftTimeUs(timeUs); 1840 } 1841 } 1842 1843 status_t MPEG4Writer::Track::threadEntry() { 1844 int32_t count = 0; 1845 const int64_t interleaveDurationUs = mOwner->interleaveDuration(); 1846 const bool hasMultipleTracks = (mOwner->numTracks() > 1); 1847 int64_t chunkTimestampUs = 0; 1848 int32_t nChunks = 0; 1849 int32_t nZeroLengthFrames = 0; 1850 int64_t lastTimestampUs = 0; // Previous sample time stamp 1851 int64_t lastDurationUs = 0; // Between the previous two samples 1852 int64_t currDurationTicks = 0; // Timescale based ticks 1853 int64_t lastDurationTicks = 0; // Timescale based ticks 1854 int32_t sampleCount = 1; // Sample count in the current stts table entry 1855 uint32_t previousSampleSize = 0; // Size of the previous sample 1856 int64_t previousPausedDurationUs = 0; 1857 int64_t timestampUs = 0; 1858 int64_t cttsOffsetTimeUs = 0; 1859 int64_t currCttsOffsetTimeTicks = 0; // Timescale based ticks 1860 int64_t lastCttsOffsetTimeTicks = -1; // Timescale based ticks 1861 int32_t cttsSampleCount = 0; // Sample count in the current ctts table entry 1862 1863 if (mIsAudio) { 1864 prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0); 1865 } else { 1866 prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0); 1867 } 1868 androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO); 1869 1870 sp<MetaData> meta_data; 1871 1872 mNumSamples = 0; 1873 status_t err = OK; 1874 MediaBuffer *buffer; 1875 while (!mDone && (err = mSource->read(&buffer)) == OK) { 1876 if (buffer->range_length() == 0) { 1877 buffer->release(); 1878 buffer = NULL; 1879 ++nZeroLengthFrames; 1880 continue; 1881 } 1882 1883 // If the codec specific data has not been received yet, delay pause. 1884 // After the codec specific data is received, discard what we received 1885 // when the track is to be paused. 1886 if (mPaused && !mResumed) { 1887 buffer->release(); 1888 buffer = NULL; 1889 continue; 1890 } 1891 1892 ++count; 1893 1894 int32_t isCodecConfig; 1895 if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig) 1896 && isCodecConfig) { 1897 CHECK(!mGotAllCodecSpecificData); 1898 1899 if (mIsAvc) { 1900 status_t err = makeAVCCodecSpecificData( 1901 (const uint8_t *)buffer->data() 1902 + buffer->range_offset(), 1903 buffer->range_length()); 1904 CHECK_EQ((status_t)OK, err); 1905 } else if (mIsMPEG4) { 1906 mCodecSpecificDataSize = buffer->range_length(); 1907 mCodecSpecificData = malloc(mCodecSpecificDataSize); 1908 memcpy(mCodecSpecificData, 1909 (const uint8_t *)buffer->data() 1910 + buffer->range_offset(), 1911 buffer->range_length()); 1912 } 1913 1914 buffer->release(); 1915 buffer = NULL; 1916 1917 mGotAllCodecSpecificData = true; 1918 continue; 1919 } 1920 1921 // Make a deep copy of the MediaBuffer and Metadata and release 1922 // the original as soon as we can 1923 MediaBuffer *copy = new MediaBuffer(buffer->range_length()); 1924 memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(), 1925 buffer->range_length()); 1926 copy->set_range(0, buffer->range_length()); 1927 meta_data = new MetaData(*buffer->meta_data().get()); 1928 buffer->release(); 1929 buffer = NULL; 1930 1931 if (mIsAvc) StripStartcode(copy); 1932 1933 size_t sampleSize = copy->range_length(); 1934 if (mIsAvc) { 1935 if (mOwner->useNalLengthFour()) { 1936 sampleSize += 4; 1937 } else { 1938 sampleSize += 2; 1939 } 1940 } 1941 1942 // Max file size or duration handling 1943 mMdatSizeBytes += sampleSize; 1944 updateTrackSizeEstimate(); 1945 1946 if (mOwner->exceedsFileSizeLimit()) { 1947 mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0); 1948 break; 1949 } 1950 if (mOwner->exceedsFileDurationLimit()) { 1951 mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0); 1952 break; 1953 } 1954 1955 1956 int32_t isSync = false; 1957 meta_data->findInt32(kKeyIsSyncFrame, &isSync); 1958 CHECK(meta_data->findInt64(kKeyTime, ×tampUs)); 1959 1960 //////////////////////////////////////////////////////////////////////////////// 1961 if (mNumSamples == 0) { 1962 mFirstSampleTimeRealUs = systemTime() / 1000; 1963 mStartTimestampUs = timestampUs; 1964 mOwner->setStartTimestampUs(mStartTimestampUs); 1965 previousPausedDurationUs = mStartTimestampUs; 1966 } 1967 1968 if (mResumed) { 1969 int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs; 1970 CHECK_GE(durExcludingEarlierPausesUs, 0ll); 1971 int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs; 1972 CHECK_GE(pausedDurationUs, lastDurationUs); 1973 previousPausedDurationUs += pausedDurationUs - lastDurationUs; 1974 mResumed = false; 1975 } 1976 1977 timestampUs -= previousPausedDurationUs; 1978 CHECK_GE(timestampUs, 0ll); 1979 if (!mIsAudio) { 1980 /* 1981 * Composition time: timestampUs 1982 * Decoding time: decodingTimeUs 1983 * Composition time offset = composition time - decoding time 1984 */ 1985 int64_t decodingTimeUs; 1986 CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs)); 1987 decodingTimeUs -= previousPausedDurationUs; 1988 cttsOffsetTimeUs = 1989 timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs; 1990 CHECK_GE(cttsOffsetTimeUs, 0ll); 1991 timestampUs = decodingTimeUs; 1992 ALOGV("decoding time: %lld and ctts offset time: %lld", 1993 timestampUs, cttsOffsetTimeUs); 1994 1995 // Update ctts box table if necessary 1996 currCttsOffsetTimeTicks = 1997 (cttsOffsetTimeUs * mTimeScale + 500000LL) / 1000000LL; 1998 CHECK_LE(currCttsOffsetTimeTicks, 0x0FFFFFFFFLL); 1999 if (mNumSamples == 0) { 2000 // Force the first ctts table entry to have one single entry 2001 // so that we can do adjustment for the initial track start 2002 // time offset easily in writeCttsBox(). 2003 lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks; 2004 addOneCttsTableEntry(1, currCttsOffsetTimeTicks); 2005 cttsSampleCount = 0; // No sample in ctts box is pending 2006 } else { 2007 if (currCttsOffsetTimeTicks != lastCttsOffsetTimeTicks) { 2008 addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks); 2009 lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks; 2010 cttsSampleCount = 1; // One sample in ctts box is pending 2011 } else { 2012 ++cttsSampleCount; 2013 } 2014 } 2015 2016 // Update ctts time offset range 2017 if (mNumSamples == 0) { 2018 mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2019 mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2020 } else { 2021 if (currCttsOffsetTimeTicks > mMaxCttsOffsetTimeUs) { 2022 mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2023 } else if (currCttsOffsetTimeTicks < mMinCttsOffsetTimeUs) { 2024 mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2025 } 2026 } 2027 2028 } 2029 2030 if (mIsRealTimeRecording) { 2031 if (mIsAudio) { 2032 updateDriftTime(meta_data); 2033 } 2034 } 2035 2036 CHECK_GE(timestampUs, 0ll); 2037 ALOGV("%s media time stamp: %lld and previous paused duration %lld", 2038 mIsAudio? "Audio": "Video", timestampUs, previousPausedDurationUs); 2039 if (timestampUs > mTrackDurationUs) { 2040 mTrackDurationUs = timestampUs; 2041 } 2042 2043 // We need to use the time scale based ticks, rather than the 2044 // timestamp itself to determine whether we have to use a new 2045 // stts entry, since we may have rounding errors. 2046 // The calculation is intended to reduce the accumulated 2047 // rounding errors. 2048 currDurationTicks = 2049 ((timestampUs * mTimeScale + 500000LL) / 1000000LL - 2050 (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL); 2051 CHECK_GE(currDurationTicks, 0ll); 2052 2053 if ((mNumSamples % kSampleArraySize) == 0) { 2054 uint32_t *arr = new uint32_t[kSampleArraySize]; 2055 CHECK(arr != NULL); 2056 mSampleSizes.push_back(arr); 2057 mCurrentSampleSizeArr = arr; 2058 } 2059 2060 mCurrentSampleSizeArr[mNumSamples % kSampleArraySize] = htonl(sampleSize); 2061 ++mNumSamples; 2062 if (mNumSamples > 2) { 2063 2064 // Force the first sample to have its own stts entry so that 2065 // we can adjust its value later to maintain the A/V sync. 2066 if (mNumSamples == 3 || currDurationTicks != lastDurationTicks) { 2067 addOneSttsTableEntry(sampleCount, lastDurationTicks); 2068 sampleCount = 1; 2069 } else { 2070 ++sampleCount; 2071 } 2072 2073 } 2074 if (mSamplesHaveSameSize) { 2075 if (mNumSamples >= 2 && previousSampleSize != sampleSize) { 2076 mSamplesHaveSameSize = false; 2077 } 2078 previousSampleSize = sampleSize; 2079 } 2080 ALOGV("%s timestampUs/lastTimestampUs: %lld/%lld", 2081 mIsAudio? "Audio": "Video", timestampUs, lastTimestampUs); 2082 lastDurationUs = timestampUs - lastTimestampUs; 2083 lastDurationTicks = currDurationTicks; 2084 lastTimestampUs = timestampUs; 2085 2086 if (isSync != 0) { 2087 addOneStssTableEntry(mNumSamples); 2088 } 2089 2090 if (mTrackingProgressStatus) { 2091 if (mPreviousTrackTimeUs <= 0) { 2092 mPreviousTrackTimeUs = mStartTimestampUs; 2093 } 2094 trackProgressStatus(timestampUs); 2095 } 2096 if (!hasMultipleTracks) { 2097 off64_t offset = mIsAvc? mOwner->addLengthPrefixedSample_l(copy) 2098 : mOwner->addSample_l(copy); 2099 if (mChunkOffsets.empty()) { 2100 addChunkOffset(offset); 2101 } 2102 copy->release(); 2103 copy = NULL; 2104 continue; 2105 } 2106 2107 mChunkSamples.push_back(copy); 2108 if (interleaveDurationUs == 0) { 2109 addOneStscTableEntry(++nChunks, 1); 2110 bufferChunk(timestampUs); 2111 } else { 2112 if (chunkTimestampUs == 0) { 2113 chunkTimestampUs = timestampUs; 2114 } else { 2115 int64_t chunkDurationUs = timestampUs - chunkTimestampUs; 2116 if (chunkDurationUs > interleaveDurationUs) { 2117 if (chunkDurationUs > mMaxChunkDurationUs) { 2118 mMaxChunkDurationUs = chunkDurationUs; 2119 } 2120 ++nChunks; 2121 if (nChunks == 1 || // First chunk 2122 (--(mStscTableEntries.end()))->samplesPerChunk != 2123 mChunkSamples.size()) { 2124 addOneStscTableEntry(nChunks, mChunkSamples.size()); 2125 } 2126 bufferChunk(timestampUs); 2127 chunkTimestampUs = timestampUs; 2128 } 2129 } 2130 } 2131 2132 } 2133 2134 if (isTrackMalFormed()) { 2135 err = ERROR_MALFORMED; 2136 } 2137 2138 mOwner->trackProgressStatus(mTrackId, -1, err); 2139 2140 // Last chunk 2141 if (!hasMultipleTracks) { 2142 addOneStscTableEntry(1, mNumSamples); 2143 } else if (!mChunkSamples.empty()) { 2144 addOneStscTableEntry(++nChunks, mChunkSamples.size()); 2145 bufferChunk(timestampUs); 2146 } 2147 2148 // We don't really know how long the last frame lasts, since 2149 // there is no frame time after it, just repeat the previous 2150 // frame's duration. 2151 if (mNumSamples == 1) { 2152 lastDurationUs = 0; // A single sample's duration 2153 lastDurationTicks = 0; 2154 } else { 2155 ++sampleCount; // Count for the last sample 2156 } 2157 2158 if (mNumSamples <= 2) { 2159 addOneSttsTableEntry(1, lastDurationTicks); 2160 if (sampleCount - 1 > 0) { 2161 addOneSttsTableEntry(sampleCount - 1, lastDurationTicks); 2162 } 2163 } else { 2164 addOneSttsTableEntry(sampleCount, lastDurationTicks); 2165 } 2166 2167 // The last ctts box may not have been written yet, and this 2168 // is to make sure that we write out the last ctts box. 2169 if (currCttsOffsetTimeTicks == lastCttsOffsetTimeTicks) { 2170 if (cttsSampleCount > 0) { 2171 addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks); 2172 } 2173 } 2174 2175 mTrackDurationUs += lastDurationUs; 2176 mReachedEOS = true; 2177 2178 sendTrackSummary(hasMultipleTracks); 2179 2180 ALOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s", 2181 count, nZeroLengthFrames, mNumSamples, mIsAudio? "audio": "video"); 2182 if (mIsAudio) { 2183 ALOGI("Audio track drift time: %lld us", mOwner->getDriftTimeUs()); 2184 } 2185 2186 if (err == ERROR_END_OF_STREAM) { 2187 return OK; 2188 } 2189 return err; 2190 } 2191 2192 bool MPEG4Writer::Track::isTrackMalFormed() const { 2193 if (mSampleSizes.empty()) { // no samples written 2194 ALOGE("The number of recorded samples is 0"); 2195 return true; 2196 } 2197 2198 if (!mIsAudio && mNumStssTableEntries == 0) { // no sync frames for video 2199 ALOGE("There are no sync frames for video track"); 2200 return true; 2201 } 2202 2203 if (OK != checkCodecSpecificData()) { // no codec specific data 2204 return true; 2205 } 2206 2207 return false; 2208 } 2209 2210 void MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) { 2211 2212 // Send track summary only if test mode is enabled. 2213 if (!isTestModeEnabled()) { 2214 return; 2215 } 2216 2217 int trackNum = (mTrackId << 28); 2218 2219 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2220 trackNum | MEDIA_RECORDER_TRACK_INFO_TYPE, 2221 mIsAudio? 0: 1); 2222 2223 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2224 trackNum | MEDIA_RECORDER_TRACK_INFO_DURATION_MS, 2225 mTrackDurationUs / 1000); 2226 2227 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2228 trackNum | MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES, 2229 mNumSamples); 2230 2231 { 2232 // The system delay time excluding the requested initial delay that 2233 // is used to eliminate the recording sound. 2234 int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL; 2235 if (startTimeOffsetUs < 0) { // Start time offset was not set 2236 startTimeOffsetUs = kInitialDelayTimeUs; 2237 } 2238 int64_t initialDelayUs = 2239 mFirstSampleTimeRealUs - mStartTimeRealUs - startTimeOffsetUs; 2240 2241 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2242 trackNum | MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS, 2243 (initialDelayUs) / 1000); 2244 } 2245 2246 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2247 trackNum | MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES, 2248 mMdatSizeBytes / 1024); 2249 2250 if (hasMultipleTracks) { 2251 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2252 trackNum | MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS, 2253 mMaxChunkDurationUs / 1000); 2254 2255 int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 2256 if (mStartTimestampUs != moovStartTimeUs) { 2257 int64_t startTimeOffsetUs = mStartTimestampUs - moovStartTimeUs; 2258 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2259 trackNum | MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS, 2260 startTimeOffsetUs / 1000); 2261 } 2262 } 2263 } 2264 2265 void MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) { 2266 ALOGV("trackProgressStatus: %lld us", timeUs); 2267 if (mTrackEveryTimeDurationUs > 0 && 2268 timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) { 2269 ALOGV("Fire time tracking progress status at %lld us", timeUs); 2270 mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err); 2271 mPreviousTrackTimeUs = timeUs; 2272 } 2273 } 2274 2275 void MPEG4Writer::trackProgressStatus( 2276 size_t trackId, int64_t timeUs, status_t err) { 2277 Mutex::Autolock lock(mLock); 2278 int32_t trackNum = (trackId << 28); 2279 2280 // Error notification 2281 // Do not consider ERROR_END_OF_STREAM an error 2282 if (err != OK && err != ERROR_END_OF_STREAM) { 2283 notify(MEDIA_RECORDER_TRACK_EVENT_ERROR, 2284 trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL, 2285 err); 2286 return; 2287 } 2288 2289 if (timeUs == -1) { 2290 // Send completion notification 2291 notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2292 trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS, 2293 err); 2294 } else { 2295 // Send progress status 2296 notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2297 trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME, 2298 timeUs / 1000); 2299 } 2300 } 2301 2302 void MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) { 2303 ALOGV("setDriftTimeUs: %lld us", driftTimeUs); 2304 Mutex::Autolock autolock(mLock); 2305 mDriftTimeUs = driftTimeUs; 2306 } 2307 2308 int64_t MPEG4Writer::getDriftTimeUs() { 2309 ALOGV("getDriftTimeUs: %lld us", mDriftTimeUs); 2310 Mutex::Autolock autolock(mLock); 2311 return mDriftTimeUs; 2312 } 2313 2314 bool MPEG4Writer::useNalLengthFour() { 2315 return mUse4ByteNalLength; 2316 } 2317 2318 void MPEG4Writer::Track::bufferChunk(int64_t timestampUs) { 2319 ALOGV("bufferChunk"); 2320 2321 Chunk chunk(this, timestampUs, mChunkSamples); 2322 mOwner->bufferChunk(chunk); 2323 mChunkSamples.clear(); 2324 } 2325 2326 int64_t MPEG4Writer::Track::getDurationUs() const { 2327 return mTrackDurationUs; 2328 } 2329 2330 int64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const { 2331 return mEstimatedTrackSizeBytes; 2332 } 2333 2334 status_t MPEG4Writer::Track::checkCodecSpecificData() const { 2335 const char *mime; 2336 CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 2337 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) || 2338 !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) || 2339 !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 2340 if (!mCodecSpecificData || 2341 mCodecSpecificDataSize <= 0) { 2342 ALOGE("Missing codec specific data"); 2343 return ERROR_MALFORMED; 2344 } 2345 } else { 2346 if (mCodecSpecificData || 2347 mCodecSpecificDataSize > 0) { 2348 ALOGE("Unexepected codec specific data found"); 2349 return ERROR_MALFORMED; 2350 } 2351 } 2352 return OK; 2353 } 2354 2355 void MPEG4Writer::Track::writeTrackHeader(bool use32BitOffset) { 2356 2357 ALOGV("%s track time scale: %d", 2358 mIsAudio? "Audio": "Video", mTimeScale); 2359 2360 time_t now = time(NULL); 2361 mOwner->beginBox("trak"); 2362 writeTkhdBox(now); 2363 mOwner->beginBox("mdia"); 2364 writeMdhdBox(now); 2365 writeHdlrBox(); 2366 mOwner->beginBox("minf"); 2367 if (mIsAudio) { 2368 writeSmhdBox(); 2369 } else { 2370 writeVmhdBox(); 2371 } 2372 writeDinfBox(); 2373 writeStblBox(use32BitOffset); 2374 mOwner->endBox(); // minf 2375 mOwner->endBox(); // mdia 2376 mOwner->endBox(); // trak 2377 } 2378 2379 void MPEG4Writer::Track::writeStblBox(bool use32BitOffset) { 2380 mOwner->beginBox("stbl"); 2381 mOwner->beginBox("stsd"); 2382 mOwner->writeInt32(0); // version=0, flags=0 2383 mOwner->writeInt32(1); // entry count 2384 if (mIsAudio) { 2385 writeAudioFourCCBox(); 2386 } else { 2387 writeVideoFourCCBox(); 2388 } 2389 mOwner->endBox(); // stsd 2390 writeSttsBox(); 2391 writeCttsBox(); 2392 if (!mIsAudio) { 2393 writeStssBox(); 2394 } 2395 writeStszBox(); 2396 writeStscBox(); 2397 writeStcoBox(use32BitOffset); 2398 mOwner->endBox(); // stbl 2399 } 2400 2401 void MPEG4Writer::Track::writeVideoFourCCBox() { 2402 const char *mime; 2403 bool success = mMeta->findCString(kKeyMIMEType, &mime); 2404 CHECK(success); 2405 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 2406 mOwner->beginBox("mp4v"); 2407 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 2408 mOwner->beginBox("s263"); 2409 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 2410 mOwner->beginBox("avc1"); 2411 } else { 2412 ALOGE("Unknown mime type '%s'.", mime); 2413 CHECK(!"should not be here, unknown mime type."); 2414 } 2415 2416 mOwner->writeInt32(0); // reserved 2417 mOwner->writeInt16(0); // reserved 2418 mOwner->writeInt16(1); // data ref index 2419 mOwner->writeInt16(0); // predefined 2420 mOwner->writeInt16(0); // reserved 2421 mOwner->writeInt32(0); // predefined 2422 mOwner->writeInt32(0); // predefined 2423 mOwner->writeInt32(0); // predefined 2424 2425 int32_t width, height; 2426 success = mMeta->findInt32(kKeyWidth, &width); 2427 success = success && mMeta->findInt32(kKeyHeight, &height); 2428 CHECK(success); 2429 2430 mOwner->writeInt16(width); 2431 mOwner->writeInt16(height); 2432 mOwner->writeInt32(0x480000); // horiz resolution 2433 mOwner->writeInt32(0x480000); // vert resolution 2434 mOwner->writeInt32(0); // reserved 2435 mOwner->writeInt16(1); // frame count 2436 mOwner->write(" ", 32); 2437 mOwner->writeInt16(0x18); // depth 2438 mOwner->writeInt16(-1); // predefined 2439 2440 CHECK_LT(23 + mCodecSpecificDataSize, 128); 2441 2442 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 2443 writeMp4vEsdsBox(); 2444 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 2445 writeD263Box(); 2446 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 2447 writeAvccBox(); 2448 } 2449 2450 writePaspBox(); 2451 mOwner->endBox(); // mp4v, s263 or avc1 2452 } 2453 2454 void MPEG4Writer::Track::writeAudioFourCCBox() { 2455 const char *mime; 2456 bool success = mMeta->findCString(kKeyMIMEType, &mime); 2457 CHECK(success); 2458 const char *fourcc = NULL; 2459 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) { 2460 fourcc = "samr"; 2461 } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 2462 fourcc = "sawb"; 2463 } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 2464 fourcc = "mp4a"; 2465 } else { 2466 ALOGE("Unknown mime type '%s'.", mime); 2467 CHECK(!"should not be here, unknown mime type."); 2468 } 2469 2470 mOwner->beginBox(fourcc); // audio format 2471 mOwner->writeInt32(0); // reserved 2472 mOwner->writeInt16(0); // reserved 2473 mOwner->writeInt16(0x1); // data ref index 2474 mOwner->writeInt32(0); // reserved 2475 mOwner->writeInt32(0); // reserved 2476 int32_t nChannels; 2477 CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels)); 2478 mOwner->writeInt16(nChannels); // channel count 2479 mOwner->writeInt16(16); // sample size 2480 mOwner->writeInt16(0); // predefined 2481 mOwner->writeInt16(0); // reserved 2482 2483 int32_t samplerate; 2484 success = mMeta->findInt32(kKeySampleRate, &samplerate); 2485 CHECK(success); 2486 mOwner->writeInt32(samplerate << 16); 2487 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 2488 writeMp4aEsdsBox(); 2489 } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) || 2490 !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 2491 writeDamrBox(); 2492 } 2493 mOwner->endBox(); 2494 } 2495 2496 void MPEG4Writer::Track::writeMp4aEsdsBox() { 2497 mOwner->beginBox("esds"); 2498 CHECK(mCodecSpecificData); 2499 CHECK_GT(mCodecSpecificDataSize, 0); 2500 2501 // Make sure all sizes encode to a single byte. 2502 CHECK_LT(mCodecSpecificDataSize + 23, 128); 2503 2504 mOwner->writeInt32(0); // version=0, flags=0 2505 mOwner->writeInt8(0x03); // ES_DescrTag 2506 mOwner->writeInt8(23 + mCodecSpecificDataSize); 2507 mOwner->writeInt16(0x0000);// ES_ID 2508 mOwner->writeInt8(0x00); 2509 2510 mOwner->writeInt8(0x04); // DecoderConfigDescrTag 2511 mOwner->writeInt8(15 + mCodecSpecificDataSize); 2512 mOwner->writeInt8(0x40); // objectTypeIndication ISO/IEC 14492-2 2513 mOwner->writeInt8(0x15); // streamType AudioStream 2514 2515 mOwner->writeInt16(0x03); // XXX 2516 mOwner->writeInt8(0x00); // buffer size 24-bit 2517 mOwner->writeInt32(96000); // max bit rate 2518 mOwner->writeInt32(96000); // avg bit rate 2519 2520 mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 2521 mOwner->writeInt8(mCodecSpecificDataSize); 2522 mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2523 2524 static const uint8_t kData2[] = { 2525 0x06, // SLConfigDescriptorTag 2526 0x01, 2527 0x02 2528 }; 2529 mOwner->write(kData2, sizeof(kData2)); 2530 2531 mOwner->endBox(); // esds 2532 } 2533 2534 void MPEG4Writer::Track::writeMp4vEsdsBox() { 2535 CHECK(mCodecSpecificData); 2536 CHECK_GT(mCodecSpecificDataSize, 0); 2537 mOwner->beginBox("esds"); 2538 2539 mOwner->writeInt32(0); // version=0, flags=0 2540 2541 mOwner->writeInt8(0x03); // ES_DescrTag 2542 mOwner->writeInt8(23 + mCodecSpecificDataSize); 2543 mOwner->writeInt16(0x0000); // ES_ID 2544 mOwner->writeInt8(0x1f); 2545 2546 mOwner->writeInt8(0x04); // DecoderConfigDescrTag 2547 mOwner->writeInt8(15 + mCodecSpecificDataSize); 2548 mOwner->writeInt8(0x20); // objectTypeIndication ISO/IEC 14492-2 2549 mOwner->writeInt8(0x11); // streamType VisualStream 2550 2551 static const uint8_t kData[] = { 2552 0x01, 0x77, 0x00, 2553 0x00, 0x03, 0xe8, 0x00, 2554 0x00, 0x03, 0xe8, 0x00 2555 }; 2556 mOwner->write(kData, sizeof(kData)); 2557 2558 mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 2559 2560 mOwner->writeInt8(mCodecSpecificDataSize); 2561 mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2562 2563 static const uint8_t kData2[] = { 2564 0x06, // SLConfigDescriptorTag 2565 0x01, 2566 0x02 2567 }; 2568 mOwner->write(kData2, sizeof(kData2)); 2569 2570 mOwner->endBox(); // esds 2571 } 2572 2573 void MPEG4Writer::Track::writeTkhdBox(time_t now) { 2574 mOwner->beginBox("tkhd"); 2575 // Flags = 7 to indicate that the track is enabled, and 2576 // part of the presentation 2577 mOwner->writeInt32(0x07); // version=0, flags=7 2578 mOwner->writeInt32(now); // creation time 2579 mOwner->writeInt32(now); // modification time 2580 mOwner->writeInt32(mTrackId + 1); // track id starts with 1 2581 mOwner->writeInt32(0); // reserved 2582 int64_t trakDurationUs = getDurationUs(); 2583 int32_t mvhdTimeScale = mOwner->getTimeScale(); 2584 int32_t tkhdDuration = 2585 (trakDurationUs * mvhdTimeScale + 5E5) / 1E6; 2586 mOwner->writeInt32(tkhdDuration); // in mvhd timescale 2587 mOwner->writeInt32(0); // reserved 2588 mOwner->writeInt32(0); // reserved 2589 mOwner->writeInt16(0); // layer 2590 mOwner->writeInt16(0); // alternate group 2591 mOwner->writeInt16(mIsAudio ? 0x100 : 0); // volume 2592 mOwner->writeInt16(0); // reserved 2593 2594 mOwner->writeCompositionMatrix(mRotation); // matrix 2595 2596 if (mIsAudio) { 2597 mOwner->writeInt32(0); 2598 mOwner->writeInt32(0); 2599 } else { 2600 int32_t width, height; 2601 bool success = mMeta->findInt32(kKeyWidth, &width); 2602 success = success && mMeta->findInt32(kKeyHeight, &height); 2603 CHECK(success); 2604 2605 mOwner->writeInt32(width << 16); // 32-bit fixed-point value 2606 mOwner->writeInt32(height << 16); // 32-bit fixed-point value 2607 } 2608 mOwner->endBox(); // tkhd 2609 } 2610 2611 void MPEG4Writer::Track::writeVmhdBox() { 2612 mOwner->beginBox("vmhd"); 2613 mOwner->writeInt32(0x01); // version=0, flags=1 2614 mOwner->writeInt16(0); // graphics mode 2615 mOwner->writeInt16(0); // opcolor 2616 mOwner->writeInt16(0); 2617 mOwner->writeInt16(0); 2618 mOwner->endBox(); 2619 } 2620 2621 void MPEG4Writer::Track::writeSmhdBox() { 2622 mOwner->beginBox("smhd"); 2623 mOwner->writeInt32(0); // version=0, flags=0 2624 mOwner->writeInt16(0); // balance 2625 mOwner->writeInt16(0); // reserved 2626 mOwner->endBox(); 2627 } 2628 2629 void MPEG4Writer::Track::writeHdlrBox() { 2630 mOwner->beginBox("hdlr"); 2631 mOwner->writeInt32(0); // version=0, flags=0 2632 mOwner->writeInt32(0); // component type: should be mhlr 2633 mOwner->writeFourcc(mIsAudio ? "soun" : "vide"); // component subtype 2634 mOwner->writeInt32(0); // reserved 2635 mOwner->writeInt32(0); // reserved 2636 mOwner->writeInt32(0); // reserved 2637 // Removing "r" for the name string just makes the string 4 byte aligned 2638 mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle"); // name 2639 mOwner->endBox(); 2640 } 2641 2642 void MPEG4Writer::Track::writeMdhdBox(time_t now) { 2643 int64_t trakDurationUs = getDurationUs(); 2644 mOwner->beginBox("mdhd"); 2645 mOwner->writeInt32(0); // version=0, flags=0 2646 mOwner->writeInt32(now); // creation time 2647 mOwner->writeInt32(now); // modification time 2648 mOwner->writeInt32(mTimeScale); // media timescale 2649 int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6; 2650 mOwner->writeInt32(mdhdDuration); // use media timescale 2651 // Language follows the three letter standard ISO-639-2/T 2652 // 'e', 'n', 'g' for "English", for instance. 2653 // Each character is packed as the difference between its ASCII value and 0x60. 2654 // For "English", these are 00101, 01110, 00111. 2655 // XXX: Where is the padding bit located: 0x15C7? 2656 mOwner->writeInt16(0); // language code 2657 mOwner->writeInt16(0); // predefined 2658 mOwner->endBox(); 2659 } 2660 2661 void MPEG4Writer::Track::writeDamrBox() { 2662 // 3gpp2 Spec AMRSampleEntry fields 2663 mOwner->beginBox("damr"); 2664 mOwner->writeCString(" "); // vendor: 4 bytes 2665 mOwner->writeInt8(0); // decoder version 2666 mOwner->writeInt16(0x83FF); // mode set: all enabled 2667 mOwner->writeInt8(0); // mode change period 2668 mOwner->writeInt8(1); // frames per sample 2669 mOwner->endBox(); 2670 } 2671 2672 void MPEG4Writer::Track::writeUrlBox() { 2673 // The table index here refers to the sample description index 2674 // in the sample table entries. 2675 mOwner->beginBox("url "); 2676 mOwner->writeInt32(1); // version=0, flags=1 (self-contained) 2677 mOwner->endBox(); // url 2678 } 2679 2680 void MPEG4Writer::Track::writeDrefBox() { 2681 mOwner->beginBox("dref"); 2682 mOwner->writeInt32(0); // version=0, flags=0 2683 mOwner->writeInt32(1); // entry count (either url or urn) 2684 writeUrlBox(); 2685 mOwner->endBox(); // dref 2686 } 2687 2688 void MPEG4Writer::Track::writeDinfBox() { 2689 mOwner->beginBox("dinf"); 2690 writeDrefBox(); 2691 mOwner->endBox(); // dinf 2692 } 2693 2694 void MPEG4Writer::Track::writeAvccBox() { 2695 CHECK(mCodecSpecificData); 2696 CHECK_GE(mCodecSpecificDataSize, 5); 2697 2698 // Patch avcc's lengthSize field to match the number 2699 // of bytes we use to indicate the size of a nal unit. 2700 uint8_t *ptr = (uint8_t *)mCodecSpecificData; 2701 ptr[4] = (ptr[4] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1); 2702 mOwner->beginBox("avcC"); 2703 mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2704 mOwner->endBox(); // avcC 2705 } 2706 2707 void MPEG4Writer::Track::writeD263Box() { 2708 mOwner->beginBox("d263"); 2709 mOwner->writeInt32(0); // vendor 2710 mOwner->writeInt8(0); // decoder version 2711 mOwner->writeInt8(10); // level: 10 2712 mOwner->writeInt8(0); // profile: 0 2713 mOwner->endBox(); // d263 2714 } 2715 2716 // This is useful if the pixel is not square 2717 void MPEG4Writer::Track::writePaspBox() { 2718 mOwner->beginBox("pasp"); 2719 mOwner->writeInt32(1 << 16); // hspacing 2720 mOwner->writeInt32(1 << 16); // vspacing 2721 mOwner->endBox(); // pasp 2722 } 2723 2724 int32_t MPEG4Writer::Track::getStartTimeOffsetScaledTime() const { 2725 int64_t trackStartTimeOffsetUs = 0; 2726 int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 2727 if (mStartTimestampUs != moovStartTimeUs) { 2728 CHECK_GT(mStartTimestampUs, moovStartTimeUs); 2729 trackStartTimeOffsetUs = mStartTimestampUs - moovStartTimeUs; 2730 } 2731 return (trackStartTimeOffsetUs * mTimeScale + 500000LL) / 1000000LL; 2732 } 2733 2734 void MPEG4Writer::Track::writeSttsBox() { 2735 mOwner->beginBox("stts"); 2736 mOwner->writeInt32(0); // version=0, flags=0 2737 mOwner->writeInt32(mNumSttsTableEntries); 2738 2739 // Compensate for small start time difference from different media tracks 2740 List<SttsTableEntry>::iterator it = mSttsTableEntries.begin(); 2741 CHECK(it != mSttsTableEntries.end() && it->sampleCount == 1); 2742 mOwner->writeInt32(it->sampleCount); 2743 mOwner->writeInt32(getStartTimeOffsetScaledTime() + it->sampleDuration); 2744 2745 int64_t totalCount = 1; 2746 while (++it != mSttsTableEntries.end()) { 2747 mOwner->writeInt32(it->sampleCount); 2748 mOwner->writeInt32(it->sampleDuration); 2749 totalCount += it->sampleCount; 2750 } 2751 CHECK_EQ(totalCount, mNumSamples); 2752 mOwner->endBox(); // stts 2753 } 2754 2755 void MPEG4Writer::Track::writeCttsBox() { 2756 if (mIsAudio) { // ctts is not for audio 2757 return; 2758 } 2759 2760 // There is no B frame at all 2761 if (mMinCttsOffsetTimeUs == mMaxCttsOffsetTimeUs) { 2762 return; 2763 } 2764 2765 // Do not write ctts box when there is no need to have it. 2766 if ((mNumCttsTableEntries == 1 && 2767 mCttsTableEntries.begin()->sampleDuration == 0) || 2768 mNumCttsTableEntries == 0) { 2769 return; 2770 } 2771 2772 ALOGD("ctts box has %d entries with range [%lld, %lld]", 2773 mNumCttsTableEntries, mMinCttsOffsetTimeUs, mMaxCttsOffsetTimeUs); 2774 2775 mOwner->beginBox("ctts"); 2776 // Version 1 allows to use negative offset time value, but 2777 // we are sticking to version 0 for now. 2778 mOwner->writeInt32(0); // version=0, flags=0 2779 mOwner->writeInt32(mNumCttsTableEntries); 2780 2781 // Compensate for small start time difference from different media tracks 2782 List<CttsTableEntry>::iterator it = mCttsTableEntries.begin(); 2783 CHECK(it != mCttsTableEntries.end() && it->sampleCount == 1); 2784 mOwner->writeInt32(it->sampleCount); 2785 mOwner->writeInt32(getStartTimeOffsetScaledTime() + 2786 it->sampleDuration - mMinCttsOffsetTimeUs); 2787 2788 int64_t totalCount = 1; 2789 while (++it != mCttsTableEntries.end()) { 2790 mOwner->writeInt32(it->sampleCount); 2791 mOwner->writeInt32(it->sampleDuration - mMinCttsOffsetTimeUs); 2792 totalCount += it->sampleCount; 2793 } 2794 CHECK_EQ(totalCount, mNumSamples); 2795 mOwner->endBox(); // ctts 2796 } 2797 2798 void MPEG4Writer::Track::writeStssBox() { 2799 mOwner->beginBox("stss"); 2800 mOwner->writeInt32(0); // version=0, flags=0 2801 mOwner->writeInt32(mNumStssTableEntries); // number of sync frames 2802 for (List<int32_t>::iterator it = mStssTableEntries.begin(); 2803 it != mStssTableEntries.end(); ++it) { 2804 mOwner->writeInt32(*it); 2805 } 2806 mOwner->endBox(); // stss 2807 } 2808 2809 void MPEG4Writer::Track::writeStszBox() { 2810 ALOGD("writeStszBox for %s track", isAudio()? "Audio": "Video"); 2811 mOwner->beginBox("stsz"); 2812 mOwner->writeInt32(0); // version=0, flags=0 2813 if (mSamplesHaveSameSize) { 2814 CHECK(mCurrentSampleSizeArr != 0); 2815 mOwner->write(mCurrentSampleSizeArr, 4, 1); // default sample size 2816 } else { 2817 mOwner->writeInt32(0); 2818 } 2819 mOwner->writeInt32(mNumSamples); 2820 uint32_t nSamples = mNumSamples; 2821 if (!mSamplesHaveSameSize) { 2822 for (List<uint32_t *>::iterator it = mSampleSizes.begin(); 2823 it != mSampleSizes.end(); ++it) { 2824 if (nSamples >= kSampleArraySize) { 2825 mOwner->write(*it, 4, kSampleArraySize); 2826 nSamples -= kSampleArraySize; 2827 } else { 2828 mOwner->write(*it, 4, nSamples); 2829 break; 2830 } 2831 } 2832 } 2833 mOwner->endBox(); // stsz 2834 ALOGD("writeStszBox: X"); 2835 } 2836 2837 void MPEG4Writer::Track::writeStscBox() { 2838 mOwner->beginBox("stsc"); 2839 mOwner->writeInt32(0); // version=0, flags=0 2840 mOwner->writeInt32(mNumStscTableEntries); 2841 for (List<StscTableEntry>::iterator it = mStscTableEntries.begin(); 2842 it != mStscTableEntries.end(); ++it) { 2843 mOwner->writeInt32(it->firstChunk); 2844 mOwner->writeInt32(it->samplesPerChunk); 2845 mOwner->writeInt32(it->sampleDescriptionId); 2846 } 2847 mOwner->endBox(); // stsc 2848 } 2849 2850 void MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) { 2851 mOwner->beginBox(use32BitOffset? "stco": "co64"); 2852 mOwner->writeInt32(0); // version=0, flags=0 2853 mOwner->writeInt32(mNumStcoTableEntries); 2854 for (List<off64_t>::iterator it = mChunkOffsets.begin(); 2855 it != mChunkOffsets.end(); ++it) { 2856 if (use32BitOffset) { 2857 mOwner->writeInt32(static_cast<int32_t>(*it)); 2858 } else { 2859 mOwner->writeInt64((*it)); 2860 } 2861 } 2862 mOwner->endBox(); // stco or co64 2863 } 2864 2865 void MPEG4Writer::writeUdtaBox() { 2866 beginBox("udta"); 2867 writeGeoDataBox(); 2868 endBox(); 2869 } 2870 2871 /* 2872 * Geodata is stored according to ISO-6709 standard. 2873 */ 2874 void MPEG4Writer::writeGeoDataBox() { 2875 beginBox("\xA9xyz"); 2876 /* 2877 * For historical reasons, any user data start 2878 * with "\0xA9", must be followed by its assoicated 2879 * language code. 2880 * 0x0012: text string length 2881 * 0x15c7: lang (locale) code: en 2882 */ 2883 writeInt32(0x001215c7); 2884 writeLatitude(mLatitudex10000); 2885 writeLongitude(mLongitudex10000); 2886 writeInt8(0x2F); 2887 endBox(); 2888 } 2889 2890 } // namespace android 2891