MPEG4Writer.cpp revision efcdf187baab9ec29e12adcf85e63fe3e6d5aa4d
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 43namespace android { 44 45static const int64_t kMax32BitFileSize = 0x007fffffffLL; 46static const uint8_t kNalUnitTypeSeqParamSet = 0x07; 47static const uint8_t kNalUnitTypePicParamSet = 0x08; 48static const int64_t kInitialDelayTimeUs = 700000LL; 49 50class MPEG4Writer::Track { 51public: 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 72private: 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(uint32_t now); 240 void writeSmhdBox(); 241 void writeVmhdBox(); 242 void writeHdlrBox(); 243 void writeTkhdBox(uint32_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 254MPEG4Writer::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 278MPEG4Writer::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 297MPEG4Writer::~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 309status_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 326status_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 340status_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 352status_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 369int64_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 428status_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 534bool MPEG4Writer::use32BitFileOffset() const { 535 return mUse32BitOffset; 536} 537 538status_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 554void 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 */ 584void 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 625void MPEG4Writer::release() { 626 close(mFd); 627 mFd = -1; 628 mInitCheck = NO_INIT; 629 mStarted = false; 630} 631 632status_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 726uint32_t MPEG4Writer::getMpeg4Time() { 727 time_t now = time(NULL); 728 // MP4 file uses time counting seconds since midnight, Jan. 1, 1904 729 // while time function returns Unix epoch values which starts 730 // at 1970-01-01. Lets add the number of seconds between them 731 uint32_t mpeg4Time = now + (66 * 365 + 17) * (24 * 60 * 60); 732 return mpeg4Time; 733} 734 735void MPEG4Writer::writeMvhdBox(int64_t durationUs) { 736 uint32_t now = getMpeg4Time(); 737 beginBox("mvhd"); 738 writeInt32(0); // version=0, flags=0 739 writeInt32(now); // creation time 740 writeInt32(now); // modification time 741 writeInt32(mTimeScale); // mvhd timescale 742 int32_t duration = (durationUs * mTimeScale + 5E5) / 1E6; 743 writeInt32(duration); 744 writeInt32(0x10000); // rate: 1.0 745 writeInt16(0x100); // volume 746 writeInt16(0); // reserved 747 writeInt32(0); // reserved 748 writeInt32(0); // reserved 749 writeCompositionMatrix(0); // matrix 750 writeInt32(0); // predefined 751 writeInt32(0); // predefined 752 writeInt32(0); // predefined 753 writeInt32(0); // predefined 754 writeInt32(0); // predefined 755 writeInt32(0); // predefined 756 writeInt32(mTracks.size() + 1); // nextTrackID 757 endBox(); // mvhd 758} 759 760void MPEG4Writer::writeMoovBox(int64_t durationUs) { 761 beginBox("moov"); 762 writeMvhdBox(durationUs); 763 if (mAreGeoTagsAvailable) { 764 writeUdtaBox(); 765 } 766 int32_t id = 1; 767 for (List<Track *>::iterator it = mTracks.begin(); 768 it != mTracks.end(); ++it, ++id) { 769 (*it)->writeTrackHeader(mUse32BitOffset); 770 } 771 endBox(); // moov 772} 773 774void MPEG4Writer::writeFtypBox(MetaData *param) { 775 beginBox("ftyp"); 776 777 int32_t fileType; 778 if (param && param->findInt32(kKeyFileType, &fileType) && 779 fileType != OUTPUT_FORMAT_MPEG_4) { 780 writeFourcc("3gp4"); 781 } else { 782 writeFourcc("isom"); 783 } 784 785 writeInt32(0); 786 writeFourcc("isom"); 787 writeFourcc("3gp4"); 788 endBox(); 789} 790 791static bool isTestModeEnabled() { 792#if (PROPERTY_VALUE_MAX < 5) 793#error "PROPERTY_VALUE_MAX must be at least 5" 794#endif 795 796 // Test mode is enabled only if rw.media.record.test system 797 // property is enabled. 798 char value[PROPERTY_VALUE_MAX]; 799 if (property_get("rw.media.record.test", value, NULL) && 800 (!strcasecmp(value, "true") || !strcasecmp(value, "1"))) { 801 return true; 802 } 803 return false; 804} 805 806void MPEG4Writer::sendSessionSummary() { 807 // Send session summary only if test mode is enabled 808 if (!isTestModeEnabled()) { 809 return; 810 } 811 812 for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 813 it != mChunkInfos.end(); ++it) { 814 int trackNum = it->mTrack->getTrackId() << 28; 815 notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 816 trackNum | MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS, 817 it->mMaxInterChunkDurUs); 818 } 819} 820 821status_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) { 822 mInterleaveDurationUs = durationUs; 823 return OK; 824} 825 826void MPEG4Writer::lock() { 827 mLock.lock(); 828} 829 830void MPEG4Writer::unlock() { 831 mLock.unlock(); 832} 833 834off64_t MPEG4Writer::addSample_l(MediaBuffer *buffer) { 835 off64_t old_offset = mOffset; 836 837 ::write(mFd, 838 (const uint8_t *)buffer->data() + buffer->range_offset(), 839 buffer->range_length()); 840 841 mOffset += buffer->range_length(); 842 843 return old_offset; 844} 845 846static void StripStartcode(MediaBuffer *buffer) { 847 if (buffer->range_length() < 4) { 848 return; 849 } 850 851 const uint8_t *ptr = 852 (const uint8_t *)buffer->data() + buffer->range_offset(); 853 854 if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) { 855 buffer->set_range( 856 buffer->range_offset() + 4, buffer->range_length() - 4); 857 } 858} 859 860off64_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) { 861 off64_t old_offset = mOffset; 862 863 size_t length = buffer->range_length(); 864 865 if (mUse4ByteNalLength) { 866 uint8_t x = length >> 24; 867 ::write(mFd, &x, 1); 868 x = (length >> 16) & 0xff; 869 ::write(mFd, &x, 1); 870 x = (length >> 8) & 0xff; 871 ::write(mFd, &x, 1); 872 x = length & 0xff; 873 ::write(mFd, &x, 1); 874 875 ::write(mFd, 876 (const uint8_t *)buffer->data() + buffer->range_offset(), 877 length); 878 879 mOffset += length + 4; 880 } else { 881 CHECK_LT(length, 65536); 882 883 uint8_t x = length >> 8; 884 ::write(mFd, &x, 1); 885 x = length & 0xff; 886 ::write(mFd, &x, 1); 887 ::write(mFd, (const uint8_t *)buffer->data() + buffer->range_offset(), length); 888 mOffset += length + 2; 889 } 890 891 return old_offset; 892} 893 894size_t MPEG4Writer::write( 895 const void *ptr, size_t size, size_t nmemb) { 896 897 const size_t bytes = size * nmemb; 898 if (mWriteMoovBoxToMemory) { 899 // This happens only when we write the moov box at the end of 900 // recording, not for each output video/audio frame we receive. 901 off64_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes; 902 if (moovBoxSize > mEstimatedMoovBoxSize) { 903 for (List<off64_t>::iterator it = mBoxes.begin(); 904 it != mBoxes.end(); ++it) { 905 (*it) += mOffset; 906 } 907 lseek64(mFd, mOffset, SEEK_SET); 908 ::write(mFd, mMoovBoxBuffer, mMoovBoxBufferOffset); 909 ::write(mFd, ptr, size * nmemb); 910 mOffset += (bytes + mMoovBoxBufferOffset); 911 free(mMoovBoxBuffer); 912 mMoovBoxBuffer = NULL; 913 mMoovBoxBufferOffset = 0; 914 mWriteMoovBoxToMemory = false; 915 mStreamableFile = false; 916 } else { 917 memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes); 918 mMoovBoxBufferOffset += bytes; 919 } 920 } else { 921 ::write(mFd, ptr, size * nmemb); 922 mOffset += bytes; 923 } 924 return bytes; 925} 926 927void MPEG4Writer::beginBox(const char *fourcc) { 928 CHECK_EQ(strlen(fourcc), 4); 929 930 mBoxes.push_back(mWriteMoovBoxToMemory? 931 mMoovBoxBufferOffset: mOffset); 932 933 writeInt32(0); 934 writeFourcc(fourcc); 935} 936 937void MPEG4Writer::endBox() { 938 CHECK(!mBoxes.empty()); 939 940 off64_t offset = *--mBoxes.end(); 941 mBoxes.erase(--mBoxes.end()); 942 943 if (mWriteMoovBoxToMemory) { 944 int32_t x = htonl(mMoovBoxBufferOffset - offset); 945 memcpy(mMoovBoxBuffer + offset, &x, 4); 946 } else { 947 lseek64(mFd, offset, SEEK_SET); 948 writeInt32(mOffset - offset); 949 mOffset -= 4; 950 lseek64(mFd, mOffset, SEEK_SET); 951 } 952} 953 954void MPEG4Writer::writeInt8(int8_t x) { 955 write(&x, 1, 1); 956} 957 958void MPEG4Writer::writeInt16(int16_t x) { 959 x = htons(x); 960 write(&x, 1, 2); 961} 962 963void MPEG4Writer::writeInt32(int32_t x) { 964 x = htonl(x); 965 write(&x, 1, 4); 966} 967 968void MPEG4Writer::writeInt64(int64_t x) { 969 x = hton64(x); 970 write(&x, 1, 8); 971} 972 973void MPEG4Writer::writeCString(const char *s) { 974 size_t n = strlen(s); 975 write(s, 1, n + 1); 976} 977 978void MPEG4Writer::writeFourcc(const char *s) { 979 CHECK_EQ(strlen(s), 4); 980 write(s, 1, 4); 981} 982 983 984// Written in +/-DD.DDDD format 985void MPEG4Writer::writeLatitude(int degreex10000) { 986 bool isNegative = (degreex10000 < 0); 987 char sign = isNegative? '-': '+'; 988 989 // Handle the whole part 990 char str[9]; 991 int wholePart = degreex10000 / 10000; 992 if (wholePart == 0) { 993 snprintf(str, 5, "%c%.2d.", sign, wholePart); 994 } else { 995 snprintf(str, 5, "%+.2d.", wholePart); 996 } 997 998 // Handle the fractional part 999 int fractionalPart = degreex10000 - (wholePart * 10000); 1000 if (fractionalPart < 0) { 1001 fractionalPart = -fractionalPart; 1002 } 1003 snprintf(&str[4], 5, "%.4d", fractionalPart); 1004 1005 // Do not write the null terminator 1006 write(str, 1, 8); 1007} 1008 1009// Written in +/- DDD.DDDD format 1010void MPEG4Writer::writeLongitude(int degreex10000) { 1011 bool isNegative = (degreex10000 < 0); 1012 char sign = isNegative? '-': '+'; 1013 1014 // Handle the whole part 1015 char str[10]; 1016 int wholePart = degreex10000 / 10000; 1017 if (wholePart == 0) { 1018 snprintf(str, 6, "%c%.3d.", sign, wholePart); 1019 } else { 1020 snprintf(str, 6, "%+.3d.", wholePart); 1021 } 1022 1023 // Handle the fractional part 1024 int fractionalPart = degreex10000 - (wholePart * 10000); 1025 if (fractionalPart < 0) { 1026 fractionalPart = -fractionalPart; 1027 } 1028 snprintf(&str[5], 5, "%.4d", fractionalPart); 1029 1030 // Do not write the null terminator 1031 write(str, 1, 9); 1032} 1033 1034/* 1035 * Geodata is stored according to ISO-6709 standard. 1036 * latitudex10000 is latitude in degrees times 10000, and 1037 * longitudex10000 is longitude in degrees times 10000. 1038 * The range for the latitude is in [-90, +90], and 1039 * The range for the longitude is in [-180, +180] 1040 */ 1041status_t MPEG4Writer::setGeoData(int latitudex10000, int longitudex10000) { 1042 // Is latitude or longitude out of range? 1043 if (latitudex10000 < -900000 || latitudex10000 > 900000 || 1044 longitudex10000 < -1800000 || longitudex10000 > 1800000) { 1045 return BAD_VALUE; 1046 } 1047 1048 mLatitudex10000 = latitudex10000; 1049 mLongitudex10000 = longitudex10000; 1050 mAreGeoTagsAvailable = true; 1051 return OK; 1052} 1053 1054void MPEG4Writer::write(const void *data, size_t size) { 1055 write(data, 1, size); 1056} 1057 1058bool MPEG4Writer::isFileStreamable() const { 1059 return mStreamableFile; 1060} 1061 1062bool MPEG4Writer::exceedsFileSizeLimit() { 1063 // No limit 1064 if (mMaxFileSizeLimitBytes == 0) { 1065 return false; 1066 } 1067 1068 int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize); 1069 for (List<Track *>::iterator it = mTracks.begin(); 1070 it != mTracks.end(); ++it) { 1071 nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes(); 1072 } 1073 1074 // Be conservative in the estimate: do not exceed 95% of 1075 // the target file limit. For small target file size limit, though, 1076 // this will not help. 1077 return (nTotalBytesEstimate >= (95 * mMaxFileSizeLimitBytes) / 100); 1078} 1079 1080bool MPEG4Writer::exceedsFileDurationLimit() { 1081 // No limit 1082 if (mMaxFileDurationLimitUs == 0) { 1083 return false; 1084 } 1085 1086 for (List<Track *>::iterator it = mTracks.begin(); 1087 it != mTracks.end(); ++it) { 1088 if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) { 1089 return true; 1090 } 1091 } 1092 return false; 1093} 1094 1095bool MPEG4Writer::reachedEOS() { 1096 bool allDone = true; 1097 for (List<Track *>::iterator it = mTracks.begin(); 1098 it != mTracks.end(); ++it) { 1099 if (!(*it)->reachedEOS()) { 1100 allDone = false; 1101 break; 1102 } 1103 } 1104 1105 return allDone; 1106} 1107 1108void MPEG4Writer::setStartTimestampUs(int64_t timeUs) { 1109 ALOGI("setStartTimestampUs: %lld", timeUs); 1110 CHECK_GE(timeUs, 0ll); 1111 Mutex::Autolock autoLock(mLock); 1112 if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) { 1113 mStartTimestampUs = timeUs; 1114 ALOGI("Earliest track starting time: %lld", mStartTimestampUs); 1115 } 1116} 1117 1118int64_t MPEG4Writer::getStartTimestampUs() { 1119 Mutex::Autolock autoLock(mLock); 1120 return mStartTimestampUs; 1121} 1122 1123size_t MPEG4Writer::numTracks() { 1124 Mutex::Autolock autolock(mLock); 1125 return mTracks.size(); 1126} 1127 1128//////////////////////////////////////////////////////////////////////////////// 1129 1130MPEG4Writer::Track::Track( 1131 MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId) 1132 : mOwner(owner), 1133 mMeta(source->getFormat()), 1134 mSource(source), 1135 mDone(false), 1136 mPaused(false), 1137 mResumed(false), 1138 mStarted(false), 1139 mTrackId(trackId), 1140 mTrackDurationUs(0), 1141 mEstimatedTrackSizeBytes(0), 1142 mSamplesHaveSameSize(true), 1143 mCodecSpecificData(NULL), 1144 mCodecSpecificDataSize(0), 1145 mGotAllCodecSpecificData(false), 1146 mReachedEOS(false), 1147 mRotation(0) { 1148 getCodecSpecificDataFromInputFormatIfPossible(); 1149 1150 const char *mime; 1151 mMeta->findCString(kKeyMIMEType, &mime); 1152 mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); 1153 mIsAudio = !strncasecmp(mime, "audio/", 6); 1154 mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) || 1155 !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC); 1156 1157 setTimeScale(); 1158} 1159 1160void MPEG4Writer::Track::updateTrackSizeEstimate() { 1161 1162 int64_t stcoBoxSizeBytes = mOwner->use32BitFileOffset() 1163 ? mNumStcoTableEntries * 4 1164 : mNumStcoTableEntries * 8; 1165 1166 int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mNumSamples * 4); 1167 1168 mEstimatedTrackSizeBytes = mMdatSizeBytes; // media data size 1169 if (!mOwner->isFileStreamable()) { 1170 // Reserved free space is not large enough to hold 1171 // all meta data and thus wasted. 1172 mEstimatedTrackSizeBytes += mNumStscTableEntries * 12 + // stsc box size 1173 mNumStssTableEntries * 4 + // stss box size 1174 mNumSttsTableEntries * 8 + // stts box size 1175 mNumCttsTableEntries * 8 + // ctts box size 1176 stcoBoxSizeBytes + // stco box size 1177 stszBoxSizeBytes; // stsz box size 1178 } 1179} 1180 1181void MPEG4Writer::Track::addOneStscTableEntry( 1182 size_t chunkId, size_t sampleId) { 1183 1184 StscTableEntry stscEntry(chunkId, sampleId, 1); 1185 mStscTableEntries.push_back(stscEntry); 1186 ++mNumStscTableEntries; 1187} 1188 1189void MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) { 1190 mStssTableEntries.push_back(sampleId); 1191 ++mNumStssTableEntries; 1192} 1193 1194void MPEG4Writer::Track::addOneSttsTableEntry( 1195 size_t sampleCount, int32_t duration) { 1196 1197 if (duration == 0) { 1198 ALOGW("0-duration samples found: %d", sampleCount); 1199 } 1200 SttsTableEntry sttsEntry(sampleCount, duration); 1201 mSttsTableEntries.push_back(sttsEntry); 1202 ++mNumSttsTableEntries; 1203} 1204 1205void MPEG4Writer::Track::addOneCttsTableEntry( 1206 size_t sampleCount, int32_t duration) { 1207 1208 if (mIsAudio) { 1209 return; 1210 } 1211 CttsTableEntry cttsEntry(sampleCount, duration); 1212 mCttsTableEntries.push_back(cttsEntry); 1213 ++mNumCttsTableEntries; 1214} 1215 1216void MPEG4Writer::Track::addChunkOffset(off64_t offset) { 1217 ++mNumStcoTableEntries; 1218 mChunkOffsets.push_back(offset); 1219} 1220 1221void MPEG4Writer::Track::setTimeScale() { 1222 ALOGV("setTimeScale"); 1223 // Default time scale 1224 mTimeScale = 90000; 1225 1226 if (mIsAudio) { 1227 // Use the sampling rate as the default time scale for audio track. 1228 int32_t sampleRate; 1229 bool success = mMeta->findInt32(kKeySampleRate, &sampleRate); 1230 CHECK(success); 1231 mTimeScale = sampleRate; 1232 } 1233 1234 // If someone would like to overwrite the timescale, use user-supplied value. 1235 int32_t timeScale; 1236 if (mMeta->findInt32(kKeyTimeScale, &timeScale)) { 1237 mTimeScale = timeScale; 1238 } 1239 1240 CHECK_GT(mTimeScale, 0); 1241} 1242 1243void MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() { 1244 const char *mime; 1245 CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 1246 1247 if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 1248 uint32_t type; 1249 const void *data; 1250 size_t size; 1251 if (mMeta->findData(kKeyAVCC, &type, &data, &size)) { 1252 mCodecSpecificData = malloc(size); 1253 mCodecSpecificDataSize = size; 1254 memcpy(mCodecSpecificData, data, size); 1255 mGotAllCodecSpecificData = true; 1256 } 1257 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) 1258 || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 1259 uint32_t type; 1260 const void *data; 1261 size_t size; 1262 if (mMeta->findData(kKeyESDS, &type, &data, &size)) { 1263 ESDS esds(data, size); 1264 if (esds.getCodecSpecificInfo(&data, &size) == OK) { 1265 mCodecSpecificData = malloc(size); 1266 mCodecSpecificDataSize = size; 1267 memcpy(mCodecSpecificData, data, size); 1268 mGotAllCodecSpecificData = true; 1269 } 1270 } 1271 } 1272} 1273 1274MPEG4Writer::Track::~Track() { 1275 stop(); 1276 1277 if (mCodecSpecificData != NULL) { 1278 free(mCodecSpecificData); 1279 mCodecSpecificData = NULL; 1280 } 1281 1282 while (!mSampleSizes.empty()) { 1283 List<uint32_t *>::iterator it = mSampleSizes.begin(); 1284 delete[] (*it); 1285 mSampleSizes.erase(it); 1286 } 1287} 1288 1289void MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) { 1290 ALOGV("initTrackingProgressStatus"); 1291 mPreviousTrackTimeUs = -1; 1292 mTrackingProgressStatus = false; 1293 mTrackEveryTimeDurationUs = 0; 1294 { 1295 int64_t timeUs; 1296 if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) { 1297 ALOGV("Receive request to track progress status for every %lld us", timeUs); 1298 mTrackEveryTimeDurationUs = timeUs; 1299 mTrackingProgressStatus = true; 1300 } 1301 } 1302} 1303 1304// static 1305void *MPEG4Writer::ThreadWrapper(void *me) { 1306 ALOGV("ThreadWrapper: %p", me); 1307 MPEG4Writer *writer = static_cast<MPEG4Writer *>(me); 1308 writer->threadFunc(); 1309 return NULL; 1310} 1311 1312void MPEG4Writer::bufferChunk(const Chunk& chunk) { 1313 ALOGV("bufferChunk: %p", chunk.mTrack); 1314 Mutex::Autolock autolock(mLock); 1315 CHECK_EQ(mDone, false); 1316 1317 for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 1318 it != mChunkInfos.end(); ++it) { 1319 1320 if (chunk.mTrack == it->mTrack) { // Found owner 1321 it->mChunks.push_back(chunk); 1322 mChunkReadyCondition.signal(); 1323 return; 1324 } 1325 } 1326 1327 CHECK(!"Received a chunk for a unknown track"); 1328} 1329 1330void MPEG4Writer::writeChunkToFile(Chunk* chunk) { 1331 ALOGV("writeChunkToFile: %lld from %s track", 1332 chunk->mTimeStampUs, chunk->mTrack->isAudio()? "audio": "video"); 1333 1334 int32_t isFirstSample = true; 1335 while (!chunk->mSamples.empty()) { 1336 List<MediaBuffer *>::iterator it = chunk->mSamples.begin(); 1337 1338 off64_t offset = chunk->mTrack->isAvc() 1339 ? addLengthPrefixedSample_l(*it) 1340 : addSample_l(*it); 1341 1342 if (isFirstSample) { 1343 chunk->mTrack->addChunkOffset(offset); 1344 isFirstSample = false; 1345 } 1346 1347 (*it)->release(); 1348 (*it) = NULL; 1349 chunk->mSamples.erase(it); 1350 } 1351 chunk->mSamples.clear(); 1352} 1353 1354void MPEG4Writer::writeAllChunks() { 1355 ALOGV("writeAllChunks"); 1356 size_t outstandingChunks = 0; 1357 Chunk chunk; 1358 while (findChunkToWrite(&chunk)) { 1359 writeChunkToFile(&chunk); 1360 ++outstandingChunks; 1361 } 1362 1363 sendSessionSummary(); 1364 1365 mChunkInfos.clear(); 1366 ALOGD("%d chunks are written in the last batch", outstandingChunks); 1367} 1368 1369bool MPEG4Writer::findChunkToWrite(Chunk *chunk) { 1370 ALOGV("findChunkToWrite"); 1371 1372 int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL; 1373 Track *track = NULL; 1374 for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 1375 it != mChunkInfos.end(); ++it) { 1376 if (!it->mChunks.empty()) { 1377 List<Chunk>::iterator chunkIt = it->mChunks.begin(); 1378 if (chunkIt->mTimeStampUs < minTimestampUs) { 1379 minTimestampUs = chunkIt->mTimeStampUs; 1380 track = it->mTrack; 1381 } 1382 } 1383 } 1384 1385 if (track == NULL) { 1386 ALOGV("Nothing to be written after all"); 1387 return false; 1388 } 1389 1390 if (mIsFirstChunk) { 1391 mIsFirstChunk = false; 1392 } 1393 1394 for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 1395 it != mChunkInfos.end(); ++it) { 1396 if (it->mTrack == track) { 1397 *chunk = *(it->mChunks.begin()); 1398 it->mChunks.erase(it->mChunks.begin()); 1399 CHECK_EQ(chunk->mTrack, track); 1400 1401 int64_t interChunkTimeUs = 1402 chunk->mTimeStampUs - it->mPrevChunkTimestampUs; 1403 if (interChunkTimeUs > it->mPrevChunkTimestampUs) { 1404 it->mMaxInterChunkDurUs = interChunkTimeUs; 1405 } 1406 1407 return true; 1408 } 1409 } 1410 1411 return false; 1412} 1413 1414void MPEG4Writer::threadFunc() { 1415 ALOGV("threadFunc"); 1416 1417 prctl(PR_SET_NAME, (unsigned long)"MPEG4Writer", 0, 0, 0); 1418 1419 Mutex::Autolock autoLock(mLock); 1420 while (!mDone) { 1421 Chunk chunk; 1422 bool chunkFound = false; 1423 1424 while (!mDone && !(chunkFound = findChunkToWrite(&chunk))) { 1425 mChunkReadyCondition.wait(mLock); 1426 } 1427 1428 // Actual write without holding the lock in order to 1429 // reduce the blocking time for media track threads. 1430 if (chunkFound) { 1431 mLock.unlock(); 1432 writeChunkToFile(&chunk); 1433 mLock.lock(); 1434 } 1435 } 1436 1437 writeAllChunks(); 1438} 1439 1440status_t MPEG4Writer::startWriterThread() { 1441 ALOGV("startWriterThread"); 1442 1443 mDone = false; 1444 mIsFirstChunk = true; 1445 mDriftTimeUs = 0; 1446 for (List<Track *>::iterator it = mTracks.begin(); 1447 it != mTracks.end(); ++it) { 1448 ChunkInfo info; 1449 info.mTrack = *it; 1450 info.mPrevChunkTimestampUs = 0; 1451 info.mMaxInterChunkDurUs = 0; 1452 mChunkInfos.push_back(info); 1453 } 1454 1455 pthread_attr_t attr; 1456 pthread_attr_init(&attr); 1457 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 1458 pthread_create(&mThread, &attr, ThreadWrapper, this); 1459 pthread_attr_destroy(&attr); 1460 mWriterThreadStarted = true; 1461 return OK; 1462} 1463 1464 1465status_t MPEG4Writer::Track::start(MetaData *params) { 1466 if (!mDone && mPaused) { 1467 mPaused = false; 1468 mResumed = true; 1469 return OK; 1470 } 1471 1472 int64_t startTimeUs; 1473 if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) { 1474 startTimeUs = 0; 1475 } 1476 mStartTimeRealUs = startTimeUs; 1477 1478 int32_t rotationDegrees; 1479 if (!mIsAudio && params && params->findInt32(kKeyRotation, &rotationDegrees)) { 1480 mRotation = rotationDegrees; 1481 } 1482 1483 mIsRealTimeRecording = true; 1484 { 1485 int32_t isNotRealTime; 1486 if (params && params->findInt32(kKeyNotRealTime, &isNotRealTime)) { 1487 mIsRealTimeRecording = (isNotRealTime == 0); 1488 } 1489 } 1490 1491 initTrackingProgressStatus(params); 1492 1493 sp<MetaData> meta = new MetaData; 1494 if (mIsRealTimeRecording && mOwner->numTracks() > 1) { 1495 /* 1496 * This extra delay of accepting incoming audio/video signals 1497 * helps to align a/v start time at the beginning of a recording 1498 * session, and it also helps eliminate the "recording" sound for 1499 * camcorder applications. 1500 * 1501 * If client does not set the start time offset, we fall back to 1502 * use the default initial delay value. 1503 */ 1504 int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL; 1505 if (startTimeOffsetUs < 0) { // Start time offset was not set 1506 startTimeOffsetUs = kInitialDelayTimeUs; 1507 } 1508 startTimeUs += startTimeOffsetUs; 1509 ALOGI("Start time offset: %lld us", startTimeOffsetUs); 1510 } 1511 1512 meta->setInt64(kKeyTime, startTimeUs); 1513 1514 status_t err = mSource->start(meta.get()); 1515 if (err != OK) { 1516 mDone = mReachedEOS = true; 1517 return err; 1518 } 1519 1520 pthread_attr_t attr; 1521 pthread_attr_init(&attr); 1522 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 1523 1524 mDone = false; 1525 mStarted = true; 1526 mTrackDurationUs = 0; 1527 mReachedEOS = false; 1528 mEstimatedTrackSizeBytes = 0; 1529 mNumStcoTableEntries = 0; 1530 mNumStssTableEntries = 0; 1531 mNumStscTableEntries = 0; 1532 mNumSttsTableEntries = 0; 1533 mNumCttsTableEntries = 0; 1534 mMdatSizeBytes = 0; 1535 1536 mMaxChunkDurationUs = 0; 1537 1538 pthread_create(&mThread, &attr, ThreadWrapper, this); 1539 pthread_attr_destroy(&attr); 1540 1541 return OK; 1542} 1543 1544status_t MPEG4Writer::Track::pause() { 1545 mPaused = true; 1546 return OK; 1547} 1548 1549status_t MPEG4Writer::Track::stop() { 1550 ALOGD("Stopping %s track", mIsAudio? "Audio": "Video"); 1551 if (!mStarted) { 1552 ALOGE("Stop() called but track is not started"); 1553 return ERROR_END_OF_STREAM; 1554 } 1555 1556 if (mDone) { 1557 return OK; 1558 } 1559 mDone = true; 1560 1561 void *dummy; 1562 pthread_join(mThread, &dummy); 1563 1564 status_t err = (status_t) dummy; 1565 1566 ALOGD("Stopping %s track source", mIsAudio? "Audio": "Video"); 1567 { 1568 status_t status = mSource->stop(); 1569 if (err == OK && status != OK && status != ERROR_END_OF_STREAM) { 1570 err = status; 1571 } 1572 } 1573 1574 ALOGD("%s track stopped", mIsAudio? "Audio": "Video"); 1575 return err; 1576} 1577 1578bool MPEG4Writer::Track::reachedEOS() { 1579 return mReachedEOS; 1580} 1581 1582// static 1583void *MPEG4Writer::Track::ThreadWrapper(void *me) { 1584 Track *track = static_cast<Track *>(me); 1585 1586 status_t err = track->threadEntry(); 1587 return (void *) err; 1588} 1589 1590static void getNalUnitType(uint8_t byte, uint8_t* type) { 1591 ALOGV("getNalUnitType: %d", byte); 1592 1593 // nal_unit_type: 5-bit unsigned integer 1594 *type = (byte & 0x1F); 1595} 1596 1597static const uint8_t *findNextStartCode( 1598 const uint8_t *data, size_t length) { 1599 1600 ALOGV("findNextStartCode: %p %d", data, length); 1601 1602 size_t bytesLeft = length; 1603 while (bytesLeft > 4 && 1604 memcmp("\x00\x00\x00\x01", &data[length - bytesLeft], 4)) { 1605 --bytesLeft; 1606 } 1607 if (bytesLeft <= 4) { 1608 bytesLeft = 0; // Last parameter set 1609 } 1610 return &data[length - bytesLeft]; 1611} 1612 1613const uint8_t *MPEG4Writer::Track::parseParamSet( 1614 const uint8_t *data, size_t length, int type, size_t *paramSetLen) { 1615 1616 ALOGV("parseParamSet"); 1617 CHECK(type == kNalUnitTypeSeqParamSet || 1618 type == kNalUnitTypePicParamSet); 1619 1620 const uint8_t *nextStartCode = findNextStartCode(data, length); 1621 *paramSetLen = nextStartCode - data; 1622 if (*paramSetLen == 0) { 1623 ALOGE("Param set is malformed, since its length is 0"); 1624 return NULL; 1625 } 1626 1627 AVCParamSet paramSet(*paramSetLen, data); 1628 if (type == kNalUnitTypeSeqParamSet) { 1629 if (*paramSetLen < 4) { 1630 ALOGE("Seq parameter set malformed"); 1631 return NULL; 1632 } 1633 if (mSeqParamSets.empty()) { 1634 mProfileIdc = data[1]; 1635 mProfileCompatible = data[2]; 1636 mLevelIdc = data[3]; 1637 } else { 1638 if (mProfileIdc != data[1] || 1639 mProfileCompatible != data[2] || 1640 mLevelIdc != data[3]) { 1641 ALOGE("Inconsistent profile/level found in seq parameter sets"); 1642 return NULL; 1643 } 1644 } 1645 mSeqParamSets.push_back(paramSet); 1646 } else { 1647 mPicParamSets.push_back(paramSet); 1648 } 1649 return nextStartCode; 1650} 1651 1652status_t MPEG4Writer::Track::copyAVCCodecSpecificData( 1653 const uint8_t *data, size_t size) { 1654 ALOGV("copyAVCCodecSpecificData"); 1655 1656 // 2 bytes for each of the parameter set length field 1657 // plus the 7 bytes for the header 1658 if (size < 4 + 7) { 1659 ALOGE("Codec specific data length too short: %d", size); 1660 return ERROR_MALFORMED; 1661 } 1662 1663 mCodecSpecificDataSize = size; 1664 mCodecSpecificData = malloc(size); 1665 memcpy(mCodecSpecificData, data, size); 1666 return OK; 1667} 1668 1669status_t MPEG4Writer::Track::parseAVCCodecSpecificData( 1670 const uint8_t *data, size_t size) { 1671 1672 ALOGV("parseAVCCodecSpecificData"); 1673 // Data starts with a start code. 1674 // SPS and PPS are separated with start codes. 1675 // Also, SPS must come before PPS 1676 uint8_t type = kNalUnitTypeSeqParamSet; 1677 bool gotSps = false; 1678 bool gotPps = false; 1679 const uint8_t *tmp = data; 1680 const uint8_t *nextStartCode = data; 1681 size_t bytesLeft = size; 1682 size_t paramSetLen = 0; 1683 mCodecSpecificDataSize = 0; 1684 while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) { 1685 getNalUnitType(*(tmp + 4), &type); 1686 if (type == kNalUnitTypeSeqParamSet) { 1687 if (gotPps) { 1688 ALOGE("SPS must come before PPS"); 1689 return ERROR_MALFORMED; 1690 } 1691 if (!gotSps) { 1692 gotSps = true; 1693 } 1694 nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 1695 } else if (type == kNalUnitTypePicParamSet) { 1696 if (!gotSps) { 1697 ALOGE("SPS must come before PPS"); 1698 return ERROR_MALFORMED; 1699 } 1700 if (!gotPps) { 1701 gotPps = true; 1702 } 1703 nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 1704 } else { 1705 ALOGE("Only SPS and PPS Nal units are expected"); 1706 return ERROR_MALFORMED; 1707 } 1708 1709 if (nextStartCode == NULL) { 1710 return ERROR_MALFORMED; 1711 } 1712 1713 // Move on to find the next parameter set 1714 bytesLeft -= nextStartCode - tmp; 1715 tmp = nextStartCode; 1716 mCodecSpecificDataSize += (2 + paramSetLen); 1717 } 1718 1719 { 1720 // Check on the number of seq parameter sets 1721 size_t nSeqParamSets = mSeqParamSets.size(); 1722 if (nSeqParamSets == 0) { 1723 ALOGE("Cound not find sequence parameter set"); 1724 return ERROR_MALFORMED; 1725 } 1726 1727 if (nSeqParamSets > 0x1F) { 1728 ALOGE("Too many seq parameter sets (%d) found", nSeqParamSets); 1729 return ERROR_MALFORMED; 1730 } 1731 } 1732 1733 { 1734 // Check on the number of pic parameter sets 1735 size_t nPicParamSets = mPicParamSets.size(); 1736 if (nPicParamSets == 0) { 1737 ALOGE("Cound not find picture parameter set"); 1738 return ERROR_MALFORMED; 1739 } 1740 if (nPicParamSets > 0xFF) { 1741 ALOGE("Too many pic parameter sets (%d) found", nPicParamSets); 1742 return ERROR_MALFORMED; 1743 } 1744 } 1745// FIXME: 1746// Add chromat_format_idc, bit depth values, etc for AVC/h264 high profile and above 1747// and remove #if 0 1748#if 0 1749 { 1750 // Check on the profiles 1751 // These profiles requires additional parameter set extensions 1752 if (mProfileIdc == 100 || mProfileIdc == 110 || 1753 mProfileIdc == 122 || mProfileIdc == 144) { 1754 ALOGE("Sorry, no support for profile_idc: %d!", mProfileIdc); 1755 return BAD_VALUE; 1756 } 1757 } 1758#endif 1759 return OK; 1760} 1761 1762status_t MPEG4Writer::Track::makeAVCCodecSpecificData( 1763 const uint8_t *data, size_t size) { 1764 1765 if (mCodecSpecificData != NULL) { 1766 ALOGE("Already have codec specific data"); 1767 return ERROR_MALFORMED; 1768 } 1769 1770 if (size < 4) { 1771 ALOGE("Codec specific data length too short: %d", size); 1772 return ERROR_MALFORMED; 1773 } 1774 1775 // Data is in the form of AVCCodecSpecificData 1776 if (memcmp("\x00\x00\x00\x01", data, 4)) { 1777 return copyAVCCodecSpecificData(data, size); 1778 } 1779 1780 if (parseAVCCodecSpecificData(data, size) != OK) { 1781 return ERROR_MALFORMED; 1782 } 1783 1784 // ISO 14496-15: AVC file format 1785 mCodecSpecificDataSize += 7; // 7 more bytes in the header 1786 mCodecSpecificData = malloc(mCodecSpecificDataSize); 1787 uint8_t *header = (uint8_t *)mCodecSpecificData; 1788 header[0] = 1; // version 1789 header[1] = mProfileIdc; // profile indication 1790 header[2] = mProfileCompatible; // profile compatibility 1791 header[3] = mLevelIdc; 1792 1793 // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne 1794 if (mOwner->useNalLengthFour()) { 1795 header[4] = 0xfc | 3; // length size == 4 bytes 1796 } else { 1797 header[4] = 0xfc | 1; // length size == 2 bytes 1798 } 1799 1800 // 3-bit '111' followed by 5-bit numSequenceParameterSets 1801 int nSequenceParamSets = mSeqParamSets.size(); 1802 header[5] = 0xe0 | nSequenceParamSets; 1803 header += 6; 1804 for (List<AVCParamSet>::iterator it = mSeqParamSets.begin(); 1805 it != mSeqParamSets.end(); ++it) { 1806 // 16-bit sequence parameter set length 1807 uint16_t seqParamSetLength = it->mLength; 1808 header[0] = seqParamSetLength >> 8; 1809 header[1] = seqParamSetLength & 0xff; 1810 1811 // SPS NAL unit (sequence parameter length bytes) 1812 memcpy(&header[2], it->mData, seqParamSetLength); 1813 header += (2 + seqParamSetLength); 1814 } 1815 1816 // 8-bit nPictureParameterSets 1817 int nPictureParamSets = mPicParamSets.size(); 1818 header[0] = nPictureParamSets; 1819 header += 1; 1820 for (List<AVCParamSet>::iterator it = mPicParamSets.begin(); 1821 it != mPicParamSets.end(); ++it) { 1822 // 16-bit picture parameter set length 1823 uint16_t picParamSetLength = it->mLength; 1824 header[0] = picParamSetLength >> 8; 1825 header[1] = picParamSetLength & 0xff; 1826 1827 // PPS Nal unit (picture parameter set length bytes) 1828 memcpy(&header[2], it->mData, picParamSetLength); 1829 header += (2 + picParamSetLength); 1830 } 1831 1832 return OK; 1833} 1834 1835/* 1836 * Updates the drift time from the audio track so that 1837 * the video track can get the updated drift time information 1838 * from the file writer. The fluctuation of the drift time of the audio 1839 * encoding path is smoothed out with a simple filter by giving a larger 1840 * weight to more recently drift time. The filter coefficients, 0.5 and 0.5, 1841 * are heuristically determined. 1842 */ 1843void MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) { 1844 int64_t driftTimeUs = 0; 1845 if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) { 1846 int64_t prevDriftTimeUs = mOwner->getDriftTimeUs(); 1847 int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1; 1848 mOwner->setDriftTimeUs(timeUs); 1849 } 1850} 1851 1852status_t MPEG4Writer::Track::threadEntry() { 1853 int32_t count = 0; 1854 const int64_t interleaveDurationUs = mOwner->interleaveDuration(); 1855 const bool hasMultipleTracks = (mOwner->numTracks() > 1); 1856 int64_t chunkTimestampUs = 0; 1857 int32_t nChunks = 0; 1858 int32_t nZeroLengthFrames = 0; 1859 int64_t lastTimestampUs = 0; // Previous sample time stamp 1860 int64_t lastDurationUs = 0; // Between the previous two samples 1861 int64_t currDurationTicks = 0; // Timescale based ticks 1862 int64_t lastDurationTicks = 0; // Timescale based ticks 1863 int32_t sampleCount = 1; // Sample count in the current stts table entry 1864 uint32_t previousSampleSize = 0; // Size of the previous sample 1865 int64_t previousPausedDurationUs = 0; 1866 int64_t timestampUs = 0; 1867 int64_t cttsOffsetTimeUs = 0; 1868 int64_t currCttsOffsetTimeTicks = 0; // Timescale based ticks 1869 int64_t lastCttsOffsetTimeTicks = -1; // Timescale based ticks 1870 int32_t cttsSampleCount = 0; // Sample count in the current ctts table entry 1871 1872 if (mIsAudio) { 1873 prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0); 1874 } else { 1875 prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0); 1876 } 1877 androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO); 1878 1879 sp<MetaData> meta_data; 1880 1881 mNumSamples = 0; 1882 status_t err = OK; 1883 MediaBuffer *buffer; 1884 while (!mDone && (err = mSource->read(&buffer)) == OK) { 1885 if (buffer->range_length() == 0) { 1886 buffer->release(); 1887 buffer = NULL; 1888 ++nZeroLengthFrames; 1889 continue; 1890 } 1891 1892 // If the codec specific data has not been received yet, delay pause. 1893 // After the codec specific data is received, discard what we received 1894 // when the track is to be paused. 1895 if (mPaused && !mResumed) { 1896 buffer->release(); 1897 buffer = NULL; 1898 continue; 1899 } 1900 1901 ++count; 1902 1903 int32_t isCodecConfig; 1904 if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig) 1905 && isCodecConfig) { 1906 CHECK(!mGotAllCodecSpecificData); 1907 1908 if (mIsAvc) { 1909 status_t err = makeAVCCodecSpecificData( 1910 (const uint8_t *)buffer->data() 1911 + buffer->range_offset(), 1912 buffer->range_length()); 1913 CHECK_EQ((status_t)OK, err); 1914 } else if (mIsMPEG4) { 1915 mCodecSpecificDataSize = buffer->range_length(); 1916 mCodecSpecificData = malloc(mCodecSpecificDataSize); 1917 memcpy(mCodecSpecificData, 1918 (const uint8_t *)buffer->data() 1919 + buffer->range_offset(), 1920 buffer->range_length()); 1921 } 1922 1923 buffer->release(); 1924 buffer = NULL; 1925 1926 mGotAllCodecSpecificData = true; 1927 continue; 1928 } 1929 1930 // Make a deep copy of the MediaBuffer and Metadata and release 1931 // the original as soon as we can 1932 MediaBuffer *copy = new MediaBuffer(buffer->range_length()); 1933 memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(), 1934 buffer->range_length()); 1935 copy->set_range(0, buffer->range_length()); 1936 meta_data = new MetaData(*buffer->meta_data().get()); 1937 buffer->release(); 1938 buffer = NULL; 1939 1940 if (mIsAvc) StripStartcode(copy); 1941 1942 size_t sampleSize = copy->range_length(); 1943 if (mIsAvc) { 1944 if (mOwner->useNalLengthFour()) { 1945 sampleSize += 4; 1946 } else { 1947 sampleSize += 2; 1948 } 1949 } 1950 1951 // Max file size or duration handling 1952 mMdatSizeBytes += sampleSize; 1953 updateTrackSizeEstimate(); 1954 1955 if (mOwner->exceedsFileSizeLimit()) { 1956 mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0); 1957 break; 1958 } 1959 if (mOwner->exceedsFileDurationLimit()) { 1960 mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0); 1961 break; 1962 } 1963 1964 1965 int32_t isSync = false; 1966 meta_data->findInt32(kKeyIsSyncFrame, &isSync); 1967 CHECK(meta_data->findInt64(kKeyTime, ×tampUs)); 1968 1969//////////////////////////////////////////////////////////////////////////////// 1970 if (mNumSamples == 0) { 1971 mFirstSampleTimeRealUs = systemTime() / 1000; 1972 mStartTimestampUs = timestampUs; 1973 mOwner->setStartTimestampUs(mStartTimestampUs); 1974 previousPausedDurationUs = mStartTimestampUs; 1975 } 1976 1977 if (mResumed) { 1978 int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs; 1979 CHECK_GE(durExcludingEarlierPausesUs, 0ll); 1980 int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs; 1981 CHECK_GE(pausedDurationUs, lastDurationUs); 1982 previousPausedDurationUs += pausedDurationUs - lastDurationUs; 1983 mResumed = false; 1984 } 1985 1986 timestampUs -= previousPausedDurationUs; 1987 CHECK_GE(timestampUs, 0ll); 1988 if (!mIsAudio) { 1989 /* 1990 * Composition time: timestampUs 1991 * Decoding time: decodingTimeUs 1992 * Composition time offset = composition time - decoding time 1993 */ 1994 int64_t decodingTimeUs; 1995 CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs)); 1996 decodingTimeUs -= previousPausedDurationUs; 1997 cttsOffsetTimeUs = 1998 timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs; 1999 CHECK_GE(cttsOffsetTimeUs, 0ll); 2000 timestampUs = decodingTimeUs; 2001 ALOGV("decoding time: %lld and ctts offset time: %lld", 2002 timestampUs, cttsOffsetTimeUs); 2003 2004 // Update ctts box table if necessary 2005 currCttsOffsetTimeTicks = 2006 (cttsOffsetTimeUs * mTimeScale + 500000LL) / 1000000LL; 2007 CHECK_LE(currCttsOffsetTimeTicks, 0x0FFFFFFFFLL); 2008 if (mNumSamples == 0) { 2009 // Force the first ctts table entry to have one single entry 2010 // so that we can do adjustment for the initial track start 2011 // time offset easily in writeCttsBox(). 2012 lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks; 2013 addOneCttsTableEntry(1, currCttsOffsetTimeTicks); 2014 cttsSampleCount = 0; // No sample in ctts box is pending 2015 } else { 2016 if (currCttsOffsetTimeTicks != lastCttsOffsetTimeTicks) { 2017 addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks); 2018 lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks; 2019 cttsSampleCount = 1; // One sample in ctts box is pending 2020 } else { 2021 ++cttsSampleCount; 2022 } 2023 } 2024 2025 // Update ctts time offset range 2026 if (mNumSamples == 0) { 2027 mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2028 mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2029 } else { 2030 if (currCttsOffsetTimeTicks > mMaxCttsOffsetTimeUs) { 2031 mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2032 } else if (currCttsOffsetTimeTicks < mMinCttsOffsetTimeUs) { 2033 mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2034 } 2035 } 2036 2037 } 2038 2039 if (mIsRealTimeRecording) { 2040 if (mIsAudio) { 2041 updateDriftTime(meta_data); 2042 } 2043 } 2044 2045 CHECK_GE(timestampUs, 0ll); 2046 ALOGV("%s media time stamp: %lld and previous paused duration %lld", 2047 mIsAudio? "Audio": "Video", timestampUs, previousPausedDurationUs); 2048 if (timestampUs > mTrackDurationUs) { 2049 mTrackDurationUs = timestampUs; 2050 } 2051 2052 // We need to use the time scale based ticks, rather than the 2053 // timestamp itself to determine whether we have to use a new 2054 // stts entry, since we may have rounding errors. 2055 // The calculation is intended to reduce the accumulated 2056 // rounding errors. 2057 currDurationTicks = 2058 ((timestampUs * mTimeScale + 500000LL) / 1000000LL - 2059 (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL); 2060 CHECK_GE(currDurationTicks, 0ll); 2061 2062 if ((mNumSamples % kSampleArraySize) == 0) { 2063 uint32_t *arr = new uint32_t[kSampleArraySize]; 2064 CHECK(arr != NULL); 2065 mSampleSizes.push_back(arr); 2066 mCurrentSampleSizeArr = arr; 2067 } 2068 2069 mCurrentSampleSizeArr[mNumSamples % kSampleArraySize] = htonl(sampleSize); 2070 ++mNumSamples; 2071 if (mNumSamples > 2) { 2072 2073 // Force the first sample to have its own stts entry so that 2074 // we can adjust its value later to maintain the A/V sync. 2075 if (mNumSamples == 3 || currDurationTicks != lastDurationTicks) { 2076 addOneSttsTableEntry(sampleCount, lastDurationTicks); 2077 sampleCount = 1; 2078 } else { 2079 ++sampleCount; 2080 } 2081 2082 } 2083 if (mSamplesHaveSameSize) { 2084 if (mNumSamples >= 2 && previousSampleSize != sampleSize) { 2085 mSamplesHaveSameSize = false; 2086 } 2087 previousSampleSize = sampleSize; 2088 } 2089 ALOGV("%s timestampUs/lastTimestampUs: %lld/%lld", 2090 mIsAudio? "Audio": "Video", timestampUs, lastTimestampUs); 2091 lastDurationUs = timestampUs - lastTimestampUs; 2092 lastDurationTicks = currDurationTicks; 2093 lastTimestampUs = timestampUs; 2094 2095 if (isSync != 0) { 2096 addOneStssTableEntry(mNumSamples); 2097 } 2098 2099 if (mTrackingProgressStatus) { 2100 if (mPreviousTrackTimeUs <= 0) { 2101 mPreviousTrackTimeUs = mStartTimestampUs; 2102 } 2103 trackProgressStatus(timestampUs); 2104 } 2105 if (!hasMultipleTracks) { 2106 off64_t offset = mIsAvc? mOwner->addLengthPrefixedSample_l(copy) 2107 : mOwner->addSample_l(copy); 2108 if (mChunkOffsets.empty()) { 2109 addChunkOffset(offset); 2110 } 2111 copy->release(); 2112 copy = NULL; 2113 continue; 2114 } 2115 2116 mChunkSamples.push_back(copy); 2117 if (interleaveDurationUs == 0) { 2118 addOneStscTableEntry(++nChunks, 1); 2119 bufferChunk(timestampUs); 2120 } else { 2121 if (chunkTimestampUs == 0) { 2122 chunkTimestampUs = timestampUs; 2123 } else { 2124 int64_t chunkDurationUs = timestampUs - chunkTimestampUs; 2125 if (chunkDurationUs > interleaveDurationUs) { 2126 if (chunkDurationUs > mMaxChunkDurationUs) { 2127 mMaxChunkDurationUs = chunkDurationUs; 2128 } 2129 ++nChunks; 2130 if (nChunks == 1 || // First chunk 2131 (--(mStscTableEntries.end()))->samplesPerChunk != 2132 mChunkSamples.size()) { 2133 addOneStscTableEntry(nChunks, mChunkSamples.size()); 2134 } 2135 bufferChunk(timestampUs); 2136 chunkTimestampUs = timestampUs; 2137 } 2138 } 2139 } 2140 2141 } 2142 2143 if (isTrackMalFormed()) { 2144 err = ERROR_MALFORMED; 2145 } 2146 2147 mOwner->trackProgressStatus(mTrackId, -1, err); 2148 2149 // Last chunk 2150 if (!hasMultipleTracks) { 2151 addOneStscTableEntry(1, mNumSamples); 2152 } else if (!mChunkSamples.empty()) { 2153 addOneStscTableEntry(++nChunks, mChunkSamples.size()); 2154 bufferChunk(timestampUs); 2155 } 2156 2157 // We don't really know how long the last frame lasts, since 2158 // there is no frame time after it, just repeat the previous 2159 // frame's duration. 2160 if (mNumSamples == 1) { 2161 lastDurationUs = 0; // A single sample's duration 2162 lastDurationTicks = 0; 2163 } else { 2164 ++sampleCount; // Count for the last sample 2165 } 2166 2167 if (mNumSamples <= 2) { 2168 addOneSttsTableEntry(1, lastDurationTicks); 2169 if (sampleCount - 1 > 0) { 2170 addOneSttsTableEntry(sampleCount - 1, lastDurationTicks); 2171 } 2172 } else { 2173 addOneSttsTableEntry(sampleCount, lastDurationTicks); 2174 } 2175 2176 // The last ctts box may not have been written yet, and this 2177 // is to make sure that we write out the last ctts box. 2178 if (currCttsOffsetTimeTicks == lastCttsOffsetTimeTicks) { 2179 if (cttsSampleCount > 0) { 2180 addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks); 2181 } 2182 } 2183 2184 mTrackDurationUs += lastDurationUs; 2185 mReachedEOS = true; 2186 2187 sendTrackSummary(hasMultipleTracks); 2188 2189 ALOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s", 2190 count, nZeroLengthFrames, mNumSamples, mIsAudio? "audio": "video"); 2191 if (mIsAudio) { 2192 ALOGI("Audio track drift time: %lld us", mOwner->getDriftTimeUs()); 2193 } 2194 2195 if (err == ERROR_END_OF_STREAM) { 2196 return OK; 2197 } 2198 return err; 2199} 2200 2201bool MPEG4Writer::Track::isTrackMalFormed() const { 2202 if (mSampleSizes.empty()) { // no samples written 2203 ALOGE("The number of recorded samples is 0"); 2204 return true; 2205 } 2206 2207 if (!mIsAudio && mNumStssTableEntries == 0) { // no sync frames for video 2208 ALOGE("There are no sync frames for video track"); 2209 return true; 2210 } 2211 2212 if (OK != checkCodecSpecificData()) { // no codec specific data 2213 return true; 2214 } 2215 2216 return false; 2217} 2218 2219void MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) { 2220 2221 // Send track summary only if test mode is enabled. 2222 if (!isTestModeEnabled()) { 2223 return; 2224 } 2225 2226 int trackNum = (mTrackId << 28); 2227 2228 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2229 trackNum | MEDIA_RECORDER_TRACK_INFO_TYPE, 2230 mIsAudio? 0: 1); 2231 2232 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2233 trackNum | MEDIA_RECORDER_TRACK_INFO_DURATION_MS, 2234 mTrackDurationUs / 1000); 2235 2236 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2237 trackNum | MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES, 2238 mNumSamples); 2239 2240 { 2241 // The system delay time excluding the requested initial delay that 2242 // is used to eliminate the recording sound. 2243 int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL; 2244 if (startTimeOffsetUs < 0) { // Start time offset was not set 2245 startTimeOffsetUs = kInitialDelayTimeUs; 2246 } 2247 int64_t initialDelayUs = 2248 mFirstSampleTimeRealUs - mStartTimeRealUs - startTimeOffsetUs; 2249 2250 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2251 trackNum | MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS, 2252 (initialDelayUs) / 1000); 2253 } 2254 2255 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2256 trackNum | MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES, 2257 mMdatSizeBytes / 1024); 2258 2259 if (hasMultipleTracks) { 2260 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2261 trackNum | MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS, 2262 mMaxChunkDurationUs / 1000); 2263 2264 int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 2265 if (mStartTimestampUs != moovStartTimeUs) { 2266 int64_t startTimeOffsetUs = mStartTimestampUs - moovStartTimeUs; 2267 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2268 trackNum | MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS, 2269 startTimeOffsetUs / 1000); 2270 } 2271 } 2272} 2273 2274void MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) { 2275 ALOGV("trackProgressStatus: %lld us", timeUs); 2276 if (mTrackEveryTimeDurationUs > 0 && 2277 timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) { 2278 ALOGV("Fire time tracking progress status at %lld us", timeUs); 2279 mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err); 2280 mPreviousTrackTimeUs = timeUs; 2281 } 2282} 2283 2284void MPEG4Writer::trackProgressStatus( 2285 size_t trackId, int64_t timeUs, status_t err) { 2286 Mutex::Autolock lock(mLock); 2287 int32_t trackNum = (trackId << 28); 2288 2289 // Error notification 2290 // Do not consider ERROR_END_OF_STREAM an error 2291 if (err != OK && err != ERROR_END_OF_STREAM) { 2292 notify(MEDIA_RECORDER_TRACK_EVENT_ERROR, 2293 trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL, 2294 err); 2295 return; 2296 } 2297 2298 if (timeUs == -1) { 2299 // Send completion notification 2300 notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2301 trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS, 2302 err); 2303 } else { 2304 // Send progress status 2305 notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2306 trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME, 2307 timeUs / 1000); 2308 } 2309} 2310 2311void MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) { 2312 ALOGV("setDriftTimeUs: %lld us", driftTimeUs); 2313 Mutex::Autolock autolock(mLock); 2314 mDriftTimeUs = driftTimeUs; 2315} 2316 2317int64_t MPEG4Writer::getDriftTimeUs() { 2318 ALOGV("getDriftTimeUs: %lld us", mDriftTimeUs); 2319 Mutex::Autolock autolock(mLock); 2320 return mDriftTimeUs; 2321} 2322 2323bool MPEG4Writer::useNalLengthFour() { 2324 return mUse4ByteNalLength; 2325} 2326 2327void MPEG4Writer::Track::bufferChunk(int64_t timestampUs) { 2328 ALOGV("bufferChunk"); 2329 2330 Chunk chunk(this, timestampUs, mChunkSamples); 2331 mOwner->bufferChunk(chunk); 2332 mChunkSamples.clear(); 2333} 2334 2335int64_t MPEG4Writer::Track::getDurationUs() const { 2336 return mTrackDurationUs; 2337} 2338 2339int64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const { 2340 return mEstimatedTrackSizeBytes; 2341} 2342 2343status_t MPEG4Writer::Track::checkCodecSpecificData() const { 2344 const char *mime; 2345 CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 2346 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) || 2347 !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) || 2348 !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 2349 if (!mCodecSpecificData || 2350 mCodecSpecificDataSize <= 0) { 2351 ALOGE("Missing codec specific data"); 2352 return ERROR_MALFORMED; 2353 } 2354 } else { 2355 if (mCodecSpecificData || 2356 mCodecSpecificDataSize > 0) { 2357 ALOGE("Unexepected codec specific data found"); 2358 return ERROR_MALFORMED; 2359 } 2360 } 2361 return OK; 2362} 2363 2364void MPEG4Writer::Track::writeTrackHeader(bool use32BitOffset) { 2365 2366 ALOGV("%s track time scale: %d", 2367 mIsAudio? "Audio": "Video", mTimeScale); 2368 2369 uint32_t now = getMpeg4Time(); 2370 mOwner->beginBox("trak"); 2371 writeTkhdBox(now); 2372 mOwner->beginBox("mdia"); 2373 writeMdhdBox(now); 2374 writeHdlrBox(); 2375 mOwner->beginBox("minf"); 2376 if (mIsAudio) { 2377 writeSmhdBox(); 2378 } else { 2379 writeVmhdBox(); 2380 } 2381 writeDinfBox(); 2382 writeStblBox(use32BitOffset); 2383 mOwner->endBox(); // minf 2384 mOwner->endBox(); // mdia 2385 mOwner->endBox(); // trak 2386} 2387 2388void MPEG4Writer::Track::writeStblBox(bool use32BitOffset) { 2389 mOwner->beginBox("stbl"); 2390 mOwner->beginBox("stsd"); 2391 mOwner->writeInt32(0); // version=0, flags=0 2392 mOwner->writeInt32(1); // entry count 2393 if (mIsAudio) { 2394 writeAudioFourCCBox(); 2395 } else { 2396 writeVideoFourCCBox(); 2397 } 2398 mOwner->endBox(); // stsd 2399 writeSttsBox(); 2400 writeCttsBox(); 2401 if (!mIsAudio) { 2402 writeStssBox(); 2403 } 2404 writeStszBox(); 2405 writeStscBox(); 2406 writeStcoBox(use32BitOffset); 2407 mOwner->endBox(); // stbl 2408} 2409 2410void MPEG4Writer::Track::writeVideoFourCCBox() { 2411 const char *mime; 2412 bool success = mMeta->findCString(kKeyMIMEType, &mime); 2413 CHECK(success); 2414 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 2415 mOwner->beginBox("mp4v"); 2416 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 2417 mOwner->beginBox("s263"); 2418 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 2419 mOwner->beginBox("avc1"); 2420 } else { 2421 ALOGE("Unknown mime type '%s'.", mime); 2422 CHECK(!"should not be here, unknown mime type."); 2423 } 2424 2425 mOwner->writeInt32(0); // reserved 2426 mOwner->writeInt16(0); // reserved 2427 mOwner->writeInt16(1); // data ref index 2428 mOwner->writeInt16(0); // predefined 2429 mOwner->writeInt16(0); // reserved 2430 mOwner->writeInt32(0); // predefined 2431 mOwner->writeInt32(0); // predefined 2432 mOwner->writeInt32(0); // predefined 2433 2434 int32_t width, height; 2435 success = mMeta->findInt32(kKeyWidth, &width); 2436 success = success && mMeta->findInt32(kKeyHeight, &height); 2437 CHECK(success); 2438 2439 mOwner->writeInt16(width); 2440 mOwner->writeInt16(height); 2441 mOwner->writeInt32(0x480000); // horiz resolution 2442 mOwner->writeInt32(0x480000); // vert resolution 2443 mOwner->writeInt32(0); // reserved 2444 mOwner->writeInt16(1); // frame count 2445 mOwner->write(" ", 32); 2446 mOwner->writeInt16(0x18); // depth 2447 mOwner->writeInt16(-1); // predefined 2448 2449 CHECK_LT(23 + mCodecSpecificDataSize, 128); 2450 2451 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 2452 writeMp4vEsdsBox(); 2453 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 2454 writeD263Box(); 2455 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 2456 writeAvccBox(); 2457 } 2458 2459 writePaspBox(); 2460 mOwner->endBox(); // mp4v, s263 or avc1 2461} 2462 2463void MPEG4Writer::Track::writeAudioFourCCBox() { 2464 const char *mime; 2465 bool success = mMeta->findCString(kKeyMIMEType, &mime); 2466 CHECK(success); 2467 const char *fourcc = NULL; 2468 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) { 2469 fourcc = "samr"; 2470 } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 2471 fourcc = "sawb"; 2472 } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 2473 fourcc = "mp4a"; 2474 } else { 2475 ALOGE("Unknown mime type '%s'.", mime); 2476 CHECK(!"should not be here, unknown mime type."); 2477 } 2478 2479 mOwner->beginBox(fourcc); // audio format 2480 mOwner->writeInt32(0); // reserved 2481 mOwner->writeInt16(0); // reserved 2482 mOwner->writeInt16(0x1); // data ref index 2483 mOwner->writeInt32(0); // reserved 2484 mOwner->writeInt32(0); // reserved 2485 int32_t nChannels; 2486 CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels)); 2487 mOwner->writeInt16(nChannels); // channel count 2488 mOwner->writeInt16(16); // sample size 2489 mOwner->writeInt16(0); // predefined 2490 mOwner->writeInt16(0); // reserved 2491 2492 int32_t samplerate; 2493 success = mMeta->findInt32(kKeySampleRate, &samplerate); 2494 CHECK(success); 2495 mOwner->writeInt32(samplerate << 16); 2496 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 2497 writeMp4aEsdsBox(); 2498 } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) || 2499 !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 2500 writeDamrBox(); 2501 } 2502 mOwner->endBox(); 2503} 2504 2505void MPEG4Writer::Track::writeMp4aEsdsBox() { 2506 mOwner->beginBox("esds"); 2507 CHECK(mCodecSpecificData); 2508 CHECK_GT(mCodecSpecificDataSize, 0); 2509 2510 // Make sure all sizes encode to a single byte. 2511 CHECK_LT(mCodecSpecificDataSize + 23, 128); 2512 2513 mOwner->writeInt32(0); // version=0, flags=0 2514 mOwner->writeInt8(0x03); // ES_DescrTag 2515 mOwner->writeInt8(23 + mCodecSpecificDataSize); 2516 mOwner->writeInt16(0x0000);// ES_ID 2517 mOwner->writeInt8(0x00); 2518 2519 mOwner->writeInt8(0x04); // DecoderConfigDescrTag 2520 mOwner->writeInt8(15 + mCodecSpecificDataSize); 2521 mOwner->writeInt8(0x40); // objectTypeIndication ISO/IEC 14492-2 2522 mOwner->writeInt8(0x15); // streamType AudioStream 2523 2524 mOwner->writeInt16(0x03); // XXX 2525 mOwner->writeInt8(0x00); // buffer size 24-bit 2526 mOwner->writeInt32(96000); // max bit rate 2527 mOwner->writeInt32(96000); // avg bit rate 2528 2529 mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 2530 mOwner->writeInt8(mCodecSpecificDataSize); 2531 mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2532 2533 static const uint8_t kData2[] = { 2534 0x06, // SLConfigDescriptorTag 2535 0x01, 2536 0x02 2537 }; 2538 mOwner->write(kData2, sizeof(kData2)); 2539 2540 mOwner->endBox(); // esds 2541} 2542 2543void MPEG4Writer::Track::writeMp4vEsdsBox() { 2544 CHECK(mCodecSpecificData); 2545 CHECK_GT(mCodecSpecificDataSize, 0); 2546 mOwner->beginBox("esds"); 2547 2548 mOwner->writeInt32(0); // version=0, flags=0 2549 2550 mOwner->writeInt8(0x03); // ES_DescrTag 2551 mOwner->writeInt8(23 + mCodecSpecificDataSize); 2552 mOwner->writeInt16(0x0000); // ES_ID 2553 mOwner->writeInt8(0x1f); 2554 2555 mOwner->writeInt8(0x04); // DecoderConfigDescrTag 2556 mOwner->writeInt8(15 + mCodecSpecificDataSize); 2557 mOwner->writeInt8(0x20); // objectTypeIndication ISO/IEC 14492-2 2558 mOwner->writeInt8(0x11); // streamType VisualStream 2559 2560 static const uint8_t kData[] = { 2561 0x01, 0x77, 0x00, 2562 0x00, 0x03, 0xe8, 0x00, 2563 0x00, 0x03, 0xe8, 0x00 2564 }; 2565 mOwner->write(kData, sizeof(kData)); 2566 2567 mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 2568 2569 mOwner->writeInt8(mCodecSpecificDataSize); 2570 mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2571 2572 static const uint8_t kData2[] = { 2573 0x06, // SLConfigDescriptorTag 2574 0x01, 2575 0x02 2576 }; 2577 mOwner->write(kData2, sizeof(kData2)); 2578 2579 mOwner->endBox(); // esds 2580} 2581 2582void MPEG4Writer::Track::writeTkhdBox(uint32_t now) { 2583 mOwner->beginBox("tkhd"); 2584 // Flags = 7 to indicate that the track is enabled, and 2585 // part of the presentation 2586 mOwner->writeInt32(0x07); // version=0, flags=7 2587 mOwner->writeInt32(now); // creation time 2588 mOwner->writeInt32(now); // modification time 2589 mOwner->writeInt32(mTrackId + 1); // track id starts with 1 2590 mOwner->writeInt32(0); // reserved 2591 int64_t trakDurationUs = getDurationUs(); 2592 int32_t mvhdTimeScale = mOwner->getTimeScale(); 2593 int32_t tkhdDuration = 2594 (trakDurationUs * mvhdTimeScale + 5E5) / 1E6; 2595 mOwner->writeInt32(tkhdDuration); // in mvhd timescale 2596 mOwner->writeInt32(0); // reserved 2597 mOwner->writeInt32(0); // reserved 2598 mOwner->writeInt16(0); // layer 2599 mOwner->writeInt16(0); // alternate group 2600 mOwner->writeInt16(mIsAudio ? 0x100 : 0); // volume 2601 mOwner->writeInt16(0); // reserved 2602 2603 mOwner->writeCompositionMatrix(mRotation); // matrix 2604 2605 if (mIsAudio) { 2606 mOwner->writeInt32(0); 2607 mOwner->writeInt32(0); 2608 } else { 2609 int32_t width, height; 2610 bool success = mMeta->findInt32(kKeyWidth, &width); 2611 success = success && mMeta->findInt32(kKeyHeight, &height); 2612 CHECK(success); 2613 2614 mOwner->writeInt32(width << 16); // 32-bit fixed-point value 2615 mOwner->writeInt32(height << 16); // 32-bit fixed-point value 2616 } 2617 mOwner->endBox(); // tkhd 2618} 2619 2620void MPEG4Writer::Track::writeVmhdBox() { 2621 mOwner->beginBox("vmhd"); 2622 mOwner->writeInt32(0x01); // version=0, flags=1 2623 mOwner->writeInt16(0); // graphics mode 2624 mOwner->writeInt16(0); // opcolor 2625 mOwner->writeInt16(0); 2626 mOwner->writeInt16(0); 2627 mOwner->endBox(); 2628} 2629 2630void MPEG4Writer::Track::writeSmhdBox() { 2631 mOwner->beginBox("smhd"); 2632 mOwner->writeInt32(0); // version=0, flags=0 2633 mOwner->writeInt16(0); // balance 2634 mOwner->writeInt16(0); // reserved 2635 mOwner->endBox(); 2636} 2637 2638void MPEG4Writer::Track::writeHdlrBox() { 2639 mOwner->beginBox("hdlr"); 2640 mOwner->writeInt32(0); // version=0, flags=0 2641 mOwner->writeInt32(0); // component type: should be mhlr 2642 mOwner->writeFourcc(mIsAudio ? "soun" : "vide"); // component subtype 2643 mOwner->writeInt32(0); // reserved 2644 mOwner->writeInt32(0); // reserved 2645 mOwner->writeInt32(0); // reserved 2646 // Removing "r" for the name string just makes the string 4 byte aligned 2647 mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle"); // name 2648 mOwner->endBox(); 2649} 2650 2651void MPEG4Writer::Track::writeMdhdBox(uint32_t now) { 2652 int64_t trakDurationUs = getDurationUs(); 2653 mOwner->beginBox("mdhd"); 2654 mOwner->writeInt32(0); // version=0, flags=0 2655 mOwner->writeInt32(now); // creation time 2656 mOwner->writeInt32(now); // modification time 2657 mOwner->writeInt32(mTimeScale); // media timescale 2658 int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6; 2659 mOwner->writeInt32(mdhdDuration); // use media timescale 2660 // Language follows the three letter standard ISO-639-2/T 2661 // 'e', 'n', 'g' for "English", for instance. 2662 // Each character is packed as the difference between its ASCII value and 0x60. 2663 // For "English", these are 00101, 01110, 00111. 2664 // XXX: Where is the padding bit located: 0x15C7? 2665 mOwner->writeInt16(0); // language code 2666 mOwner->writeInt16(0); // predefined 2667 mOwner->endBox(); 2668} 2669 2670void MPEG4Writer::Track::writeDamrBox() { 2671 // 3gpp2 Spec AMRSampleEntry fields 2672 mOwner->beginBox("damr"); 2673 mOwner->writeCString(" "); // vendor: 4 bytes 2674 mOwner->writeInt8(0); // decoder version 2675 mOwner->writeInt16(0x83FF); // mode set: all enabled 2676 mOwner->writeInt8(0); // mode change period 2677 mOwner->writeInt8(1); // frames per sample 2678 mOwner->endBox(); 2679} 2680 2681void MPEG4Writer::Track::writeUrlBox() { 2682 // The table index here refers to the sample description index 2683 // in the sample table entries. 2684 mOwner->beginBox("url "); 2685 mOwner->writeInt32(1); // version=0, flags=1 (self-contained) 2686 mOwner->endBox(); // url 2687} 2688 2689void MPEG4Writer::Track::writeDrefBox() { 2690 mOwner->beginBox("dref"); 2691 mOwner->writeInt32(0); // version=0, flags=0 2692 mOwner->writeInt32(1); // entry count (either url or urn) 2693 writeUrlBox(); 2694 mOwner->endBox(); // dref 2695} 2696 2697void MPEG4Writer::Track::writeDinfBox() { 2698 mOwner->beginBox("dinf"); 2699 writeDrefBox(); 2700 mOwner->endBox(); // dinf 2701} 2702 2703void MPEG4Writer::Track::writeAvccBox() { 2704 CHECK(mCodecSpecificData); 2705 CHECK_GE(mCodecSpecificDataSize, 5); 2706 2707 // Patch avcc's lengthSize field to match the number 2708 // of bytes we use to indicate the size of a nal unit. 2709 uint8_t *ptr = (uint8_t *)mCodecSpecificData; 2710 ptr[4] = (ptr[4] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1); 2711 mOwner->beginBox("avcC"); 2712 mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2713 mOwner->endBox(); // avcC 2714} 2715 2716void MPEG4Writer::Track::writeD263Box() { 2717 mOwner->beginBox("d263"); 2718 mOwner->writeInt32(0); // vendor 2719 mOwner->writeInt8(0); // decoder version 2720 mOwner->writeInt8(10); // level: 10 2721 mOwner->writeInt8(0); // profile: 0 2722 mOwner->endBox(); // d263 2723} 2724 2725// This is useful if the pixel is not square 2726void MPEG4Writer::Track::writePaspBox() { 2727 mOwner->beginBox("pasp"); 2728 mOwner->writeInt32(1 << 16); // hspacing 2729 mOwner->writeInt32(1 << 16); // vspacing 2730 mOwner->endBox(); // pasp 2731} 2732 2733int32_t MPEG4Writer::Track::getStartTimeOffsetScaledTime() const { 2734 int64_t trackStartTimeOffsetUs = 0; 2735 int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 2736 if (mStartTimestampUs != moovStartTimeUs) { 2737 CHECK_GT(mStartTimestampUs, moovStartTimeUs); 2738 trackStartTimeOffsetUs = mStartTimestampUs - moovStartTimeUs; 2739 } 2740 return (trackStartTimeOffsetUs * mTimeScale + 500000LL) / 1000000LL; 2741} 2742 2743void MPEG4Writer::Track::writeSttsBox() { 2744 mOwner->beginBox("stts"); 2745 mOwner->writeInt32(0); // version=0, flags=0 2746 mOwner->writeInt32(mNumSttsTableEntries); 2747 2748 // Compensate for small start time difference from different media tracks 2749 List<SttsTableEntry>::iterator it = mSttsTableEntries.begin(); 2750 CHECK(it != mSttsTableEntries.end() && it->sampleCount == 1); 2751 mOwner->writeInt32(it->sampleCount); 2752 mOwner->writeInt32(getStartTimeOffsetScaledTime() + it->sampleDuration); 2753 2754 int64_t totalCount = 1; 2755 while (++it != mSttsTableEntries.end()) { 2756 mOwner->writeInt32(it->sampleCount); 2757 mOwner->writeInt32(it->sampleDuration); 2758 totalCount += it->sampleCount; 2759 } 2760 CHECK_EQ(totalCount, mNumSamples); 2761 mOwner->endBox(); // stts 2762} 2763 2764void MPEG4Writer::Track::writeCttsBox() { 2765 if (mIsAudio) { // ctts is not for audio 2766 return; 2767 } 2768 2769 // There is no B frame at all 2770 if (mMinCttsOffsetTimeUs == mMaxCttsOffsetTimeUs) { 2771 return; 2772 } 2773 2774 // Do not write ctts box when there is no need to have it. 2775 if ((mNumCttsTableEntries == 1 && 2776 mCttsTableEntries.begin()->sampleDuration == 0) || 2777 mNumCttsTableEntries == 0) { 2778 return; 2779 } 2780 2781 ALOGD("ctts box has %d entries with range [%lld, %lld]", 2782 mNumCttsTableEntries, mMinCttsOffsetTimeUs, mMaxCttsOffsetTimeUs); 2783 2784 mOwner->beginBox("ctts"); 2785 // Version 1 allows to use negative offset time value, but 2786 // we are sticking to version 0 for now. 2787 mOwner->writeInt32(0); // version=0, flags=0 2788 mOwner->writeInt32(mNumCttsTableEntries); 2789 2790 // Compensate for small start time difference from different media tracks 2791 List<CttsTableEntry>::iterator it = mCttsTableEntries.begin(); 2792 CHECK(it != mCttsTableEntries.end() && it->sampleCount == 1); 2793 mOwner->writeInt32(it->sampleCount); 2794 mOwner->writeInt32(getStartTimeOffsetScaledTime() + 2795 it->sampleDuration - mMinCttsOffsetTimeUs); 2796 2797 int64_t totalCount = 1; 2798 while (++it != mCttsTableEntries.end()) { 2799 mOwner->writeInt32(it->sampleCount); 2800 mOwner->writeInt32(it->sampleDuration - mMinCttsOffsetTimeUs); 2801 totalCount += it->sampleCount; 2802 } 2803 CHECK_EQ(totalCount, mNumSamples); 2804 mOwner->endBox(); // ctts 2805} 2806 2807void MPEG4Writer::Track::writeStssBox() { 2808 mOwner->beginBox("stss"); 2809 mOwner->writeInt32(0); // version=0, flags=0 2810 mOwner->writeInt32(mNumStssTableEntries); // number of sync frames 2811 for (List<int32_t>::iterator it = mStssTableEntries.begin(); 2812 it != mStssTableEntries.end(); ++it) { 2813 mOwner->writeInt32(*it); 2814 } 2815 mOwner->endBox(); // stss 2816} 2817 2818void MPEG4Writer::Track::writeStszBox() { 2819 ALOGD("writeStszBox for %s track", isAudio()? "Audio": "Video"); 2820 mOwner->beginBox("stsz"); 2821 mOwner->writeInt32(0); // version=0, flags=0 2822 if (mSamplesHaveSameSize) { 2823 CHECK(mCurrentSampleSizeArr != 0); 2824 mOwner->write(mCurrentSampleSizeArr, 4, 1); // default sample size 2825 } else { 2826 mOwner->writeInt32(0); 2827 } 2828 mOwner->writeInt32(mNumSamples); 2829 uint32_t nSamples = mNumSamples; 2830 if (!mSamplesHaveSameSize) { 2831 for (List<uint32_t *>::iterator it = mSampleSizes.begin(); 2832 it != mSampleSizes.end(); ++it) { 2833 if (nSamples >= kSampleArraySize) { 2834 mOwner->write(*it, 4, kSampleArraySize); 2835 nSamples -= kSampleArraySize; 2836 } else { 2837 mOwner->write(*it, 4, nSamples); 2838 break; 2839 } 2840 } 2841 } 2842 mOwner->endBox(); // stsz 2843 ALOGD("writeStszBox: X"); 2844} 2845 2846void MPEG4Writer::Track::writeStscBox() { 2847 mOwner->beginBox("stsc"); 2848 mOwner->writeInt32(0); // version=0, flags=0 2849 mOwner->writeInt32(mNumStscTableEntries); 2850 for (List<StscTableEntry>::iterator it = mStscTableEntries.begin(); 2851 it != mStscTableEntries.end(); ++it) { 2852 mOwner->writeInt32(it->firstChunk); 2853 mOwner->writeInt32(it->samplesPerChunk); 2854 mOwner->writeInt32(it->sampleDescriptionId); 2855 } 2856 mOwner->endBox(); // stsc 2857} 2858 2859void MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) { 2860 mOwner->beginBox(use32BitOffset? "stco": "co64"); 2861 mOwner->writeInt32(0); // version=0, flags=0 2862 mOwner->writeInt32(mNumStcoTableEntries); 2863 for (List<off64_t>::iterator it = mChunkOffsets.begin(); 2864 it != mChunkOffsets.end(); ++it) { 2865 if (use32BitOffset) { 2866 mOwner->writeInt32(static_cast<int32_t>(*it)); 2867 } else { 2868 mOwner->writeInt64((*it)); 2869 } 2870 } 2871 mOwner->endBox(); // stco or co64 2872} 2873 2874void MPEG4Writer::writeUdtaBox() { 2875 beginBox("udta"); 2876 writeGeoDataBox(); 2877 endBox(); 2878} 2879 2880/* 2881 * Geodata is stored according to ISO-6709 standard. 2882 */ 2883void MPEG4Writer::writeGeoDataBox() { 2884 beginBox("\xA9xyz"); 2885 /* 2886 * For historical reasons, any user data start 2887 * with "\0xA9", must be followed by its assoicated 2888 * language code. 2889 * 0x0012: text string length 2890 * 0x15c7: lang (locale) code: en 2891 */ 2892 writeInt32(0x001215c7); 2893 writeLatitude(mLatitudex10000); 2894 writeLongitude(mLongitudex10000); 2895 writeInt8(0x2F); 2896 endBox(); 2897} 2898 2899} // namespace android 2900