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