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