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