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