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 20 #include <algorithm> 21 22 #include <arpa/inet.h> 23 #include <fcntl.h> 24 #include <inttypes.h> 25 #include <pthread.h> 26 #include <sys/prctl.h> 27 #include <sys/stat.h> 28 #include <sys/types.h> 29 #include <unistd.h> 30 31 #include <utils/Log.h> 32 33 #include <functional> 34 35 #include <media/MediaSource.h> 36 #include <media/stagefright/foundation/ADebug.h> 37 #include <media/stagefright/foundation/AMessage.h> 38 #include <media/stagefright/foundation/AUtils.h> 39 #include <media/stagefright/foundation/ByteUtils.h> 40 #include <media/stagefright/foundation/ColorUtils.h> 41 #include <media/stagefright/foundation/avc_utils.h> 42 #include <media/stagefright/MPEG4Writer.h> 43 #include <media/stagefright/MediaBuffer.h> 44 #include <media/stagefright/MetaData.h> 45 #include <media/stagefright/MediaDefs.h> 46 #include <media/stagefright/MediaErrors.h> 47 #include <media/stagefright/Utils.h> 48 #include <media/mediarecorder.h> 49 #include <cutils/properties.h> 50 51 #include "include/ESDS.h" 52 #include "include/HevcUtils.h" 53 54 #ifndef __predict_false 55 #define __predict_false(exp) __builtin_expect((exp) != 0, 0) 56 #endif 57 58 #define WARN_UNLESS(condition, message, ...) \ 59 ( (__predict_false(condition)) ? false : ({ \ 60 ALOGW("Condition %s failed " message, #condition, ##__VA_ARGS__); \ 61 true; \ 62 })) 63 64 namespace android { 65 66 static const int64_t kMinStreamableFileSizeInBytes = 5 * 1024 * 1024; 67 static const int64_t kMax32BitFileSize = 0x00ffffffffLL; // 2^32-1 : max FAT32 68 // filesystem file size 69 // used by most SD cards 70 static const uint8_t kNalUnitTypeSeqParamSet = 0x07; 71 static const uint8_t kNalUnitTypePicParamSet = 0x08; 72 static const int64_t kInitialDelayTimeUs = 700000LL; 73 static const int64_t kMaxMetadataSize = 0x4000000LL; // 64MB max per-frame metadata size 74 static const int64_t kMaxCttsOffsetTimeUs = 30 * 60 * 1000000LL; // 30 minutes 75 static const size_t kESDSScratchBufferSize = 10; // kMaxAtomSize in Mpeg4Extractor 64MB 76 77 static const char kMetaKey_Version[] = "com.android.version"; 78 static const char kMetaKey_Manufacturer[] = "com.android.manufacturer"; 79 static const char kMetaKey_Model[] = "com.android.model"; 80 81 #ifdef SHOW_BUILD 82 static const char kMetaKey_Build[] = "com.android.build"; 83 #endif 84 static const char kMetaKey_CaptureFps[] = "com.android.capture.fps"; 85 static const char kMetaKey_TemporalLayerCount[] = "com.android.video.temporal_layers_count"; 86 87 static const int kTimestampDebugCount = 10; 88 static const int kItemIdBase = 10000; 89 static const char kExifHeader[] = {'E', 'x', 'i', 'f', '\0', '\0'}; 90 static const uint8_t kExifApp1Marker[] = {'E', 'x', 'i', 'f', 0xff, 0xe1}; 91 92 static const uint8_t kMandatoryHevcNalUnitTypes[3] = { 93 kHevcNalUnitTypeVps, 94 kHevcNalUnitTypeSps, 95 kHevcNalUnitTypePps, 96 }; 97 static const uint8_t kHevcNalUnitTypes[5] = { 98 kHevcNalUnitTypeVps, 99 kHevcNalUnitTypeSps, 100 kHevcNalUnitTypePps, 101 kHevcNalUnitTypePrefixSei, 102 kHevcNalUnitTypeSuffixSei, 103 }; 104 /* uncomment to include build in meta */ 105 //#define SHOW_MODEL_BUILD 1 106 107 class MPEG4Writer::Track { 108 public: 109 Track(MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId); 110 111 ~Track(); 112 113 status_t start(MetaData *params); 114 status_t stop(bool stopSource = true); 115 status_t pause(); 116 bool reachedEOS(); 117 118 int64_t getDurationUs() const; 119 int64_t getEstimatedTrackSizeBytes() const; 120 int32_t getMetaSizeIncrease(int32_t angle, int32_t trackCount) const; 121 void writeTrackHeader(bool use32BitOffset = true); 122 int64_t getMinCttsOffsetTimeUs(); 123 void bufferChunk(int64_t timestampUs); 124 bool isAvc() const { return mIsAvc; } 125 bool isHevc() const { return mIsHevc; } 126 bool isHeic() const { return mIsHeic; } 127 bool isAudio() const { return mIsAudio; } 128 bool isMPEG4() const { return mIsMPEG4; } 129 bool usePrefix() const { return mIsAvc || mIsHevc || mIsHeic; } 130 bool isExifData(MediaBufferBase *buffer, uint32_t *tiffHdrOffset) const; 131 void addChunkOffset(off64_t offset); 132 void addItemOffsetAndSize(off64_t offset, size_t size, bool isExif); 133 void flushItemRefs(); 134 int32_t getTrackId() const { return mTrackId; } 135 status_t dump(int fd, const Vector<String16>& args) const; 136 static const char *getFourCCForMime(const char *mime); 137 const char *getTrackType() const; 138 void resetInternal(); 139 140 private: 141 // A helper class to handle faster write box with table entries 142 template<class TYPE, unsigned ENTRY_SIZE> 143 // ENTRY_SIZE: # of values in each entry 144 struct ListTableEntries { 145 static_assert(ENTRY_SIZE > 0, "ENTRY_SIZE must be positive"); 146 ListTableEntries(uint32_t elementCapacity) 147 : mElementCapacity(elementCapacity), 148 mTotalNumTableEntries(0), 149 mNumValuesInCurrEntry(0), 150 mCurrTableEntriesElement(NULL) { 151 CHECK_GT(mElementCapacity, 0u); 152 // Ensure no integer overflow on allocation in add(). 153 CHECK_LT(ENTRY_SIZE, UINT32_MAX / mElementCapacity); 154 } 155 156 // Free the allocated memory. 157 ~ListTableEntries() { 158 while (!mTableEntryList.empty()) { 159 typename List<TYPE *>::iterator it = mTableEntryList.begin(); 160 delete[] (*it); 161 mTableEntryList.erase(it); 162 } 163 } 164 165 // Replace the value at the given position by the given value. 166 // There must be an existing value at the given position. 167 // @arg value must be in network byte order 168 // @arg pos location the value must be in. 169 void set(const TYPE& value, uint32_t pos) { 170 CHECK_LT(pos, mTotalNumTableEntries * ENTRY_SIZE); 171 172 typename List<TYPE *>::iterator it = mTableEntryList.begin(); 173 uint32_t iterations = (pos / (mElementCapacity * ENTRY_SIZE)); 174 while (it != mTableEntryList.end() && iterations > 0) { 175 ++it; 176 --iterations; 177 } 178 CHECK(it != mTableEntryList.end()); 179 CHECK_EQ(iterations, 0u); 180 181 (*it)[(pos % (mElementCapacity * ENTRY_SIZE))] = value; 182 } 183 184 // Get the value at the given position by the given value. 185 // @arg value the retrieved value at the position in network byte order. 186 // @arg pos location the value must be in. 187 // @return true if a value is found. 188 bool get(TYPE& value, uint32_t pos) const { 189 if (pos >= mTotalNumTableEntries * ENTRY_SIZE) { 190 return false; 191 } 192 193 typename List<TYPE *>::iterator it = mTableEntryList.begin(); 194 uint32_t iterations = (pos / (mElementCapacity * ENTRY_SIZE)); 195 while (it != mTableEntryList.end() && iterations > 0) { 196 ++it; 197 --iterations; 198 } 199 CHECK(it != mTableEntryList.end()); 200 CHECK_EQ(iterations, 0u); 201 202 value = (*it)[(pos % (mElementCapacity * ENTRY_SIZE))]; 203 return true; 204 } 205 206 // adjusts all values by |adjust(value)| 207 void adjustEntries( 208 std::function<void(size_t /* ix */, TYPE(& /* entry */)[ENTRY_SIZE])> update) { 209 size_t nEntries = mTotalNumTableEntries + mNumValuesInCurrEntry / ENTRY_SIZE; 210 size_t ix = 0; 211 for (TYPE *entryArray : mTableEntryList) { 212 size_t num = std::min(nEntries, (size_t)mElementCapacity); 213 for (size_t i = 0; i < num; ++i) { 214 update(ix++, (TYPE(&)[ENTRY_SIZE])(*entryArray)); 215 entryArray += ENTRY_SIZE; 216 } 217 nEntries -= num; 218 } 219 } 220 221 // Store a single value. 222 // @arg value must be in network byte order. 223 void add(const TYPE& value) { 224 CHECK_LT(mNumValuesInCurrEntry, mElementCapacity); 225 uint32_t nEntries = mTotalNumTableEntries % mElementCapacity; 226 uint32_t nValues = mNumValuesInCurrEntry % ENTRY_SIZE; 227 if (nEntries == 0 && nValues == 0) { 228 mCurrTableEntriesElement = new TYPE[ENTRY_SIZE * mElementCapacity]; 229 CHECK(mCurrTableEntriesElement != NULL); 230 mTableEntryList.push_back(mCurrTableEntriesElement); 231 } 232 233 uint32_t pos = nEntries * ENTRY_SIZE + nValues; 234 mCurrTableEntriesElement[pos] = value; 235 236 ++mNumValuesInCurrEntry; 237 if ((mNumValuesInCurrEntry % ENTRY_SIZE) == 0) { 238 ++mTotalNumTableEntries; 239 mNumValuesInCurrEntry = 0; 240 } 241 } 242 243 // Write out the table entries: 244 // 1. the number of entries goes first 245 // 2. followed by the values in the table enties in order 246 // @arg writer the writer to actual write to the storage 247 void write(MPEG4Writer *writer) const { 248 CHECK_EQ(mNumValuesInCurrEntry % ENTRY_SIZE, 0u); 249 uint32_t nEntries = mTotalNumTableEntries; 250 writer->writeInt32(nEntries); 251 for (typename List<TYPE *>::iterator it = mTableEntryList.begin(); 252 it != mTableEntryList.end(); ++it) { 253 CHECK_GT(nEntries, 0u); 254 if (nEntries >= mElementCapacity) { 255 writer->write(*it, sizeof(TYPE) * ENTRY_SIZE, mElementCapacity); 256 nEntries -= mElementCapacity; 257 } else { 258 writer->write(*it, sizeof(TYPE) * ENTRY_SIZE, nEntries); 259 break; 260 } 261 } 262 } 263 264 // Return the number of entries in the table. 265 uint32_t count() const { return mTotalNumTableEntries; } 266 267 private: 268 uint32_t mElementCapacity; // # entries in an element 269 uint32_t mTotalNumTableEntries; 270 uint32_t mNumValuesInCurrEntry; // up to ENTRY_SIZE 271 TYPE *mCurrTableEntriesElement; 272 mutable List<TYPE *> mTableEntryList; 273 274 DISALLOW_EVIL_CONSTRUCTORS(ListTableEntries); 275 }; 276 277 278 279 MPEG4Writer *mOwner; 280 sp<MetaData> mMeta; 281 sp<MediaSource> mSource; 282 volatile bool mDone; 283 volatile bool mPaused; 284 volatile bool mResumed; 285 volatile bool mStarted; 286 bool mIsAvc; 287 bool mIsHevc; 288 bool mIsAudio; 289 bool mIsVideo; 290 bool mIsHeic; 291 bool mIsMPEG4; 292 bool mGotStartKeyFrame; 293 bool mIsMalformed; 294 int32_t mTrackId; 295 int64_t mTrackDurationUs; 296 int64_t mMaxChunkDurationUs; 297 int64_t mLastDecodingTimeUs; 298 299 int64_t mEstimatedTrackSizeBytes; 300 int64_t mMdatSizeBytes; 301 int32_t mTimeScale; 302 303 pthread_t mThread; 304 305 306 List<MediaBuffer *> mChunkSamples; 307 308 bool mSamplesHaveSameSize; 309 ListTableEntries<uint32_t, 1> *mStszTableEntries; 310 311 ListTableEntries<uint32_t, 1> *mStcoTableEntries; 312 ListTableEntries<off64_t, 1> *mCo64TableEntries; 313 ListTableEntries<uint32_t, 3> *mStscTableEntries; 314 ListTableEntries<uint32_t, 1> *mStssTableEntries; 315 ListTableEntries<uint32_t, 2> *mSttsTableEntries; 316 ListTableEntries<uint32_t, 2> *mCttsTableEntries; 317 ListTableEntries<uint32_t, 3> *mElstTableEntries; // 3columns: segDuration, mediaTime, mediaRate 318 319 int64_t mMinCttsOffsetTimeUs; 320 int64_t mMinCttsOffsetTicks; 321 int64_t mMaxCttsOffsetTicks; 322 323 // Save the last 10 frames' timestamp and frame type for debug. 324 struct TimestampDebugHelperEntry { 325 int64_t pts; 326 int64_t dts; 327 std::string frameType; 328 }; 329 330 std::list<TimestampDebugHelperEntry> mTimestampDebugHelper; 331 332 // Sequence parameter set or picture parameter set 333 struct AVCParamSet { 334 AVCParamSet(uint16_t length, const uint8_t *data) 335 : mLength(length), mData(data) {} 336 337 uint16_t mLength; 338 const uint8_t *mData; 339 }; 340 List<AVCParamSet> mSeqParamSets; 341 List<AVCParamSet> mPicParamSets; 342 uint8_t mProfileIdc; 343 uint8_t mProfileCompatible; 344 uint8_t mLevelIdc; 345 346 void *mCodecSpecificData; 347 size_t mCodecSpecificDataSize; 348 bool mGotAllCodecSpecificData; 349 bool mTrackingProgressStatus; 350 351 bool mReachedEOS; 352 int64_t mStartTimestampUs; 353 int64_t mStartTimeRealUs; 354 int64_t mFirstSampleTimeRealUs; 355 int64_t mPreviousTrackTimeUs; 356 int64_t mTrackEveryTimeDurationUs; 357 358 int32_t mRotation; 359 360 Vector<uint16_t> mProperties; 361 ItemRefs mDimgRefs; 362 Vector<uint16_t> mExifList; 363 uint16_t mImageItemId; 364 int32_t mIsPrimary; 365 int32_t mWidth, mHeight; 366 int32_t mTileWidth, mTileHeight; 367 int32_t mGridRows, mGridCols; 368 size_t mNumTiles, mTileIndex; 369 370 // Update the audio track's drift information. 371 void updateDriftTime(const sp<MetaData>& meta); 372 373 void dumpTimeStamps(); 374 375 int64_t getStartTimeOffsetTimeUs() const; 376 int32_t getStartTimeOffsetScaledTime() const; 377 378 static void *ThreadWrapper(void *me); 379 status_t threadEntry(); 380 381 const uint8_t *parseParamSet( 382 const uint8_t *data, size_t length, int type, size_t *paramSetLen); 383 384 status_t copyCodecSpecificData(const uint8_t *data, size_t size, size_t minLength = 0); 385 386 status_t makeAVCCodecSpecificData(const uint8_t *data, size_t size); 387 status_t copyAVCCodecSpecificData(const uint8_t *data, size_t size); 388 status_t parseAVCCodecSpecificData(const uint8_t *data, size_t size); 389 390 status_t makeHEVCCodecSpecificData(const uint8_t *data, size_t size); 391 status_t copyHEVCCodecSpecificData(const uint8_t *data, size_t size); 392 status_t parseHEVCCodecSpecificData( 393 const uint8_t *data, size_t size, HevcParameterSets ¶mSets); 394 395 // Track authoring progress status 396 void trackProgressStatus(int64_t timeUs, status_t err = OK); 397 void initTrackingProgressStatus(MetaData *params); 398 399 void getCodecSpecificDataFromInputFormatIfPossible(); 400 401 // Determine the track time scale 402 // If it is an audio track, try to use the sampling rate as 403 // the time scale; however, if user chooses the overwrite 404 // value, the user-supplied time scale will be used. 405 void setTimeScale(); 406 407 // Simple validation on the codec specific data 408 status_t checkCodecSpecificData() const; 409 410 void updateTrackSizeEstimate(); 411 void addOneStscTableEntry(size_t chunkId, size_t sampleId); 412 void addOneStssTableEntry(size_t sampleId); 413 414 // Duration is time scale based 415 void addOneSttsTableEntry(size_t sampleCount, int32_t timescaledDur); 416 void addOneCttsTableEntry(size_t sampleCount, int32_t timescaledDur); 417 void addOneElstTableEntry(uint32_t segmentDuration, int32_t mediaTime, 418 int16_t mediaRate, int16_t mediaRateFraction); 419 420 bool isTrackMalFormed() const; 421 void sendTrackSummary(bool hasMultipleTracks); 422 423 // Write the boxes 424 void writeStcoBox(bool use32BitOffset); 425 void writeStscBox(); 426 void writeStszBox(); 427 void writeStssBox(); 428 void writeSttsBox(); 429 void writeCttsBox(); 430 void writeD263Box(); 431 void writePaspBox(); 432 void writeAvccBox(); 433 void writeHvccBox(); 434 void writeUrlBox(); 435 void writeDrefBox(); 436 void writeDinfBox(); 437 void writeDamrBox(); 438 void writeMdhdBox(uint32_t now); 439 void writeSmhdBox(); 440 void writeVmhdBox(); 441 void writeNmhdBox(); 442 void writeHdlrBox(); 443 void writeTkhdBox(uint32_t now); 444 void writeColrBox(); 445 void writeMp4aEsdsBox(); 446 void writeMp4vEsdsBox(); 447 void writeAudioFourCCBox(); 448 void writeVideoFourCCBox(); 449 void writeMetadataFourCCBox(); 450 void writeStblBox(bool use32BitOffset); 451 void writeEdtsBox(); 452 453 Track(const Track &); 454 Track &operator=(const Track &); 455 }; 456 457 MPEG4Writer::MPEG4Writer(int fd) { 458 initInternal(dup(fd), true /*isFirstSession*/); 459 } 460 461 MPEG4Writer::~MPEG4Writer() { 462 reset(); 463 464 while (!mTracks.empty()) { 465 List<Track *>::iterator it = mTracks.begin(); 466 delete *it; 467 (*it) = NULL; 468 mTracks.erase(it); 469 } 470 mTracks.clear(); 471 472 if (mNextFd != -1) { 473 close(mNextFd); 474 } 475 } 476 477 void MPEG4Writer::initInternal(int fd, bool isFirstSession) { 478 ALOGV("initInternal"); 479 mFd = fd; 480 mNextFd = -1; 481 mInitCheck = mFd < 0? NO_INIT: OK; 482 483 mInterleaveDurationUs = 1000000; 484 485 mStartTimestampUs = -1LL; 486 mStartTimeOffsetMs = -1; 487 mStartTimeOffsetBFramesUs = 0; 488 mPaused = false; 489 mStarted = false; 490 mWriterThreadStarted = false; 491 mSendNotify = false; 492 493 // Reset following variables for all the sessions and they will be 494 // initialized in start(MetaData *param). 495 mIsRealTimeRecording = true; 496 mUse4ByteNalLength = true; 497 mUse32BitOffset = true; 498 mOffset = 0; 499 mMdatOffset = 0; 500 mInMemoryCache = NULL; 501 mInMemoryCacheOffset = 0; 502 mInMemoryCacheSize = 0; 503 mWriteBoxToMemory = false; 504 mFreeBoxOffset = 0; 505 mStreamableFile = false; 506 mTimeScale = -1; 507 mHasFileLevelMeta = false; 508 mPrimaryItemId = 0; 509 mAssociationEntryCount = 0; 510 mNumGrids = 0; 511 mHasRefs = false; 512 513 // Following variables only need to be set for the first recording session. 514 // And they will stay the same for all the recording sessions. 515 if (isFirstSession) { 516 mMoovExtraSize = 0; 517 mHasMoovBox = false; 518 mMetaKeys = new AMessage(); 519 addDeviceMeta(); 520 mLatitudex10000 = 0; 521 mLongitudex10000 = 0; 522 mAreGeoTagsAvailable = false; 523 mSwitchPending = false; 524 mIsFileSizeLimitExplicitlyRequested = false; 525 } 526 527 // Verify mFd is seekable 528 off64_t off = lseek64(mFd, 0, SEEK_SET); 529 if (off < 0) { 530 ALOGE("cannot seek mFd: %s (%d) %lld", strerror(errno), errno, (long long)mFd); 531 release(); 532 } 533 for (List<Track *>::iterator it = mTracks.begin(); 534 it != mTracks.end(); ++it) { 535 (*it)->resetInternal(); 536 } 537 } 538 539 status_t MPEG4Writer::dump( 540 int fd, const Vector<String16>& args) { 541 const size_t SIZE = 256; 542 char buffer[SIZE]; 543 String8 result; 544 snprintf(buffer, SIZE, " MPEG4Writer %p\n", this); 545 result.append(buffer); 546 snprintf(buffer, SIZE, " mStarted: %s\n", mStarted? "true": "false"); 547 result.append(buffer); 548 ::write(fd, result.string(), result.size()); 549 for (List<Track *>::iterator it = mTracks.begin(); 550 it != mTracks.end(); ++it) { 551 (*it)->dump(fd, args); 552 } 553 return OK; 554 } 555 556 status_t MPEG4Writer::Track::dump( 557 int fd, const Vector<String16>& /* args */) const { 558 const size_t SIZE = 256; 559 char buffer[SIZE]; 560 String8 result; 561 snprintf(buffer, SIZE, " %s track\n", getTrackType()); 562 result.append(buffer); 563 snprintf(buffer, SIZE, " reached EOS: %s\n", 564 mReachedEOS? "true": "false"); 565 result.append(buffer); 566 snprintf(buffer, SIZE, " frames encoded : %d\n", mStszTableEntries->count()); 567 result.append(buffer); 568 snprintf(buffer, SIZE, " duration encoded : %" PRId64 " us\n", mTrackDurationUs); 569 result.append(buffer); 570 ::write(fd, result.string(), result.size()); 571 return OK; 572 } 573 574 // static 575 const char *MPEG4Writer::Track::getFourCCForMime(const char *mime) { 576 if (mime == NULL) { 577 return NULL; 578 } 579 if (!strncasecmp(mime, "audio/", 6)) { 580 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) { 581 return "samr"; 582 } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 583 return "sawb"; 584 } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 585 return "mp4a"; 586 } 587 } else if (!strncasecmp(mime, "video/", 6)) { 588 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 589 return "mp4v"; 590 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 591 return "s263"; 592 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 593 return "avc1"; 594 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) { 595 return "hvc1"; 596 } 597 } else if (!strncasecmp(mime, "application/", 12)) { 598 return "mett"; 599 } else if (!strcasecmp(MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC, mime)) { 600 return "heic"; 601 } else { 602 ALOGE("Track (%s) other than video/audio/metadata is not supported", mime); 603 } 604 return NULL; 605 } 606 607 status_t MPEG4Writer::addSource(const sp<MediaSource> &source) { 608 Mutex::Autolock l(mLock); 609 if (mStarted) { 610 ALOGE("Attempt to add source AFTER recording is started"); 611 return UNKNOWN_ERROR; 612 } 613 614 CHECK(source.get() != NULL); 615 616 const char *mime; 617 source->getFormat()->findCString(kKeyMIMEType, &mime); 618 619 if (Track::getFourCCForMime(mime) == NULL) { 620 ALOGE("Unsupported mime '%s'", mime); 621 return ERROR_UNSUPPORTED; 622 } 623 624 // This is a metadata track or the first track of either audio or video 625 // Go ahead to add the track. 626 Track *track = new Track(this, source, 1 + mTracks.size()); 627 mTracks.push_back(track); 628 629 mHasMoovBox |= !track->isHeic(); 630 mHasFileLevelMeta |= track->isHeic(); 631 632 return OK; 633 } 634 635 status_t MPEG4Writer::startTracks(MetaData *params) { 636 if (mTracks.empty()) { 637 ALOGE("No source added"); 638 return INVALID_OPERATION; 639 } 640 641 for (List<Track *>::iterator it = mTracks.begin(); 642 it != mTracks.end(); ++it) { 643 status_t err = (*it)->start(params); 644 645 if (err != OK) { 646 for (List<Track *>::iterator it2 = mTracks.begin(); 647 it2 != it; ++it2) { 648 (*it2)->stop(); 649 } 650 651 return err; 652 } 653 } 654 return OK; 655 } 656 657 void MPEG4Writer::addDeviceMeta() { 658 // add device info and estimate space in 'moov' 659 char val[PROPERTY_VALUE_MAX]; 660 size_t n; 661 // meta size is estimated by adding up the following: 662 // - meta header structures, which occur only once (total 66 bytes) 663 // - size for each key, which consists of a fixed header (32 bytes), 664 // plus key length and data length. 665 mMoovExtraSize += 66; 666 if (property_get("ro.build.version.release", val, NULL) 667 && (n = strlen(val)) > 0) { 668 mMetaKeys->setString(kMetaKey_Version, val, n + 1); 669 mMoovExtraSize += sizeof(kMetaKey_Version) + n + 32; 670 } 671 672 if (property_get_bool("media.recorder.show_manufacturer_and_model", false)) { 673 if (property_get("ro.product.manufacturer", val, NULL) 674 && (n = strlen(val)) > 0) { 675 mMetaKeys->setString(kMetaKey_Manufacturer, val, n + 1); 676 mMoovExtraSize += sizeof(kMetaKey_Manufacturer) + n + 32; 677 } 678 if (property_get("ro.product.model", val, NULL) 679 && (n = strlen(val)) > 0) { 680 mMetaKeys->setString(kMetaKey_Model, val, n + 1); 681 mMoovExtraSize += sizeof(kMetaKey_Model) + n + 32; 682 } 683 } 684 #ifdef SHOW_MODEL_BUILD 685 if (property_get("ro.build.display.id", val, NULL) 686 && (n = strlen(val)) > 0) { 687 mMetaKeys->setString(kMetaKey_Build, val, n + 1); 688 mMoovExtraSize += sizeof(kMetaKey_Build) + n + 32; 689 } 690 #endif 691 } 692 693 int64_t MPEG4Writer::estimateFileLevelMetaSize(MetaData *params) { 694 int32_t rotation; 695 if (!params || !params->findInt32(kKeyRotation, &rotation)) { 696 rotation = 0; 697 } 698 699 // base meta size 700 int64_t metaSize = 12 // meta fullbox header 701 + 33 // hdlr box 702 + 14 // pitm box 703 + 16 // iloc box (fixed size portion) 704 + 14 // iinf box (fixed size portion) 705 + 32 // iprp box (fixed size protion) 706 + 8 // idat box (when empty) 707 + 12 // iref box (when empty) 708 ; 709 710 for (List<Track *>::iterator it = mTracks.begin(); 711 it != mTracks.end(); ++it) { 712 if ((*it)->isHeic()) { 713 metaSize += (*it)->getMetaSizeIncrease(rotation, mTracks.size()); 714 } 715 } 716 717 ALOGV("estimated meta size: %lld", (long long) metaSize); 718 719 // Need at least 8-byte padding at the end, otherwise the left-over 720 // freebox may become malformed 721 return metaSize + 8; 722 } 723 724 int64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) { 725 // This implementation is highly experimental/heurisitic. 726 // 727 // Statistical analysis shows that metadata usually accounts 728 // for a small portion of the total file size, usually < 0.6%. 729 730 // The default MIN_MOOV_BOX_SIZE is set to 0.6% x 1MB / 2, 731 // where 1MB is the common file size limit for MMS application. 732 // The default MAX _MOOV_BOX_SIZE value is based on about 3 733 // minute video recording with a bit rate about 3 Mbps, because 734 // statistics also show that most of the video captured are going 735 // to be less than 3 minutes. 736 737 // If the estimation is wrong, we will pay the price of wasting 738 // some reserved space. This should not happen so often statistically. 739 static const int32_t factor = mUse32BitOffset? 1: 2; 740 static const int64_t MIN_MOOV_BOX_SIZE = 3 * 1024; // 3 KB 741 static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000); 742 int64_t size = MIN_MOOV_BOX_SIZE; 743 744 // Max file size limit is set 745 if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) { 746 size = mMaxFileSizeLimitBytes * 6 / 1000; 747 } 748 749 // Max file duration limit is set 750 if (mMaxFileDurationLimitUs != 0) { 751 if (bitRate > 0) { 752 int64_t size2 = 753 ((mMaxFileDurationLimitUs / 1000) * bitRate * 6) / 8000000; 754 if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) { 755 // When both file size and duration limits are set, 756 // we use the smaller limit of the two. 757 if (size > size2) { 758 size = size2; 759 } 760 } else { 761 // Only max file duration limit is set 762 size = size2; 763 } 764 } 765 } 766 767 if (size < MIN_MOOV_BOX_SIZE) { 768 size = MIN_MOOV_BOX_SIZE; 769 } 770 771 // Any long duration recording will be probably end up with 772 // non-streamable mp4 file. 773 if (size > MAX_MOOV_BOX_SIZE) { 774 size = MAX_MOOV_BOX_SIZE; 775 } 776 777 // Account for the extra stuff (Geo, meta keys, etc.) 778 size += mMoovExtraSize; 779 780 ALOGI("limits: %" PRId64 "/%" PRId64 " bytes/us, bit rate: %d bps and the" 781 " estimated moov size %" PRId64 " bytes", 782 mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size); 783 784 int64_t estimatedSize = factor * size; 785 CHECK_GE(estimatedSize, 8); 786 787 return estimatedSize; 788 } 789 790 status_t MPEG4Writer::start(MetaData *param) { 791 if (mInitCheck != OK) { 792 return UNKNOWN_ERROR; 793 } 794 mStartMeta = param; 795 796 /* 797 * Check mMaxFileSizeLimitBytes at the beginning 798 * since mMaxFileSizeLimitBytes may be implicitly 799 * changed later for 32-bit file offset even if 800 * user does not ask to set it explicitly. 801 */ 802 if (mMaxFileSizeLimitBytes != 0) { 803 mIsFileSizeLimitExplicitlyRequested = true; 804 } 805 806 int32_t use64BitOffset; 807 if (param && 808 param->findInt32(kKey64BitFileOffset, &use64BitOffset) && 809 use64BitOffset) { 810 mUse32BitOffset = false; 811 } 812 813 if (mUse32BitOffset) { 814 // Implicit 32 bit file size limit 815 if (mMaxFileSizeLimitBytes == 0) { 816 mMaxFileSizeLimitBytes = kMax32BitFileSize; 817 } 818 819 // If file size is set to be larger than the 32 bit file 820 // size limit, treat it as an error. 821 if (mMaxFileSizeLimitBytes > kMax32BitFileSize) { 822 ALOGW("32-bit file size limit (%" PRId64 " bytes) too big. " 823 "It is changed to %" PRId64 " bytes", 824 mMaxFileSizeLimitBytes, kMax32BitFileSize); 825 mMaxFileSizeLimitBytes = kMax32BitFileSize; 826 } 827 } 828 829 int32_t use2ByteNalLength; 830 if (param && 831 param->findInt32(kKey2ByteNalLength, &use2ByteNalLength) && 832 use2ByteNalLength) { 833 mUse4ByteNalLength = false; 834 } 835 836 int32_t isRealTimeRecording; 837 if (param && param->findInt32(kKeyRealTimeRecording, &isRealTimeRecording)) { 838 mIsRealTimeRecording = isRealTimeRecording; 839 } 840 841 mStartTimestampUs = -1; 842 843 if (mStarted) { 844 if (mPaused) { 845 mPaused = false; 846 return startTracks(param); 847 } 848 return OK; 849 } 850 851 if (!param || 852 !param->findInt32(kKeyTimeScale, &mTimeScale)) { 853 mTimeScale = 1000; 854 } 855 CHECK_GT(mTimeScale, 0); 856 ALOGV("movie time scale: %d", mTimeScale); 857 858 /* 859 * When the requested file size limit is small, the priority 860 * is to meet the file size limit requirement, rather than 861 * to make the file streamable. mStreamableFile does not tell 862 * whether the actual recorded file is streamable or not. 863 */ 864 mStreamableFile = 865 (mMaxFileSizeLimitBytes != 0 && 866 mMaxFileSizeLimitBytes >= kMinStreamableFileSizeInBytes); 867 868 /* 869 * mWriteBoxToMemory is true if the amount of data in a file-level meta or 870 * moov box is smaller than the reserved free space at the beginning of a 871 * file, AND when the content of the box is constructed. Note that video/ 872 * audio frame data is always written to the file but not in the memory. 873 * 874 * Before stop()/reset() is called, mWriteBoxToMemory is always 875 * false. When reset() is called at the end of a recording session, 876 * file-level meta and/or moov box needs to be constructed. 877 * 878 * 1) Right before the box is constructed, mWriteBoxToMemory to set to 879 * mStreamableFile so that if the file is intended to be streamable, it 880 * is set to true; otherwise, it is set to false. When the value is set 881 * to false, all the content of that box is written immediately to 882 * the end of the file. When the value is set to true, all the 883 * content of that box is written to an in-memory cache, 884 * mInMemoryCache, util the following condition happens. Note 885 * that the size of the in-memory cache is the same as the 886 * reserved free space at the beginning of the file. 887 * 888 * 2) While the data of the box is written to an in-memory 889 * cache, the data size is checked against the reserved space. 890 * If the data size surpasses the reserved space, subsequent box data 891 * could no longer be hold in the in-memory cache. This also 892 * indicates that the reserved space was too small. At this point, 893 * _all_ subsequent box data must be written to the end of the file. 894 * mWriteBoxToMemory must be set to false to direct the write 895 * to the file. 896 * 897 * 3) If the data size in the box is smaller than the reserved 898 * space after the box is completely constructed, the in-memory 899 * cache copy of the box is written to the reserved free space. 900 * mWriteBoxToMemory is always set to false after all boxes that 901 * using the in-memory cache have been constructed. 902 */ 903 mWriteBoxToMemory = false; 904 mInMemoryCache = NULL; 905 mInMemoryCacheOffset = 0; 906 907 908 ALOGV("muxer starting: mHasMoovBox %d, mHasFileLevelMeta %d", 909 mHasMoovBox, mHasFileLevelMeta); 910 911 writeFtypBox(param); 912 913 mFreeBoxOffset = mOffset; 914 915 if (mInMemoryCacheSize == 0) { 916 int32_t bitRate = -1; 917 if (mHasFileLevelMeta) { 918 mInMemoryCacheSize += estimateFileLevelMetaSize(param); 919 } 920 if (mHasMoovBox) { 921 if (param) { 922 param->findInt32(kKeyBitRate, &bitRate); 923 } 924 mInMemoryCacheSize += estimateMoovBoxSize(bitRate); 925 } 926 } 927 if (mStreamableFile) { 928 // Reserve a 'free' box only for streamable file 929 lseek64(mFd, mFreeBoxOffset, SEEK_SET); 930 writeInt32(mInMemoryCacheSize); 931 write("free", 4); 932 mMdatOffset = mFreeBoxOffset + mInMemoryCacheSize; 933 } else { 934 mMdatOffset = mOffset; 935 } 936 937 mOffset = mMdatOffset; 938 lseek64(mFd, mMdatOffset, SEEK_SET); 939 if (mUse32BitOffset) { 940 write("????mdat", 8); 941 } else { 942 write("\x00\x00\x00\x01mdat????????", 16); 943 } 944 945 status_t err = startWriterThread(); 946 if (err != OK) { 947 return err; 948 } 949 950 err = startTracks(param); 951 if (err != OK) { 952 return err; 953 } 954 955 mStarted = true; 956 return OK; 957 } 958 959 bool MPEG4Writer::use32BitFileOffset() const { 960 return mUse32BitOffset; 961 } 962 963 status_t MPEG4Writer::pause() { 964 ALOGW("MPEG4Writer: pause is not supported"); 965 return ERROR_UNSUPPORTED; 966 } 967 968 void MPEG4Writer::stopWriterThread() { 969 ALOGD("Stopping writer thread"); 970 if (!mWriterThreadStarted) { 971 return; 972 } 973 974 { 975 Mutex::Autolock autolock(mLock); 976 977 mDone = true; 978 mChunkReadyCondition.signal(); 979 } 980 981 void *dummy; 982 pthread_join(mThread, &dummy); 983 mWriterThreadStarted = false; 984 ALOGD("Writer thread stopped"); 985 } 986 987 /* 988 * MP4 file standard defines a composition matrix: 989 * | a b u | 990 * | c d v | 991 * | x y w | 992 * 993 * the element in the matrix is stored in the following 994 * order: {a, b, u, c, d, v, x, y, w}, 995 * where a, b, c, d, x, and y is in 16.16 format, while 996 * u, v and w is in 2.30 format. 997 */ 998 void MPEG4Writer::writeCompositionMatrix(int degrees) { 999 ALOGV("writeCompositionMatrix"); 1000 uint32_t a = 0x00010000; 1001 uint32_t b = 0; 1002 uint32_t c = 0; 1003 uint32_t d = 0x00010000; 1004 switch (degrees) { 1005 case 0: 1006 break; 1007 case 90: 1008 a = 0; 1009 b = 0x00010000; 1010 c = 0xFFFF0000; 1011 d = 0; 1012 break; 1013 case 180: 1014 a = 0xFFFF0000; 1015 d = 0xFFFF0000; 1016 break; 1017 case 270: 1018 a = 0; 1019 b = 0xFFFF0000; 1020 c = 0x00010000; 1021 d = 0; 1022 break; 1023 default: 1024 CHECK(!"Should never reach this unknown rotation"); 1025 break; 1026 } 1027 1028 writeInt32(a); // a 1029 writeInt32(b); // b 1030 writeInt32(0); // u 1031 writeInt32(c); // c 1032 writeInt32(d); // d 1033 writeInt32(0); // v 1034 writeInt32(0); // x 1035 writeInt32(0); // y 1036 writeInt32(0x40000000); // w 1037 } 1038 1039 void MPEG4Writer::release() { 1040 close(mFd); 1041 mFd = -1; 1042 if (mNextFd != -1) { 1043 close(mNextFd); 1044 mNextFd = -1; 1045 } 1046 mInitCheck = NO_INIT; 1047 mStarted = false; 1048 free(mInMemoryCache); 1049 mInMemoryCache = NULL; 1050 } 1051 1052 void MPEG4Writer::finishCurrentSession() { 1053 reset(false /* stopSource */); 1054 } 1055 1056 status_t MPEG4Writer::switchFd() { 1057 ALOGV("switchFd"); 1058 Mutex::Autolock l(mLock); 1059 if (mSwitchPending) { 1060 return OK; 1061 } 1062 1063 if (mNextFd == -1) { 1064 ALOGW("No FileDescripter for next recording"); 1065 return INVALID_OPERATION; 1066 } 1067 1068 mSwitchPending = true; 1069 sp<AMessage> msg = new AMessage(kWhatSwitch, mReflector); 1070 status_t err = msg->post(); 1071 1072 return err; 1073 } 1074 1075 status_t MPEG4Writer::reset(bool stopSource) { 1076 if (mInitCheck != OK) { 1077 return OK; 1078 } else { 1079 if (!mWriterThreadStarted || 1080 !mStarted) { 1081 if (mWriterThreadStarted) { 1082 stopWriterThread(); 1083 } 1084 release(); 1085 return OK; 1086 } 1087 } 1088 1089 status_t err = OK; 1090 int64_t maxDurationUs = 0; 1091 int64_t minDurationUs = 0x7fffffffffffffffLL; 1092 int32_t nonImageTrackCount = 0; 1093 for (List<Track *>::iterator it = mTracks.begin(); 1094 it != mTracks.end(); ++it) { 1095 status_t status = (*it)->stop(stopSource); 1096 if (err == OK && status != OK) { 1097 err = status; 1098 } 1099 1100 // skip image tracks 1101 if ((*it)->isHeic()) continue; 1102 nonImageTrackCount++; 1103 1104 int64_t durationUs = (*it)->getDurationUs(); 1105 if (durationUs > maxDurationUs) { 1106 maxDurationUs = durationUs; 1107 } 1108 if (durationUs < minDurationUs) { 1109 minDurationUs = durationUs; 1110 } 1111 } 1112 1113 if (nonImageTrackCount > 1) { 1114 ALOGD("Duration from tracks range is [%" PRId64 ", %" PRId64 "] us", 1115 minDurationUs, maxDurationUs); 1116 } 1117 1118 stopWriterThread(); 1119 1120 // Do not write out movie header on error. 1121 if (err != OK) { 1122 release(); 1123 return err; 1124 } 1125 1126 // Fix up the size of the 'mdat' chunk. 1127 if (mUse32BitOffset) { 1128 lseek64(mFd, mMdatOffset, SEEK_SET); 1129 uint32_t size = htonl(static_cast<uint32_t>(mOffset - mMdatOffset)); 1130 ::write(mFd, &size, 4); 1131 } else { 1132 lseek64(mFd, mMdatOffset + 8, SEEK_SET); 1133 uint64_t size = mOffset - mMdatOffset; 1134 size = hton64(size); 1135 ::write(mFd, &size, 8); 1136 } 1137 lseek64(mFd, mOffset, SEEK_SET); 1138 1139 // Construct file-level meta and moov box now 1140 mInMemoryCacheOffset = 0; 1141 mWriteBoxToMemory = mStreamableFile; 1142 if (mWriteBoxToMemory) { 1143 // There is no need to allocate in-memory cache 1144 // if the file is not streamable. 1145 1146 mInMemoryCache = (uint8_t *) malloc(mInMemoryCacheSize); 1147 CHECK(mInMemoryCache != NULL); 1148 } 1149 1150 if (mHasFileLevelMeta) { 1151 writeFileLevelMetaBox(); 1152 if (mWriteBoxToMemory) { 1153 writeCachedBoxToFile("meta"); 1154 } else { 1155 ALOGI("The file meta box is written at the end."); 1156 } 1157 } 1158 1159 if (mHasMoovBox) { 1160 writeMoovBox(maxDurationUs); 1161 // mWriteBoxToMemory could be set to false in 1162 // MPEG4Writer::write() method 1163 if (mWriteBoxToMemory) { 1164 writeCachedBoxToFile("moov"); 1165 } else { 1166 ALOGI("The mp4 file will not be streamable."); 1167 } 1168 } 1169 mWriteBoxToMemory = false; 1170 1171 // Free in-memory cache for box writing 1172 if (mInMemoryCache != NULL) { 1173 free(mInMemoryCache); 1174 mInMemoryCache = NULL; 1175 mInMemoryCacheOffset = 0; 1176 } 1177 1178 CHECK(mBoxes.empty()); 1179 1180 release(); 1181 return err; 1182 } 1183 1184 /* 1185 * Writes currently cached box into file. 1186 * 1187 * Must be called while mWriteBoxToMemory is true, and will not modify 1188 * mWriteBoxToMemory. After the call, remaining cache size will be 1189 * reduced and buffer offset will be set to the beginning of the cache. 1190 */ 1191 void MPEG4Writer::writeCachedBoxToFile(const char *type) { 1192 CHECK(mWriteBoxToMemory); 1193 1194 mWriteBoxToMemory = false; 1195 // Content of the box is saved in the cache, and the in-memory 1196 // box needs to be written to the file in a single shot. 1197 1198 CHECK_LE(mInMemoryCacheOffset + 8, mInMemoryCacheSize); 1199 1200 // Cached box 1201 lseek64(mFd, mFreeBoxOffset, SEEK_SET); 1202 mOffset = mFreeBoxOffset; 1203 write(mInMemoryCache, 1, mInMemoryCacheOffset); 1204 1205 // Free box 1206 lseek64(mFd, mOffset, SEEK_SET); 1207 mFreeBoxOffset = mOffset; 1208 writeInt32(mInMemoryCacheSize - mInMemoryCacheOffset); 1209 write("free", 4); 1210 1211 // Rewind buffering to the beginning, and restore mWriteBoxToMemory flag 1212 mInMemoryCacheSize -= mInMemoryCacheOffset; 1213 mInMemoryCacheOffset = 0; 1214 mWriteBoxToMemory = true; 1215 1216 ALOGV("dumped out %s box, estimated size remaining %lld", 1217 type, (long long)mInMemoryCacheSize); 1218 } 1219 1220 uint32_t MPEG4Writer::getMpeg4Time() { 1221 time_t now = time(NULL); 1222 // MP4 file uses time counting seconds since midnight, Jan. 1, 1904 1223 // while time function returns Unix epoch values which starts 1224 // at 1970-01-01. Lets add the number of seconds between them 1225 static const uint32_t delta = (66 * 365 + 17) * (24 * 60 * 60); 1226 if (now < 0 || uint32_t(now) > UINT32_MAX - delta) { 1227 return 0; 1228 } 1229 uint32_t mpeg4Time = uint32_t(now) + delta; 1230 return mpeg4Time; 1231 } 1232 1233 void MPEG4Writer::writeMvhdBox(int64_t durationUs) { 1234 uint32_t now = getMpeg4Time(); 1235 beginBox("mvhd"); 1236 writeInt32(0); // version=0, flags=0 1237 writeInt32(now); // creation time 1238 writeInt32(now); // modification time 1239 writeInt32(mTimeScale); // mvhd timescale 1240 int32_t duration = (durationUs * mTimeScale + 5E5) / 1E6; 1241 writeInt32(duration); 1242 writeInt32(0x10000); // rate: 1.0 1243 writeInt16(0x100); // volume 1244 writeInt16(0); // reserved 1245 writeInt32(0); // reserved 1246 writeInt32(0); // reserved 1247 writeCompositionMatrix(0); // matrix 1248 writeInt32(0); // predefined 1249 writeInt32(0); // predefined 1250 writeInt32(0); // predefined 1251 writeInt32(0); // predefined 1252 writeInt32(0); // predefined 1253 writeInt32(0); // predefined 1254 writeInt32(mTracks.size() + 1); // nextTrackID 1255 endBox(); // mvhd 1256 } 1257 1258 void MPEG4Writer::writeMoovBox(int64_t durationUs) { 1259 beginBox("moov"); 1260 writeMvhdBox(durationUs); 1261 if (mAreGeoTagsAvailable) { 1262 writeUdtaBox(); 1263 } 1264 writeMoovLevelMetaBox(); 1265 // Loop through all the tracks to get the global time offset if there is 1266 // any ctts table appears in a video track. 1267 int64_t minCttsOffsetTimeUs = kMaxCttsOffsetTimeUs; 1268 for (List<Track *>::iterator it = mTracks.begin(); 1269 it != mTracks.end(); ++it) { 1270 if (!(*it)->isHeic()) { 1271 minCttsOffsetTimeUs = 1272 std::min(minCttsOffsetTimeUs, (*it)->getMinCttsOffsetTimeUs()); 1273 } 1274 } 1275 ALOGI("Ajust the moov start time from %lld us -> %lld us", 1276 (long long)mStartTimestampUs, 1277 (long long)(mStartTimestampUs + minCttsOffsetTimeUs - kMaxCttsOffsetTimeUs)); 1278 // Adjust the global start time. 1279 mStartTimestampUs += minCttsOffsetTimeUs - kMaxCttsOffsetTimeUs; 1280 1281 // Add mStartTimeOffsetBFramesUs(-ve or zero) to the duration of first entry in STTS. 1282 mStartTimeOffsetBFramesUs = minCttsOffsetTimeUs - kMaxCttsOffsetTimeUs; 1283 ALOGV("mStartTimeOffsetBFramesUs :%" PRId32, mStartTimeOffsetBFramesUs); 1284 1285 for (List<Track *>::iterator it = mTracks.begin(); 1286 it != mTracks.end(); ++it) { 1287 if (!(*it)->isHeic()) { 1288 (*it)->writeTrackHeader(mUse32BitOffset); 1289 } 1290 } 1291 endBox(); // moov 1292 } 1293 1294 void MPEG4Writer::writeFtypBox(MetaData *param) { 1295 beginBox("ftyp"); 1296 1297 int32_t fileType; 1298 if (!param || !param->findInt32(kKeyFileType, &fileType)) { 1299 fileType = OUTPUT_FORMAT_MPEG_4; 1300 } 1301 if (fileType != OUTPUT_FORMAT_MPEG_4 && fileType != OUTPUT_FORMAT_HEIF) { 1302 writeFourcc("3gp4"); 1303 writeInt32(0); 1304 writeFourcc("isom"); 1305 writeFourcc("3gp4"); 1306 } else { 1307 // Only write "heic" as major brand if the client specified HEIF 1308 // AND we indeed receive some image heic tracks. 1309 if (fileType == OUTPUT_FORMAT_HEIF && mHasFileLevelMeta) { 1310 writeFourcc("heic"); 1311 } else { 1312 writeFourcc("mp42"); 1313 } 1314 writeInt32(0); 1315 if (mHasFileLevelMeta) { 1316 writeFourcc("mif1"); 1317 writeFourcc("heic"); 1318 } 1319 if (mHasMoovBox) { 1320 writeFourcc("isom"); 1321 writeFourcc("mp42"); 1322 } 1323 } 1324 1325 endBox(); 1326 } 1327 1328 static bool isTestModeEnabled() { 1329 #if (PROPERTY_VALUE_MAX < 5) 1330 #error "PROPERTY_VALUE_MAX must be at least 5" 1331 #endif 1332 1333 // Test mode is enabled only if rw.media.record.test system 1334 // property is enabled. 1335 if (property_get_bool("rw.media.record.test", false)) { 1336 return true; 1337 } 1338 return false; 1339 } 1340 1341 void MPEG4Writer::sendSessionSummary() { 1342 // Send session summary only if test mode is enabled 1343 if (!isTestModeEnabled()) { 1344 return; 1345 } 1346 1347 for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 1348 it != mChunkInfos.end(); ++it) { 1349 int trackNum = it->mTrack->getTrackId() << 28; 1350 notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 1351 trackNum | MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS, 1352 it->mMaxInterChunkDurUs); 1353 } 1354 } 1355 1356 status_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) { 1357 mInterleaveDurationUs = durationUs; 1358 return OK; 1359 } 1360 1361 void MPEG4Writer::lock() { 1362 mLock.lock(); 1363 } 1364 1365 void MPEG4Writer::unlock() { 1366 mLock.unlock(); 1367 } 1368 1369 off64_t MPEG4Writer::addSample_l( 1370 MediaBuffer *buffer, bool usePrefix, 1371 uint32_t tiffHdrOffset, size_t *bytesWritten) { 1372 off64_t old_offset = mOffset; 1373 1374 if (usePrefix) { 1375 addMultipleLengthPrefixedSamples_l(buffer); 1376 } else { 1377 if (tiffHdrOffset > 0) { 1378 tiffHdrOffset = htonl(tiffHdrOffset); 1379 ::write(mFd, &tiffHdrOffset, 4); // exif_tiff_header_offset field 1380 mOffset += 4; 1381 } 1382 1383 ::write(mFd, 1384 (const uint8_t *)buffer->data() + buffer->range_offset(), 1385 buffer->range_length()); 1386 1387 mOffset += buffer->range_length(); 1388 } 1389 1390 *bytesWritten = mOffset - old_offset; 1391 return old_offset; 1392 } 1393 1394 static void StripStartcode(MediaBuffer *buffer) { 1395 if (buffer->range_length() < 4) { 1396 return; 1397 } 1398 1399 const uint8_t *ptr = 1400 (const uint8_t *)buffer->data() + buffer->range_offset(); 1401 1402 if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) { 1403 buffer->set_range( 1404 buffer->range_offset() + 4, buffer->range_length() - 4); 1405 } 1406 } 1407 1408 void MPEG4Writer::addMultipleLengthPrefixedSamples_l(MediaBuffer *buffer) { 1409 const uint8_t *dataStart = (const uint8_t *)buffer->data() + buffer->range_offset(); 1410 const uint8_t *currentNalStart = dataStart; 1411 const uint8_t *nextNalStart; 1412 const uint8_t *data = dataStart; 1413 size_t nextNalSize; 1414 size_t searchSize = buffer->range_length(); 1415 1416 while (getNextNALUnit(&data, &searchSize, &nextNalStart, 1417 &nextNalSize, true) == OK) { 1418 size_t currentNalSize = nextNalStart - currentNalStart - 4 /* strip start-code */; 1419 MediaBuffer *nalBuf = new MediaBuffer((void *)currentNalStart, currentNalSize); 1420 addLengthPrefixedSample_l(nalBuf); 1421 nalBuf->release(); 1422 1423 currentNalStart = nextNalStart; 1424 } 1425 1426 size_t currentNalOffset = currentNalStart - dataStart; 1427 buffer->set_range(buffer->range_offset() + currentNalOffset, 1428 buffer->range_length() - currentNalOffset); 1429 addLengthPrefixedSample_l(buffer); 1430 } 1431 1432 void MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) { 1433 size_t length = buffer->range_length(); 1434 1435 if (mUse4ByteNalLength) { 1436 uint8_t x = length >> 24; 1437 ::write(mFd, &x, 1); 1438 x = (length >> 16) & 0xff; 1439 ::write(mFd, &x, 1); 1440 x = (length >> 8) & 0xff; 1441 ::write(mFd, &x, 1); 1442 x = length & 0xff; 1443 ::write(mFd, &x, 1); 1444 1445 ::write(mFd, 1446 (const uint8_t *)buffer->data() + buffer->range_offset(), 1447 length); 1448 1449 mOffset += length + 4; 1450 } else { 1451 CHECK_LT(length, 65536u); 1452 1453 uint8_t x = length >> 8; 1454 ::write(mFd, &x, 1); 1455 x = length & 0xff; 1456 ::write(mFd, &x, 1); 1457 ::write(mFd, (const uint8_t *)buffer->data() + buffer->range_offset(), length); 1458 mOffset += length + 2; 1459 } 1460 } 1461 1462 size_t MPEG4Writer::write( 1463 const void *ptr, size_t size, size_t nmemb) { 1464 1465 const size_t bytes = size * nmemb; 1466 if (mWriteBoxToMemory) { 1467 1468 off64_t boxSize = 8 + mInMemoryCacheOffset + bytes; 1469 if (boxSize > mInMemoryCacheSize) { 1470 // The reserved free space at the beginning of the file is not big 1471 // enough. Boxes should be written to the end of the file from now 1472 // on, but not to the in-memory cache. 1473 1474 // We write partial box that is in the memory to the file first. 1475 for (List<off64_t>::iterator it = mBoxes.begin(); 1476 it != mBoxes.end(); ++it) { 1477 (*it) += mOffset; 1478 } 1479 lseek64(mFd, mOffset, SEEK_SET); 1480 ::write(mFd, mInMemoryCache, mInMemoryCacheOffset); 1481 ::write(mFd, ptr, bytes); 1482 mOffset += (bytes + mInMemoryCacheOffset); 1483 1484 // All subsequent boxes will be written to the end of the file. 1485 mWriteBoxToMemory = false; 1486 } else { 1487 memcpy(mInMemoryCache + mInMemoryCacheOffset, ptr, bytes); 1488 mInMemoryCacheOffset += bytes; 1489 } 1490 } else { 1491 ::write(mFd, ptr, size * nmemb); 1492 mOffset += bytes; 1493 } 1494 return bytes; 1495 } 1496 1497 void MPEG4Writer::beginBox(uint32_t id) { 1498 mBoxes.push_back(mWriteBoxToMemory? 1499 mInMemoryCacheOffset: mOffset); 1500 1501 writeInt32(0); 1502 writeInt32(id); 1503 } 1504 1505 void MPEG4Writer::beginBox(const char *fourcc) { 1506 CHECK_EQ(strlen(fourcc), 4u); 1507 1508 mBoxes.push_back(mWriteBoxToMemory? 1509 mInMemoryCacheOffset: mOffset); 1510 1511 writeInt32(0); 1512 writeFourcc(fourcc); 1513 } 1514 1515 void MPEG4Writer::endBox() { 1516 CHECK(!mBoxes.empty()); 1517 1518 off64_t offset = *--mBoxes.end(); 1519 mBoxes.erase(--mBoxes.end()); 1520 1521 if (mWriteBoxToMemory) { 1522 int32_t x = htonl(mInMemoryCacheOffset - offset); 1523 memcpy(mInMemoryCache + offset, &x, 4); 1524 } else { 1525 lseek64(mFd, offset, SEEK_SET); 1526 writeInt32(mOffset - offset); 1527 mOffset -= 4; 1528 lseek64(mFd, mOffset, SEEK_SET); 1529 } 1530 } 1531 1532 void MPEG4Writer::writeInt8(int8_t x) { 1533 write(&x, 1, 1); 1534 } 1535 1536 void MPEG4Writer::writeInt16(int16_t x) { 1537 x = htons(x); 1538 write(&x, 1, 2); 1539 } 1540 1541 void MPEG4Writer::writeInt32(int32_t x) { 1542 x = htonl(x); 1543 write(&x, 1, 4); 1544 } 1545 1546 void MPEG4Writer::writeInt64(int64_t x) { 1547 x = hton64(x); 1548 write(&x, 1, 8); 1549 } 1550 1551 void MPEG4Writer::writeCString(const char *s) { 1552 size_t n = strlen(s); 1553 write(s, 1, n + 1); 1554 } 1555 1556 void MPEG4Writer::writeFourcc(const char *s) { 1557 CHECK_EQ(strlen(s), 4u); 1558 write(s, 1, 4); 1559 } 1560 1561 1562 // Written in +/-DD.DDDD format 1563 void MPEG4Writer::writeLatitude(int degreex10000) { 1564 bool isNegative = (degreex10000 < 0); 1565 char sign = isNegative? '-': '+'; 1566 1567 // Handle the whole part 1568 char str[9]; 1569 int wholePart = degreex10000 / 10000; 1570 if (wholePart == 0) { 1571 snprintf(str, 5, "%c%.2d.", sign, wholePart); 1572 } else { 1573 snprintf(str, 5, "%+.2d.", wholePart); 1574 } 1575 1576 // Handle the fractional part 1577 int fractionalPart = degreex10000 - (wholePart * 10000); 1578 if (fractionalPart < 0) { 1579 fractionalPart = -fractionalPart; 1580 } 1581 snprintf(&str[4], 5, "%.4d", fractionalPart); 1582 1583 // Do not write the null terminator 1584 write(str, 1, 8); 1585 } 1586 1587 // Written in +/- DDD.DDDD format 1588 void MPEG4Writer::writeLongitude(int degreex10000) { 1589 bool isNegative = (degreex10000 < 0); 1590 char sign = isNegative? '-': '+'; 1591 1592 // Handle the whole part 1593 char str[10]; 1594 int wholePart = degreex10000 / 10000; 1595 if (wholePart == 0) { 1596 snprintf(str, 6, "%c%.3d.", sign, wholePart); 1597 } else { 1598 snprintf(str, 6, "%+.3d.", wholePart); 1599 } 1600 1601 // Handle the fractional part 1602 int fractionalPart = degreex10000 - (wholePart * 10000); 1603 if (fractionalPart < 0) { 1604 fractionalPart = -fractionalPart; 1605 } 1606 snprintf(&str[5], 5, "%.4d", fractionalPart); 1607 1608 // Do not write the null terminator 1609 write(str, 1, 9); 1610 } 1611 1612 /* 1613 * Geodata is stored according to ISO-6709 standard. 1614 * latitudex10000 is latitude in degrees times 10000, and 1615 * longitudex10000 is longitude in degrees times 10000. 1616 * The range for the latitude is in [-90, +90], and 1617 * The range for the longitude is in [-180, +180] 1618 */ 1619 status_t MPEG4Writer::setGeoData(int latitudex10000, int longitudex10000) { 1620 // Is latitude or longitude out of range? 1621 if (latitudex10000 < -900000 || latitudex10000 > 900000 || 1622 longitudex10000 < -1800000 || longitudex10000 > 1800000) { 1623 return BAD_VALUE; 1624 } 1625 1626 mLatitudex10000 = latitudex10000; 1627 mLongitudex10000 = longitudex10000; 1628 mAreGeoTagsAvailable = true; 1629 mMoovExtraSize += 30; 1630 return OK; 1631 } 1632 1633 status_t MPEG4Writer::setCaptureRate(float captureFps) { 1634 if (captureFps <= 0.0f) { 1635 return BAD_VALUE; 1636 } 1637 1638 mMetaKeys->setFloat(kMetaKey_CaptureFps, captureFps); 1639 mMoovExtraSize += sizeof(kMetaKey_CaptureFps) + 4 + 32; 1640 1641 return OK; 1642 } 1643 1644 status_t MPEG4Writer::setTemporalLayerCount(uint32_t layerCount) { 1645 if (layerCount > 9) { 1646 return BAD_VALUE; 1647 } 1648 1649 if (layerCount > 0) { 1650 mMetaKeys->setInt32(kMetaKey_TemporalLayerCount, layerCount); 1651 mMoovExtraSize += sizeof(kMetaKey_TemporalLayerCount) + 4 + 32; 1652 } 1653 1654 return OK; 1655 } 1656 1657 void MPEG4Writer::notifyApproachingLimit() { 1658 Mutex::Autolock autolock(mLock); 1659 // Only notify once. 1660 if (mSendNotify) { 1661 return; 1662 } 1663 ALOGW("Recorded file size is approaching limit %" PRId64 "bytes", 1664 mMaxFileSizeLimitBytes); 1665 notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_APPROACHING, 0); 1666 mSendNotify = true; 1667 } 1668 1669 void MPEG4Writer::write(const void *data, size_t size) { 1670 write(data, 1, size); 1671 } 1672 1673 bool MPEG4Writer::isFileStreamable() const { 1674 return mStreamableFile; 1675 } 1676 1677 bool MPEG4Writer::exceedsFileSizeLimit() { 1678 // No limit 1679 if (mMaxFileSizeLimitBytes == 0) { 1680 return false; 1681 } 1682 int64_t nTotalBytesEstimate = static_cast<int64_t>(mInMemoryCacheSize); 1683 for (List<Track *>::iterator it = mTracks.begin(); 1684 it != mTracks.end(); ++it) { 1685 nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes(); 1686 } 1687 1688 if (!mStreamableFile) { 1689 // Add 1024 bytes as error tolerance 1690 return nTotalBytesEstimate + 1024 >= mMaxFileSizeLimitBytes; 1691 } 1692 1693 // Be conservative in the estimate: do not exceed 95% of 1694 // the target file limit. For small target file size limit, though, 1695 // this will not help. 1696 return (nTotalBytesEstimate >= (95 * mMaxFileSizeLimitBytes) / 100); 1697 } 1698 1699 bool MPEG4Writer::approachingFileSizeLimit() { 1700 // No limit 1701 if (mMaxFileSizeLimitBytes == 0) { 1702 return false; 1703 } 1704 1705 int64_t nTotalBytesEstimate = static_cast<int64_t>(mInMemoryCacheSize); 1706 for (List<Track *>::iterator it = mTracks.begin(); 1707 it != mTracks.end(); ++it) { 1708 nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes(); 1709 } 1710 1711 if (!mStreamableFile) { 1712 // Add 1024 bytes as error tolerance 1713 return nTotalBytesEstimate + 1024 >= (90 * mMaxFileSizeLimitBytes) / 100; 1714 } 1715 1716 return (nTotalBytesEstimate >= (90 * mMaxFileSizeLimitBytes) / 100); 1717 } 1718 1719 bool MPEG4Writer::exceedsFileDurationLimit() { 1720 // No limit 1721 if (mMaxFileDurationLimitUs == 0) { 1722 return false; 1723 } 1724 1725 for (List<Track *>::iterator it = mTracks.begin(); 1726 it != mTracks.end(); ++it) { 1727 if (!(*it)->isHeic() && (*it)->getDurationUs() >= mMaxFileDurationLimitUs) { 1728 return true; 1729 } 1730 } 1731 return false; 1732 } 1733 1734 bool MPEG4Writer::reachedEOS() { 1735 bool allDone = true; 1736 for (List<Track *>::iterator it = mTracks.begin(); 1737 it != mTracks.end(); ++it) { 1738 if (!(*it)->reachedEOS()) { 1739 allDone = false; 1740 break; 1741 } 1742 } 1743 1744 return allDone; 1745 } 1746 1747 void MPEG4Writer::setStartTimestampUs(int64_t timeUs) { 1748 ALOGI("setStartTimestampUs: %" PRId64, timeUs); 1749 CHECK_GE(timeUs, 0LL); 1750 Mutex::Autolock autoLock(mLock); 1751 if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) { 1752 mStartTimestampUs = timeUs; 1753 ALOGI("Earliest track starting time: %" PRId64, mStartTimestampUs); 1754 } 1755 } 1756 1757 int64_t MPEG4Writer::getStartTimestampUs() { 1758 Mutex::Autolock autoLock(mLock); 1759 return mStartTimestampUs; 1760 } 1761 1762 int32_t MPEG4Writer::getStartTimeOffsetBFramesUs() { 1763 Mutex::Autolock autoLock(mLock); 1764 return mStartTimeOffsetBFramesUs; 1765 } 1766 1767 size_t MPEG4Writer::numTracks() { 1768 Mutex::Autolock autolock(mLock); 1769 return mTracks.size(); 1770 } 1771 1772 //////////////////////////////////////////////////////////////////////////////// 1773 1774 MPEG4Writer::Track::Track( 1775 MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId) 1776 : mOwner(owner), 1777 mMeta(source->getFormat()), 1778 mSource(source), 1779 mDone(false), 1780 mPaused(false), 1781 mResumed(false), 1782 mStarted(false), 1783 mGotStartKeyFrame(false), 1784 mIsMalformed(false), 1785 mTrackId(trackId), 1786 mTrackDurationUs(0), 1787 mEstimatedTrackSizeBytes(0), 1788 mSamplesHaveSameSize(true), 1789 mStszTableEntries(new ListTableEntries<uint32_t, 1>(1000)), 1790 mStcoTableEntries(new ListTableEntries<uint32_t, 1>(1000)), 1791 mCo64TableEntries(new ListTableEntries<off64_t, 1>(1000)), 1792 mStscTableEntries(new ListTableEntries<uint32_t, 3>(1000)), 1793 mStssTableEntries(new ListTableEntries<uint32_t, 1>(1000)), 1794 mSttsTableEntries(new ListTableEntries<uint32_t, 2>(1000)), 1795 mCttsTableEntries(new ListTableEntries<uint32_t, 2>(1000)), 1796 mElstTableEntries(new ListTableEntries<uint32_t, 3>(3)), // Reserve 3 rows, a row has 3 items 1797 mMinCttsOffsetTimeUs(0), 1798 mMinCttsOffsetTicks(0), 1799 mMaxCttsOffsetTicks(0), 1800 mCodecSpecificData(NULL), 1801 mCodecSpecificDataSize(0), 1802 mGotAllCodecSpecificData(false), 1803 mReachedEOS(false), 1804 mStartTimestampUs(-1), 1805 mRotation(0), 1806 mDimgRefs("dimg"), 1807 mImageItemId(0), 1808 mIsPrimary(0), 1809 mWidth(0), 1810 mHeight(0), 1811 mTileWidth(0), 1812 mTileHeight(0), 1813 mGridRows(0), 1814 mGridCols(0), 1815 mNumTiles(1), 1816 mTileIndex(0) { 1817 getCodecSpecificDataFromInputFormatIfPossible(); 1818 1819 const char *mime; 1820 mMeta->findCString(kKeyMIMEType, &mime); 1821 mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); 1822 mIsHevc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC); 1823 mIsAudio = !strncasecmp(mime, "audio/", 6); 1824 mIsVideo = !strncasecmp(mime, "video/", 6); 1825 mIsHeic = !strcasecmp(mime, MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC); 1826 mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) || 1827 !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC); 1828 1829 // store temporal layer count 1830 if (mIsVideo) { 1831 int32_t count; 1832 if (mMeta->findInt32(kKeyTemporalLayerCount, &count) && count > 1) { 1833 mOwner->setTemporalLayerCount(count); 1834 } 1835 } 1836 1837 if (!mIsHeic) { 1838 setTimeScale(); 1839 } else { 1840 CHECK(mMeta->findInt32(kKeyWidth, &mWidth) && (mWidth > 0)); 1841 CHECK(mMeta->findInt32(kKeyHeight, &mHeight) && (mHeight > 0)); 1842 1843 int32_t tileWidth, tileHeight, gridRows, gridCols; 1844 if (mMeta->findInt32(kKeyTileWidth, &tileWidth) && (tileWidth > 0) && 1845 mMeta->findInt32(kKeyTileHeight, &tileHeight) && (tileHeight > 0) && 1846 mMeta->findInt32(kKeyGridRows, &gridRows) && (gridRows > 0) && 1847 mMeta->findInt32(kKeyGridCols, &gridCols) && (gridCols > 0)) { 1848 mTileWidth = tileWidth; 1849 mTileHeight = tileHeight; 1850 mGridRows = gridRows; 1851 mGridCols = gridCols; 1852 mNumTiles = gridRows * gridCols; 1853 } 1854 if (!mMeta->findInt32(kKeyTrackIsDefault, &mIsPrimary)) { 1855 mIsPrimary = false; 1856 } 1857 } 1858 } 1859 1860 // Clear all the internal states except the CSD data. 1861 void MPEG4Writer::Track::resetInternal() { 1862 mDone = false; 1863 mPaused = false; 1864 mResumed = false; 1865 mStarted = false; 1866 mGotStartKeyFrame = false; 1867 mIsMalformed = false; 1868 mTrackDurationUs = 0; 1869 mEstimatedTrackSizeBytes = 0; 1870 mSamplesHaveSameSize = 0; 1871 if (mStszTableEntries != NULL) { 1872 delete mStszTableEntries; 1873 mStszTableEntries = new ListTableEntries<uint32_t, 1>(1000); 1874 } 1875 if (mStcoTableEntries != NULL) { 1876 delete mStcoTableEntries; 1877 mStcoTableEntries = new ListTableEntries<uint32_t, 1>(1000); 1878 } 1879 if (mCo64TableEntries != NULL) { 1880 delete mCo64TableEntries; 1881 mCo64TableEntries = new ListTableEntries<off64_t, 1>(1000); 1882 } 1883 if (mStscTableEntries != NULL) { 1884 delete mStscTableEntries; 1885 mStscTableEntries = new ListTableEntries<uint32_t, 3>(1000); 1886 } 1887 if (mStssTableEntries != NULL) { 1888 delete mStssTableEntries; 1889 mStssTableEntries = new ListTableEntries<uint32_t, 1>(1000); 1890 } 1891 if (mSttsTableEntries != NULL) { 1892 delete mSttsTableEntries; 1893 mSttsTableEntries = new ListTableEntries<uint32_t, 2>(1000); 1894 } 1895 if (mCttsTableEntries != NULL) { 1896 delete mCttsTableEntries; 1897 mCttsTableEntries = new ListTableEntries<uint32_t, 2>(1000); 1898 } 1899 if (mElstTableEntries != NULL) { 1900 delete mElstTableEntries; 1901 mElstTableEntries = new ListTableEntries<uint32_t, 3>(3); 1902 } 1903 mReachedEOS = false; 1904 } 1905 1906 void MPEG4Writer::Track::updateTrackSizeEstimate() { 1907 mEstimatedTrackSizeBytes = mMdatSizeBytes; // media data size 1908 1909 if (!isHeic() && !mOwner->isFileStreamable()) { 1910 uint32_t stcoBoxCount = (mOwner->use32BitFileOffset() 1911 ? mStcoTableEntries->count() 1912 : mCo64TableEntries->count()); 1913 int64_t stcoBoxSizeBytes = stcoBoxCount * 4; 1914 int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mStszTableEntries->count() * 4); 1915 1916 // Reserved free space is not large enough to hold 1917 // all meta data and thus wasted. 1918 mEstimatedTrackSizeBytes += mStscTableEntries->count() * 12 + // stsc box size 1919 mStssTableEntries->count() * 4 + // stss box size 1920 mSttsTableEntries->count() * 8 + // stts box size 1921 mCttsTableEntries->count() * 8 + // ctts box size 1922 mElstTableEntries->count() * 12 + // elst box size 1923 stcoBoxSizeBytes + // stco box size 1924 stszBoxSizeBytes; // stsz box size 1925 } 1926 } 1927 1928 void MPEG4Writer::Track::addOneStscTableEntry( 1929 size_t chunkId, size_t sampleId) { 1930 mStscTableEntries->add(htonl(chunkId)); 1931 mStscTableEntries->add(htonl(sampleId)); 1932 mStscTableEntries->add(htonl(1)); 1933 } 1934 1935 void MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) { 1936 mStssTableEntries->add(htonl(sampleId)); 1937 } 1938 1939 void MPEG4Writer::Track::addOneSttsTableEntry( 1940 size_t sampleCount, int32_t duration) { 1941 1942 if (duration == 0) { 1943 ALOGW("0-duration samples found: %zu", sampleCount); 1944 } 1945 mSttsTableEntries->add(htonl(sampleCount)); 1946 mSttsTableEntries->add(htonl(duration)); 1947 } 1948 1949 void MPEG4Writer::Track::addOneCttsTableEntry( 1950 size_t sampleCount, int32_t duration) { 1951 1952 if (!mIsVideo) { 1953 return; 1954 } 1955 mCttsTableEntries->add(htonl(sampleCount)); 1956 mCttsTableEntries->add(htonl(duration)); 1957 } 1958 1959 void MPEG4Writer::Track::addOneElstTableEntry( 1960 uint32_t segmentDuration, int32_t mediaTime, int16_t mediaRate, int16_t mediaRateFraction) { 1961 ALOGV("segmentDuration:%u, mediaTime:%d", segmentDuration, mediaTime); 1962 ALOGV("mediaRate :%" PRId16 ", mediaRateFraction :%" PRId16 ", Ored %u", mediaRate, 1963 mediaRateFraction, ((((uint32_t)mediaRate) << 16) | ((uint32_t)mediaRateFraction))); 1964 mElstTableEntries->add(htonl(segmentDuration)); 1965 mElstTableEntries->add(htonl(mediaTime)); 1966 mElstTableEntries->add(htonl((((uint32_t)mediaRate) << 16) | (uint32_t)mediaRateFraction)); 1967 } 1968 1969 status_t MPEG4Writer::setNextFd(int fd) { 1970 ALOGV("addNextFd"); 1971 Mutex::Autolock l(mLock); 1972 if (mLooper == NULL) { 1973 mReflector = new AHandlerReflector<MPEG4Writer>(this); 1974 mLooper = new ALooper; 1975 mLooper->registerHandler(mReflector); 1976 mLooper->start(); 1977 } 1978 1979 if (mNextFd != -1) { 1980 // No need to set a new FD yet. 1981 return INVALID_OPERATION; 1982 } 1983 mNextFd = dup(fd); 1984 return OK; 1985 } 1986 1987 bool MPEG4Writer::Track::isExifData( 1988 MediaBufferBase *buffer, uint32_t *tiffHdrOffset) const { 1989 if (!mIsHeic) { 1990 return false; 1991 } 1992 1993 // Exif block starting with 'Exif\0\0' 1994 size_t length = buffer->range_length(); 1995 uint8_t *data = (uint8_t *)buffer->data() + buffer->range_offset(); 1996 if ((length > sizeof(kExifHeader)) 1997 && !memcmp(data, kExifHeader, sizeof(kExifHeader))) { 1998 *tiffHdrOffset = sizeof(kExifHeader); 1999 return true; 2000 } 2001 2002 // Exif block starting with fourcc 'Exif' followed by APP1 marker 2003 if ((length > sizeof(kExifApp1Marker) + 2 + sizeof(kExifHeader)) 2004 && !memcmp(data, kExifApp1Marker, sizeof(kExifApp1Marker)) 2005 && !memcmp(data + sizeof(kExifApp1Marker) + 2, kExifHeader, sizeof(kExifHeader))) { 2006 // skip 'Exif' fourcc 2007 buffer->set_range(4, buffer->range_length() - 4); 2008 2009 // 2-byte APP1 + 2-byte size followed by kExifHeader 2010 *tiffHdrOffset = 2 + 2 + sizeof(kExifHeader); 2011 return true; 2012 } 2013 2014 return false; 2015 } 2016 2017 void MPEG4Writer::Track::addChunkOffset(off64_t offset) { 2018 CHECK(!mIsHeic); 2019 if (mOwner->use32BitFileOffset()) { 2020 uint32_t value = offset; 2021 mStcoTableEntries->add(htonl(value)); 2022 } else { 2023 mCo64TableEntries->add(hton64(offset)); 2024 } 2025 } 2026 2027 void MPEG4Writer::Track::addItemOffsetAndSize(off64_t offset, size_t size, bool isExif) { 2028 CHECK(mIsHeic); 2029 2030 if (offset > UINT32_MAX || size > UINT32_MAX) { 2031 ALOGE("offset or size is out of range: %lld, %lld", 2032 (long long) offset, (long long) size); 2033 mIsMalformed = true; 2034 } 2035 if (mIsMalformed) { 2036 return; 2037 } 2038 2039 if (isExif) { 2040 mExifList.push_back(mOwner->addItem_l({ 2041 .itemType = "Exif", 2042 .isPrimary = false, 2043 .isHidden = false, 2044 .offset = (uint32_t)offset, 2045 .size = (uint32_t)size, 2046 })); 2047 return; 2048 } 2049 2050 if (mTileIndex >= mNumTiles) { 2051 ALOGW("Ignoring excess tiles!"); 2052 return; 2053 } 2054 2055 // Rotation angle in HEIF is CCW, framework angle is CW. 2056 int32_t heifRotation = 0; 2057 switch(mRotation) { 2058 case 90: heifRotation = 3; break; 2059 case 180: heifRotation = 2; break; 2060 case 270: heifRotation = 1; break; 2061 default: break; // don't set if invalid 2062 } 2063 2064 bool hasGrid = (mTileWidth > 0); 2065 2066 if (mProperties.empty()) { 2067 mProperties.push_back(mOwner->addProperty_l({ 2068 .type = FOURCC('h', 'v', 'c', 'C'), 2069 .hvcc = ABuffer::CreateAsCopy(mCodecSpecificData, mCodecSpecificDataSize) 2070 })); 2071 2072 mProperties.push_back(mOwner->addProperty_l({ 2073 .type = FOURCC('i', 's', 'p', 'e'), 2074 .width = hasGrid ? mTileWidth : mWidth, 2075 .height = hasGrid ? mTileHeight : mHeight, 2076 })); 2077 2078 if (!hasGrid && heifRotation > 0) { 2079 mProperties.push_back(mOwner->addProperty_l({ 2080 .type = FOURCC('i', 'r', 'o', 't'), 2081 .rotation = heifRotation, 2082 })); 2083 } 2084 } 2085 2086 mTileIndex++; 2087 if (hasGrid) { 2088 mDimgRefs.value.push_back(mOwner->addItem_l({ 2089 .itemType = "hvc1", 2090 .isPrimary = false, 2091 .isHidden = true, 2092 .offset = (uint32_t)offset, 2093 .size = (uint32_t)size, 2094 .properties = mProperties, 2095 })); 2096 2097 if (mTileIndex == mNumTiles) { 2098 mProperties.clear(); 2099 mProperties.push_back(mOwner->addProperty_l({ 2100 .type = FOURCC('i', 's', 'p', 'e'), 2101 .width = mWidth, 2102 .height = mHeight, 2103 })); 2104 if (heifRotation > 0) { 2105 mProperties.push_back(mOwner->addProperty_l({ 2106 .type = FOURCC('i', 'r', 'o', 't'), 2107 .rotation = heifRotation, 2108 })); 2109 } 2110 mImageItemId = mOwner->addItem_l({ 2111 .itemType = "grid", 2112 .isPrimary = (mIsPrimary != 0), 2113 .isHidden = false, 2114 .rows = (uint32_t)mGridRows, 2115 .cols = (uint32_t)mGridCols, 2116 .width = (uint32_t)mWidth, 2117 .height = (uint32_t)mHeight, 2118 .properties = mProperties, 2119 }); 2120 } 2121 } else { 2122 mImageItemId = mOwner->addItem_l({ 2123 .itemType = "hvc1", 2124 .isPrimary = (mIsPrimary != 0), 2125 .isHidden = false, 2126 .offset = (uint32_t)offset, 2127 .size = (uint32_t)size, 2128 .properties = mProperties, 2129 }); 2130 } 2131 } 2132 2133 // Flush out the item refs for this track. Note that it must be called after the 2134 // writer thread has stopped, because there might be pending items in the last 2135 // few chunks written by the writer thread (as opposed to the track). In particular, 2136 // it affects the 'dimg' refs for tiled image, as we only have the refs after the 2137 // last tile sample is written. 2138 void MPEG4Writer::Track::flushItemRefs() { 2139 CHECK(mIsHeic); 2140 2141 if (mImageItemId > 0) { 2142 mOwner->addRefs_l(mImageItemId, mDimgRefs); 2143 2144 if (!mExifList.empty()) { 2145 // The "cdsc" ref is from the metadata/exif item to the image item. 2146 // So the refs all contain the image item. 2147 ItemRefs cdscRefs("cdsc"); 2148 cdscRefs.value.push_back(mImageItemId); 2149 for (uint16_t exifItem : mExifList) { 2150 mOwner->addRefs_l(exifItem, cdscRefs); 2151 } 2152 } 2153 } 2154 } 2155 2156 void MPEG4Writer::Track::setTimeScale() { 2157 ALOGV("setTimeScale"); 2158 // Default time scale 2159 mTimeScale = 90000; 2160 2161 if (mIsAudio) { 2162 // Use the sampling rate as the default time scale for audio track. 2163 int32_t sampleRate; 2164 bool success = mMeta->findInt32(kKeySampleRate, &sampleRate); 2165 CHECK(success); 2166 mTimeScale = sampleRate; 2167 } 2168 2169 // If someone would like to overwrite the timescale, use user-supplied value. 2170 int32_t timeScale; 2171 if (mMeta->findInt32(kKeyTimeScale, &timeScale)) { 2172 mTimeScale = timeScale; 2173 } 2174 2175 CHECK_GT(mTimeScale, 0); 2176 } 2177 2178 void MPEG4Writer::onMessageReceived(const sp<AMessage> &msg) { 2179 switch (msg->what()) { 2180 case kWhatSwitch: 2181 { 2182 mLock.lock(); 2183 int fd = mNextFd; 2184 mNextFd = -1; 2185 mLock.unlock(); 2186 finishCurrentSession(); 2187 initInternal(fd, false /*isFirstSession*/); 2188 start(mStartMeta.get()); 2189 mSwitchPending = false; 2190 notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_NEXT_OUTPUT_FILE_STARTED, 0); 2191 break; 2192 } 2193 default: 2194 TRESPASS(); 2195 } 2196 } 2197 2198 void MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() { 2199 const char *mime; 2200 2201 CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 2202 2203 uint32_t type; 2204 const void *data = NULL; 2205 size_t size = 0; 2206 if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 2207 mMeta->findData(kKeyAVCC, &type, &data, &size); 2208 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC) || 2209 !strcasecmp(mime, MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC)) { 2210 mMeta->findData(kKeyHVCC, &type, &data, &size); 2211 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) 2212 || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 2213 if (mMeta->findData(kKeyESDS, &type, &data, &size)) { 2214 ESDS esds(data, size); 2215 if (esds.getCodecSpecificInfo(&data, &size) == OK && 2216 data != NULL && 2217 copyCodecSpecificData((uint8_t*)data, size) == OK) { 2218 mGotAllCodecSpecificData = true; 2219 } 2220 return; 2221 } 2222 } 2223 if (data != NULL && copyCodecSpecificData((uint8_t *)data, size) == OK) { 2224 mGotAllCodecSpecificData = true; 2225 } 2226 } 2227 2228 MPEG4Writer::Track::~Track() { 2229 stop(); 2230 2231 delete mStszTableEntries; 2232 delete mStcoTableEntries; 2233 delete mCo64TableEntries; 2234 delete mStscTableEntries; 2235 delete mSttsTableEntries; 2236 delete mStssTableEntries; 2237 delete mCttsTableEntries; 2238 delete mElstTableEntries; 2239 2240 mStszTableEntries = NULL; 2241 mStcoTableEntries = NULL; 2242 mCo64TableEntries = NULL; 2243 mStscTableEntries = NULL; 2244 mSttsTableEntries = NULL; 2245 mStssTableEntries = NULL; 2246 mCttsTableEntries = NULL; 2247 mElstTableEntries = NULL; 2248 2249 if (mCodecSpecificData != NULL) { 2250 free(mCodecSpecificData); 2251 mCodecSpecificData = NULL; 2252 } 2253 } 2254 2255 void MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) { 2256 ALOGV("initTrackingProgressStatus"); 2257 mPreviousTrackTimeUs = -1; 2258 mTrackingProgressStatus = false; 2259 mTrackEveryTimeDurationUs = 0; 2260 { 2261 int64_t timeUs; 2262 if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) { 2263 ALOGV("Receive request to track progress status for every %" PRId64 " us", timeUs); 2264 mTrackEveryTimeDurationUs = timeUs; 2265 mTrackingProgressStatus = true; 2266 } 2267 } 2268 } 2269 2270 // static 2271 void *MPEG4Writer::ThreadWrapper(void *me) { 2272 ALOGV("ThreadWrapper: %p", me); 2273 MPEG4Writer *writer = static_cast<MPEG4Writer *>(me); 2274 writer->threadFunc(); 2275 return NULL; 2276 } 2277 2278 void MPEG4Writer::bufferChunk(const Chunk& chunk) { 2279 ALOGV("bufferChunk: %p", chunk.mTrack); 2280 Mutex::Autolock autolock(mLock); 2281 CHECK_EQ(mDone, false); 2282 2283 for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 2284 it != mChunkInfos.end(); ++it) { 2285 2286 if (chunk.mTrack == it->mTrack) { // Found owner 2287 it->mChunks.push_back(chunk); 2288 mChunkReadyCondition.signal(); 2289 return; 2290 } 2291 } 2292 2293 CHECK(!"Received a chunk for a unknown track"); 2294 } 2295 2296 void MPEG4Writer::writeChunkToFile(Chunk* chunk) { 2297 ALOGV("writeChunkToFile: %" PRId64 " from %s track", 2298 chunk->mTimeStampUs, chunk->mTrack->getTrackType()); 2299 2300 int32_t isFirstSample = true; 2301 while (!chunk->mSamples.empty()) { 2302 List<MediaBuffer *>::iterator it = chunk->mSamples.begin(); 2303 2304 uint32_t tiffHdrOffset; 2305 if (!(*it)->meta_data().findInt32( 2306 kKeyExifTiffOffset, (int32_t*)&tiffHdrOffset)) { 2307 tiffHdrOffset = 0; 2308 } 2309 bool isExif = (tiffHdrOffset > 0); 2310 bool usePrefix = chunk->mTrack->usePrefix() && !isExif; 2311 2312 size_t bytesWritten; 2313 off64_t offset = addSample_l(*it, usePrefix, tiffHdrOffset, &bytesWritten); 2314 2315 if (chunk->mTrack->isHeic()) { 2316 chunk->mTrack->addItemOffsetAndSize(offset, bytesWritten, isExif); 2317 } else if (isFirstSample) { 2318 chunk->mTrack->addChunkOffset(offset); 2319 isFirstSample = false; 2320 } 2321 2322 (*it)->release(); 2323 (*it) = NULL; 2324 chunk->mSamples.erase(it); 2325 } 2326 chunk->mSamples.clear(); 2327 } 2328 2329 void MPEG4Writer::writeAllChunks() { 2330 ALOGV("writeAllChunks"); 2331 size_t outstandingChunks = 0; 2332 Chunk chunk; 2333 while (findChunkToWrite(&chunk)) { 2334 writeChunkToFile(&chunk); 2335 ++outstandingChunks; 2336 } 2337 2338 sendSessionSummary(); 2339 2340 mChunkInfos.clear(); 2341 ALOGD("%zu chunks are written in the last batch", outstandingChunks); 2342 } 2343 2344 bool MPEG4Writer::findChunkToWrite(Chunk *chunk) { 2345 ALOGV("findChunkToWrite"); 2346 2347 int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL; 2348 Track *track = NULL; 2349 for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 2350 it != mChunkInfos.end(); ++it) { 2351 if (!it->mChunks.empty()) { 2352 List<Chunk>::iterator chunkIt = it->mChunks.begin(); 2353 if (chunkIt->mTimeStampUs < minTimestampUs) { 2354 minTimestampUs = chunkIt->mTimeStampUs; 2355 track = it->mTrack; 2356 } 2357 } 2358 } 2359 2360 if (track == NULL) { 2361 ALOGV("Nothing to be written after all"); 2362 return false; 2363 } 2364 2365 if (mIsFirstChunk) { 2366 mIsFirstChunk = false; 2367 } 2368 2369 for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 2370 it != mChunkInfos.end(); ++it) { 2371 if (it->mTrack == track) { 2372 *chunk = *(it->mChunks.begin()); 2373 it->mChunks.erase(it->mChunks.begin()); 2374 CHECK_EQ(chunk->mTrack, track); 2375 2376 int64_t interChunkTimeUs = 2377 chunk->mTimeStampUs - it->mPrevChunkTimestampUs; 2378 if (interChunkTimeUs > it->mPrevChunkTimestampUs) { 2379 it->mMaxInterChunkDurUs = interChunkTimeUs; 2380 } 2381 2382 return true; 2383 } 2384 } 2385 2386 return false; 2387 } 2388 2389 void MPEG4Writer::threadFunc() { 2390 ALOGV("threadFunc"); 2391 2392 prctl(PR_SET_NAME, (unsigned long)"MPEG4Writer", 0, 0, 0); 2393 2394 Mutex::Autolock autoLock(mLock); 2395 while (!mDone) { 2396 Chunk chunk; 2397 bool chunkFound = false; 2398 2399 while (!mDone && !(chunkFound = findChunkToWrite(&chunk))) { 2400 mChunkReadyCondition.wait(mLock); 2401 } 2402 2403 // In real time recording mode, write without holding the lock in order 2404 // to reduce the blocking time for media track threads. 2405 // Otherwise, hold the lock until the existing chunks get written to the 2406 // file. 2407 if (chunkFound) { 2408 if (mIsRealTimeRecording) { 2409 mLock.unlock(); 2410 } 2411 writeChunkToFile(&chunk); 2412 if (mIsRealTimeRecording) { 2413 mLock.lock(); 2414 } 2415 } 2416 } 2417 2418 writeAllChunks(); 2419 } 2420 2421 status_t MPEG4Writer::startWriterThread() { 2422 ALOGV("startWriterThread"); 2423 2424 mDone = false; 2425 mIsFirstChunk = true; 2426 mDriftTimeUs = 0; 2427 for (List<Track *>::iterator it = mTracks.begin(); 2428 it != mTracks.end(); ++it) { 2429 ChunkInfo info; 2430 info.mTrack = *it; 2431 info.mPrevChunkTimestampUs = 0; 2432 info.mMaxInterChunkDurUs = 0; 2433 mChunkInfos.push_back(info); 2434 } 2435 2436 pthread_attr_t attr; 2437 pthread_attr_init(&attr); 2438 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 2439 pthread_create(&mThread, &attr, ThreadWrapper, this); 2440 pthread_attr_destroy(&attr); 2441 mWriterThreadStarted = true; 2442 return OK; 2443 } 2444 2445 2446 status_t MPEG4Writer::Track::start(MetaData *params) { 2447 if (!mDone && mPaused) { 2448 mPaused = false; 2449 mResumed = true; 2450 return OK; 2451 } 2452 2453 int64_t startTimeUs; 2454 if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) { 2455 startTimeUs = 0; 2456 } 2457 mStartTimeRealUs = startTimeUs; 2458 2459 int32_t rotationDegrees; 2460 if ((mIsVideo || mIsHeic) && params && 2461 params->findInt32(kKeyRotation, &rotationDegrees)) { 2462 mRotation = rotationDegrees; 2463 } 2464 2465 initTrackingProgressStatus(params); 2466 2467 sp<MetaData> meta = new MetaData; 2468 if (mOwner->isRealTimeRecording() && mOwner->numTracks() > 1) { 2469 /* 2470 * This extra delay of accepting incoming audio/video signals 2471 * helps to align a/v start time at the beginning of a recording 2472 * session, and it also helps eliminate the "recording" sound for 2473 * camcorder applications. 2474 * 2475 * If client does not set the start time offset, we fall back to 2476 * use the default initial delay value. 2477 */ 2478 int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL; 2479 if (startTimeOffsetUs < 0) { // Start time offset was not set 2480 startTimeOffsetUs = kInitialDelayTimeUs; 2481 } 2482 startTimeUs += startTimeOffsetUs; 2483 ALOGI("Start time offset: %" PRId64 " us", startTimeOffsetUs); 2484 } 2485 2486 meta->setInt64(kKeyTime, startTimeUs); 2487 2488 status_t err = mSource->start(meta.get()); 2489 if (err != OK) { 2490 mDone = mReachedEOS = true; 2491 return err; 2492 } 2493 2494 pthread_attr_t attr; 2495 pthread_attr_init(&attr); 2496 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 2497 2498 mDone = false; 2499 mStarted = true; 2500 mTrackDurationUs = 0; 2501 mReachedEOS = false; 2502 mEstimatedTrackSizeBytes = 0; 2503 mMdatSizeBytes = 0; 2504 mMaxChunkDurationUs = 0; 2505 mLastDecodingTimeUs = -1; 2506 2507 pthread_create(&mThread, &attr, ThreadWrapper, this); 2508 pthread_attr_destroy(&attr); 2509 2510 return OK; 2511 } 2512 2513 status_t MPEG4Writer::Track::pause() { 2514 mPaused = true; 2515 return OK; 2516 } 2517 2518 status_t MPEG4Writer::Track::stop(bool stopSource) { 2519 ALOGD("%s track stopping. %s source", getTrackType(), stopSource ? "Stop" : "Not Stop"); 2520 if (!mStarted) { 2521 ALOGE("Stop() called but track is not started"); 2522 return ERROR_END_OF_STREAM; 2523 } 2524 2525 if (mDone) { 2526 return OK; 2527 } 2528 2529 if (stopSource) { 2530 ALOGD("%s track source stopping", getTrackType()); 2531 mSource->stop(); 2532 ALOGD("%s track source stopped", getTrackType()); 2533 } 2534 2535 // Set mDone to be true after sucessfully stop mSource as mSource may be still outputting 2536 // buffers to the writer. 2537 mDone = true; 2538 2539 void *dummy; 2540 pthread_join(mThread, &dummy); 2541 status_t err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy)); 2542 2543 ALOGD("%s track stopped. %s source", getTrackType(), stopSource ? "Stop" : "Not Stop"); 2544 return err; 2545 } 2546 2547 bool MPEG4Writer::Track::reachedEOS() { 2548 return mReachedEOS; 2549 } 2550 2551 // static 2552 void *MPEG4Writer::Track::ThreadWrapper(void *me) { 2553 Track *track = static_cast<Track *>(me); 2554 2555 status_t err = track->threadEntry(); 2556 return (void *)(uintptr_t)err; 2557 } 2558 2559 static void getNalUnitType(uint8_t byte, uint8_t* type) { 2560 ALOGV("getNalUnitType: %d", byte); 2561 2562 // nal_unit_type: 5-bit unsigned integer 2563 *type = (byte & 0x1F); 2564 } 2565 2566 const uint8_t *MPEG4Writer::Track::parseParamSet( 2567 const uint8_t *data, size_t length, int type, size_t *paramSetLen) { 2568 2569 ALOGV("parseParamSet"); 2570 CHECK(type == kNalUnitTypeSeqParamSet || 2571 type == kNalUnitTypePicParamSet); 2572 2573 const uint8_t *nextStartCode = findNextNalStartCode(data, length); 2574 *paramSetLen = nextStartCode - data; 2575 if (*paramSetLen == 0) { 2576 ALOGE("Param set is malformed, since its length is 0"); 2577 return NULL; 2578 } 2579 2580 AVCParamSet paramSet(*paramSetLen, data); 2581 if (type == kNalUnitTypeSeqParamSet) { 2582 if (*paramSetLen < 4) { 2583 ALOGE("Seq parameter set malformed"); 2584 return NULL; 2585 } 2586 if (mSeqParamSets.empty()) { 2587 mProfileIdc = data[1]; 2588 mProfileCompatible = data[2]; 2589 mLevelIdc = data[3]; 2590 } else { 2591 if (mProfileIdc != data[1] || 2592 mProfileCompatible != data[2] || 2593 mLevelIdc != data[3]) { 2594 // COULD DO: set profile/level to the lowest required to support all SPSs 2595 ALOGE("Inconsistent profile/level found in seq parameter sets"); 2596 return NULL; 2597 } 2598 } 2599 mSeqParamSets.push_back(paramSet); 2600 } else { 2601 mPicParamSets.push_back(paramSet); 2602 } 2603 return nextStartCode; 2604 } 2605 2606 status_t MPEG4Writer::Track::copyAVCCodecSpecificData( 2607 const uint8_t *data, size_t size) { 2608 ALOGV("copyAVCCodecSpecificData"); 2609 2610 // 2 bytes for each of the parameter set length field 2611 // plus the 7 bytes for the header 2612 return copyCodecSpecificData(data, size, 4 + 7); 2613 } 2614 2615 status_t MPEG4Writer::Track::copyHEVCCodecSpecificData( 2616 const uint8_t *data, size_t size) { 2617 ALOGV("copyHEVCCodecSpecificData"); 2618 2619 // Min length of HEVC CSD is 23. (ISO/IEC 14496-15:2014 Chapter 8.3.3.1.2) 2620 return copyCodecSpecificData(data, size, 23); 2621 } 2622 2623 status_t MPEG4Writer::Track::copyCodecSpecificData( 2624 const uint8_t *data, size_t size, size_t minLength) { 2625 if (size < minLength) { 2626 ALOGE("Codec specific data length too short: %zu", size); 2627 return ERROR_MALFORMED; 2628 } 2629 2630 mCodecSpecificData = malloc(size); 2631 if (mCodecSpecificData == NULL) { 2632 ALOGE("Failed allocating codec specific data"); 2633 return NO_MEMORY; 2634 } 2635 mCodecSpecificDataSize = size; 2636 memcpy(mCodecSpecificData, data, size); 2637 return OK; 2638 } 2639 2640 status_t MPEG4Writer::Track::parseAVCCodecSpecificData( 2641 const uint8_t *data, size_t size) { 2642 2643 ALOGV("parseAVCCodecSpecificData"); 2644 // Data starts with a start code. 2645 // SPS and PPS are separated with start codes. 2646 // Also, SPS must come before PPS 2647 uint8_t type = kNalUnitTypeSeqParamSet; 2648 bool gotSps = false; 2649 bool gotPps = false; 2650 const uint8_t *tmp = data; 2651 const uint8_t *nextStartCode = data; 2652 size_t bytesLeft = size; 2653 size_t paramSetLen = 0; 2654 mCodecSpecificDataSize = 0; 2655 while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) { 2656 getNalUnitType(*(tmp + 4), &type); 2657 if (type == kNalUnitTypeSeqParamSet) { 2658 if (gotPps) { 2659 ALOGE("SPS must come before PPS"); 2660 return ERROR_MALFORMED; 2661 } 2662 if (!gotSps) { 2663 gotSps = true; 2664 } 2665 nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 2666 } else if (type == kNalUnitTypePicParamSet) { 2667 if (!gotSps) { 2668 ALOGE("SPS must come before PPS"); 2669 return ERROR_MALFORMED; 2670 } 2671 if (!gotPps) { 2672 gotPps = true; 2673 } 2674 nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 2675 } else { 2676 ALOGE("Only SPS and PPS Nal units are expected"); 2677 return ERROR_MALFORMED; 2678 } 2679 2680 if (nextStartCode == NULL) { 2681 return ERROR_MALFORMED; 2682 } 2683 2684 // Move on to find the next parameter set 2685 bytesLeft -= nextStartCode - tmp; 2686 tmp = nextStartCode; 2687 mCodecSpecificDataSize += (2 + paramSetLen); 2688 } 2689 2690 { 2691 // Check on the number of seq parameter sets 2692 size_t nSeqParamSets = mSeqParamSets.size(); 2693 if (nSeqParamSets == 0) { 2694 ALOGE("Cound not find sequence parameter set"); 2695 return ERROR_MALFORMED; 2696 } 2697 2698 if (nSeqParamSets > 0x1F) { 2699 ALOGE("Too many seq parameter sets (%zu) found", nSeqParamSets); 2700 return ERROR_MALFORMED; 2701 } 2702 } 2703 2704 { 2705 // Check on the number of pic parameter sets 2706 size_t nPicParamSets = mPicParamSets.size(); 2707 if (nPicParamSets == 0) { 2708 ALOGE("Cound not find picture parameter set"); 2709 return ERROR_MALFORMED; 2710 } 2711 if (nPicParamSets > 0xFF) { 2712 ALOGE("Too many pic parameter sets (%zd) found", nPicParamSets); 2713 return ERROR_MALFORMED; 2714 } 2715 } 2716 // FIXME: 2717 // Add chromat_format_idc, bit depth values, etc for AVC/h264 high profile and above 2718 // and remove #if 0 2719 #if 0 2720 { 2721 // Check on the profiles 2722 // These profiles requires additional parameter set extensions 2723 if (mProfileIdc == 100 || mProfileIdc == 110 || 2724 mProfileIdc == 122 || mProfileIdc == 144) { 2725 ALOGE("Sorry, no support for profile_idc: %d!", mProfileIdc); 2726 return BAD_VALUE; 2727 } 2728 } 2729 #endif 2730 return OK; 2731 } 2732 2733 status_t MPEG4Writer::Track::makeAVCCodecSpecificData( 2734 const uint8_t *data, size_t size) { 2735 2736 if (mCodecSpecificData != NULL) { 2737 ALOGE("Already have codec specific data"); 2738 return ERROR_MALFORMED; 2739 } 2740 2741 if (size < 4) { 2742 ALOGE("Codec specific data length too short: %zu", size); 2743 return ERROR_MALFORMED; 2744 } 2745 2746 // Data is in the form of AVCCodecSpecificData 2747 if (memcmp("\x00\x00\x00\x01", data, 4)) { 2748 return copyAVCCodecSpecificData(data, size); 2749 } 2750 2751 if (parseAVCCodecSpecificData(data, size) != OK) { 2752 return ERROR_MALFORMED; 2753 } 2754 2755 // ISO 14496-15: AVC file format 2756 mCodecSpecificDataSize += 7; // 7 more bytes in the header 2757 mCodecSpecificData = malloc(mCodecSpecificDataSize); 2758 if (mCodecSpecificData == NULL) { 2759 mCodecSpecificDataSize = 0; 2760 ALOGE("Failed allocating codec specific data"); 2761 return NO_MEMORY; 2762 } 2763 uint8_t *header = (uint8_t *)mCodecSpecificData; 2764 header[0] = 1; // version 2765 header[1] = mProfileIdc; // profile indication 2766 header[2] = mProfileCompatible; // profile compatibility 2767 header[3] = mLevelIdc; 2768 2769 // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne 2770 if (mOwner->useNalLengthFour()) { 2771 header[4] = 0xfc | 3; // length size == 4 bytes 2772 } else { 2773 header[4] = 0xfc | 1; // length size == 2 bytes 2774 } 2775 2776 // 3-bit '111' followed by 5-bit numSequenceParameterSets 2777 int nSequenceParamSets = mSeqParamSets.size(); 2778 header[5] = 0xe0 | nSequenceParamSets; 2779 header += 6; 2780 for (List<AVCParamSet>::iterator it = mSeqParamSets.begin(); 2781 it != mSeqParamSets.end(); ++it) { 2782 // 16-bit sequence parameter set length 2783 uint16_t seqParamSetLength = it->mLength; 2784 header[0] = seqParamSetLength >> 8; 2785 header[1] = seqParamSetLength & 0xff; 2786 2787 // SPS NAL unit (sequence parameter length bytes) 2788 memcpy(&header[2], it->mData, seqParamSetLength); 2789 header += (2 + seqParamSetLength); 2790 } 2791 2792 // 8-bit nPictureParameterSets 2793 int nPictureParamSets = mPicParamSets.size(); 2794 header[0] = nPictureParamSets; 2795 header += 1; 2796 for (List<AVCParamSet>::iterator it = mPicParamSets.begin(); 2797 it != mPicParamSets.end(); ++it) { 2798 // 16-bit picture parameter set length 2799 uint16_t picParamSetLength = it->mLength; 2800 header[0] = picParamSetLength >> 8; 2801 header[1] = picParamSetLength & 0xff; 2802 2803 // PPS Nal unit (picture parameter set length bytes) 2804 memcpy(&header[2], it->mData, picParamSetLength); 2805 header += (2 + picParamSetLength); 2806 } 2807 2808 return OK; 2809 } 2810 2811 2812 status_t MPEG4Writer::Track::parseHEVCCodecSpecificData( 2813 const uint8_t *data, size_t size, HevcParameterSets ¶mSets) { 2814 2815 ALOGV("parseHEVCCodecSpecificData"); 2816 const uint8_t *tmp = data; 2817 const uint8_t *nextStartCode = data; 2818 size_t bytesLeft = size; 2819 while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) { 2820 nextStartCode = findNextNalStartCode(tmp + 4, bytesLeft - 4); 2821 status_t err = paramSets.addNalUnit(tmp + 4, (nextStartCode - tmp) - 4); 2822 if (err != OK) { 2823 return ERROR_MALFORMED; 2824 } 2825 2826 // Move on to find the next parameter set 2827 bytesLeft -= nextStartCode - tmp; 2828 tmp = nextStartCode; 2829 } 2830 2831 size_t csdSize = 23; 2832 const size_t numNalUnits = paramSets.getNumNalUnits(); 2833 for (size_t i = 0; i < ARRAY_SIZE(kMandatoryHevcNalUnitTypes); ++i) { 2834 int type = kMandatoryHevcNalUnitTypes[i]; 2835 size_t numParamSets = paramSets.getNumNalUnitsOfType(type); 2836 if (numParamSets == 0) { 2837 ALOGE("Cound not find NAL unit of type %d", type); 2838 return ERROR_MALFORMED; 2839 } 2840 } 2841 for (size_t i = 0; i < ARRAY_SIZE(kHevcNalUnitTypes); ++i) { 2842 int type = kHevcNalUnitTypes[i]; 2843 size_t numParamSets = paramSets.getNumNalUnitsOfType(type); 2844 if (numParamSets > 0xffff) { 2845 ALOGE("Too many seq parameter sets (%zu) found", numParamSets); 2846 return ERROR_MALFORMED; 2847 } 2848 csdSize += 3; 2849 for (size_t j = 0; j < numNalUnits; ++j) { 2850 if (paramSets.getType(j) != type) { 2851 continue; 2852 } 2853 csdSize += 2 + paramSets.getSize(j); 2854 } 2855 } 2856 mCodecSpecificDataSize = csdSize; 2857 return OK; 2858 } 2859 2860 status_t MPEG4Writer::Track::makeHEVCCodecSpecificData( 2861 const uint8_t *data, size_t size) { 2862 2863 if (mCodecSpecificData != NULL) { 2864 ALOGE("Already have codec specific data"); 2865 return ERROR_MALFORMED; 2866 } 2867 2868 if (size < 4) { 2869 ALOGE("Codec specific data length too short: %zu", size); 2870 return ERROR_MALFORMED; 2871 } 2872 2873 // Data is in the form of HEVCCodecSpecificData 2874 if (memcmp("\x00\x00\x00\x01", data, 4)) { 2875 return copyHEVCCodecSpecificData(data, size); 2876 } 2877 2878 HevcParameterSets paramSets; 2879 if (parseHEVCCodecSpecificData(data, size, paramSets) != OK) { 2880 ALOGE("failed parsing codec specific data"); 2881 return ERROR_MALFORMED; 2882 } 2883 2884 mCodecSpecificData = malloc(mCodecSpecificDataSize); 2885 if (mCodecSpecificData == NULL) { 2886 mCodecSpecificDataSize = 0; 2887 ALOGE("Failed allocating codec specific data"); 2888 return NO_MEMORY; 2889 } 2890 status_t err = paramSets.makeHvcc((uint8_t *)mCodecSpecificData, 2891 &mCodecSpecificDataSize, mOwner->useNalLengthFour() ? 4 : 2); 2892 if (err != OK) { 2893 ALOGE("failed constructing HVCC atom"); 2894 return err; 2895 } 2896 2897 return OK; 2898 } 2899 2900 /* 2901 * Updates the drift time from the audio track so that 2902 * the video track can get the updated drift time information 2903 * from the file writer. The fluctuation of the drift time of the audio 2904 * encoding path is smoothed out with a simple filter by giving a larger 2905 * weight to more recently drift time. The filter coefficients, 0.5 and 0.5, 2906 * are heuristically determined. 2907 */ 2908 void MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) { 2909 int64_t driftTimeUs = 0; 2910 if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) { 2911 int64_t prevDriftTimeUs = mOwner->getDriftTimeUs(); 2912 int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1; 2913 mOwner->setDriftTimeUs(timeUs); 2914 } 2915 } 2916 2917 void MPEG4Writer::Track::dumpTimeStamps() { 2918 if (!mTimestampDebugHelper.empty()) { 2919 std::string timeStampString = "Dumping " + std::string(getTrackType()) + " track's last " + 2920 std::to_string(mTimestampDebugHelper.size()) + 2921 " frames' timestamps(pts, dts) and frame type : "; 2922 for (const TimestampDebugHelperEntry& entry : mTimestampDebugHelper) { 2923 timeStampString += "\n(" + std::to_string(entry.pts) + "us, " + 2924 std::to_string(entry.dts) + "us " + entry.frameType + ") "; 2925 } 2926 ALOGE("%s", timeStampString.c_str()); 2927 } else { 2928 ALOGE("0 frames to dump timeStamps in %s track ", getTrackType()); 2929 } 2930 } 2931 2932 status_t MPEG4Writer::Track::threadEntry() { 2933 int32_t count = 0; 2934 const int64_t interleaveDurationUs = mOwner->interleaveDuration(); 2935 const bool hasMultipleTracks = (mOwner->numTracks() > 1); 2936 int64_t chunkTimestampUs = 0; 2937 int32_t nChunks = 0; 2938 int32_t nActualFrames = 0; // frames containing non-CSD data (non-0 length) 2939 int32_t nZeroLengthFrames = 0; 2940 int64_t lastTimestampUs = 0; // Previous sample time stamp 2941 int64_t lastDurationUs = 0; // Between the previous two samples 2942 int64_t currDurationTicks = 0; // Timescale based ticks 2943 int64_t lastDurationTicks = 0; // Timescale based ticks 2944 int32_t sampleCount = 1; // Sample count in the current stts table entry 2945 uint32_t previousSampleSize = 0; // Size of the previous sample 2946 int64_t previousPausedDurationUs = 0; 2947 int64_t timestampUs = 0; 2948 int64_t cttsOffsetTimeUs = 0; 2949 int64_t currCttsOffsetTimeTicks = 0; // Timescale based ticks 2950 int64_t lastCttsOffsetTimeTicks = -1; // Timescale based ticks 2951 int32_t cttsSampleCount = 0; // Sample count in the current ctts table entry 2952 uint32_t lastSamplesPerChunk = 0; 2953 2954 if (mIsAudio) { 2955 prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0); 2956 } else if (mIsVideo) { 2957 prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0); 2958 } else { 2959 prctl(PR_SET_NAME, (unsigned long)"MetadataTrackEncoding", 0, 0, 0); 2960 } 2961 2962 if (mOwner->isRealTimeRecording()) { 2963 androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO); 2964 } 2965 2966 sp<MetaData> meta_data; 2967 2968 status_t err = OK; 2969 MediaBufferBase *buffer; 2970 const char *trackName = getTrackType(); 2971 while (!mDone && (err = mSource->read(&buffer)) == OK) { 2972 if (buffer->range_length() == 0) { 2973 buffer->release(); 2974 buffer = NULL; 2975 ++nZeroLengthFrames; 2976 continue; 2977 } 2978 2979 // If the codec specific data has not been received yet, delay pause. 2980 // After the codec specific data is received, discard what we received 2981 // when the track is to be paused. 2982 if (mPaused && !mResumed) { 2983 buffer->release(); 2984 buffer = NULL; 2985 continue; 2986 } 2987 2988 ++count; 2989 2990 int32_t isCodecConfig; 2991 if (buffer->meta_data().findInt32(kKeyIsCodecConfig, &isCodecConfig) 2992 && isCodecConfig) { 2993 // if config format (at track addition) already had CSD, keep that 2994 // UNLESS we have not received any frames yet. 2995 // TODO: for now the entire CSD has to come in one frame for encoders, even though 2996 // they need to be spread out for decoders. 2997 if (mGotAllCodecSpecificData && nActualFrames > 0) { 2998 ALOGI("ignoring additional CSD for video track after first frame"); 2999 } else { 3000 mMeta = mSource->getFormat(); // get output format after format change 3001 status_t err; 3002 if (mIsAvc) { 3003 err = makeAVCCodecSpecificData( 3004 (const uint8_t *)buffer->data() 3005 + buffer->range_offset(), 3006 buffer->range_length()); 3007 } else if (mIsHevc || mIsHeic) { 3008 err = makeHEVCCodecSpecificData( 3009 (const uint8_t *)buffer->data() 3010 + buffer->range_offset(), 3011 buffer->range_length()); 3012 } else if (mIsMPEG4) { 3013 copyCodecSpecificData((const uint8_t *)buffer->data() + buffer->range_offset(), 3014 buffer->range_length()); 3015 } 3016 } 3017 3018 buffer->release(); 3019 buffer = NULL; 3020 if (OK != err) { 3021 mSource->stop(); 3022 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_ERROR, 3023 mTrackId | MEDIA_RECORDER_TRACK_ERROR_GENERAL, err); 3024 break; 3025 } 3026 3027 mGotAllCodecSpecificData = true; 3028 continue; 3029 } 3030 3031 // Per-frame metadata sample's size must be smaller than max allowed. 3032 if (!mIsVideo && !mIsAudio && !mIsHeic && 3033 buffer->range_length() >= kMaxMetadataSize) { 3034 ALOGW("Buffer size is %zu. Maximum metadata buffer size is %lld for %s track", 3035 buffer->range_length(), (long long)kMaxMetadataSize, trackName); 3036 buffer->release(); 3037 mSource->stop(); 3038 mIsMalformed = true; 3039 break; 3040 } 3041 3042 bool isExif = false; 3043 uint32_t tiffHdrOffset = 0; 3044 int32_t isMuxerData; 3045 if (buffer->meta_data().findInt32(kKeyIsMuxerData, &isMuxerData) && isMuxerData) { 3046 // We only support one type of muxer data, which is Exif data block. 3047 isExif = isExifData(buffer, &tiffHdrOffset); 3048 if (!isExif) { 3049 ALOGW("Ignoring bad Exif data block"); 3050 buffer->release(); 3051 buffer = NULL; 3052 continue; 3053 } 3054 } 3055 3056 ++nActualFrames; 3057 3058 // Make a deep copy of the MediaBuffer and Metadata and release 3059 // the original as soon as we can 3060 MediaBuffer *copy = new MediaBuffer(buffer->range_length()); 3061 memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(), 3062 buffer->range_length()); 3063 copy->set_range(0, buffer->range_length()); 3064 meta_data = new MetaData(buffer->meta_data()); 3065 buffer->release(); 3066 buffer = NULL; 3067 3068 if (isExif) { 3069 copy->meta_data().setInt32(kKeyExifTiffOffset, tiffHdrOffset); 3070 } 3071 bool usePrefix = this->usePrefix() && !isExif; 3072 3073 if (usePrefix) StripStartcode(copy); 3074 3075 size_t sampleSize = copy->range_length(); 3076 if (usePrefix) { 3077 if (mOwner->useNalLengthFour()) { 3078 sampleSize += 4; 3079 } else { 3080 sampleSize += 2; 3081 } 3082 } 3083 3084 // Max file size or duration handling 3085 mMdatSizeBytes += sampleSize; 3086 updateTrackSizeEstimate(); 3087 3088 if (mOwner->exceedsFileSizeLimit()) { 3089 if (mOwner->switchFd() != OK) { 3090 ALOGW("Recorded file size exceeds limit %" PRId64 "bytes", 3091 mOwner->mMaxFileSizeLimitBytes); 3092 mSource->stop(); 3093 mOwner->notify( 3094 MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0); 3095 } else { 3096 ALOGV("%s Current recorded file size exceeds limit %" PRId64 "bytes. Switching output", 3097 getTrackType(), mOwner->mMaxFileSizeLimitBytes); 3098 } 3099 copy->release(); 3100 break; 3101 } 3102 3103 if (mOwner->exceedsFileDurationLimit()) { 3104 ALOGW("Recorded file duration exceeds limit %" PRId64 "microseconds", 3105 mOwner->mMaxFileDurationLimitUs); 3106 mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0); 3107 copy->release(); 3108 mSource->stop(); 3109 break; 3110 } 3111 3112 if (mOwner->approachingFileSizeLimit()) { 3113 mOwner->notifyApproachingLimit(); 3114 } 3115 3116 int32_t isSync = false; 3117 meta_data->findInt32(kKeyIsSyncFrame, &isSync); 3118 CHECK(meta_data->findInt64(kKeyTime, ×tampUs)); 3119 3120 // For video, skip the first several non-key frames until getting the first key frame. 3121 if (mIsVideo && !mGotStartKeyFrame && !isSync) { 3122 ALOGD("Video skip non-key frame"); 3123 copy->release(); 3124 continue; 3125 } 3126 if (mIsVideo && isSync) { 3127 mGotStartKeyFrame = true; 3128 } 3129 //////////////////////////////////////////////////////////////////////////////// 3130 3131 if (!mIsHeic) { 3132 if (mStszTableEntries->count() == 0) { 3133 mFirstSampleTimeRealUs = systemTime() / 1000; 3134 mOwner->setStartTimestampUs(timestampUs); 3135 mStartTimestampUs = timestampUs; 3136 previousPausedDurationUs = mStartTimestampUs; 3137 } 3138 3139 if (mResumed) { 3140 int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs; 3141 if (WARN_UNLESS(durExcludingEarlierPausesUs >= 0LL, "for %s track", trackName)) { 3142 copy->release(); 3143 mSource->stop(); 3144 mIsMalformed = true; 3145 break; 3146 } 3147 3148 int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs; 3149 if (WARN_UNLESS(pausedDurationUs >= lastDurationUs, "for %s track", trackName)) { 3150 copy->release(); 3151 mSource->stop(); 3152 mIsMalformed = true; 3153 break; 3154 } 3155 3156 previousPausedDurationUs += pausedDurationUs - lastDurationUs; 3157 mResumed = false; 3158 } 3159 TimestampDebugHelperEntry timestampDebugEntry; 3160 timestampUs -= previousPausedDurationUs; 3161 timestampDebugEntry.pts = timestampUs; 3162 if (WARN_UNLESS(timestampUs >= 0LL, "for %s track", trackName)) { 3163 copy->release(); 3164 mSource->stop(); 3165 mIsMalformed = true; 3166 break; 3167 } 3168 3169 if (mIsVideo) { 3170 /* 3171 * Composition time: timestampUs 3172 * Decoding time: decodingTimeUs 3173 * Composition time offset = composition time - decoding time 3174 */ 3175 int64_t decodingTimeUs; 3176 CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs)); 3177 decodingTimeUs -= previousPausedDurationUs; 3178 3179 // ensure non-negative, monotonic decoding time 3180 if (mLastDecodingTimeUs < 0) { 3181 decodingTimeUs = std::max((int64_t)0, decodingTimeUs); 3182 } else { 3183 // increase decoding time by at least the larger vaule of 1 tick and 3184 // 0.1 milliseconds. This needs to take into account the possible 3185 // delta adjustment in DurationTicks in below. 3186 decodingTimeUs = std::max(mLastDecodingTimeUs + 3187 std::max(100, divUp(1000000, mTimeScale)), decodingTimeUs); 3188 } 3189 3190 mLastDecodingTimeUs = decodingTimeUs; 3191 timestampDebugEntry.dts = decodingTimeUs; 3192 timestampDebugEntry.frameType = isSync ? "Key frame" : "Non-Key frame"; 3193 // Insert the timestamp into the mTimestampDebugHelper 3194 if (mTimestampDebugHelper.size() >= kTimestampDebugCount) { 3195 mTimestampDebugHelper.pop_front(); 3196 } 3197 mTimestampDebugHelper.push_back(timestampDebugEntry); 3198 3199 cttsOffsetTimeUs = 3200 timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs; 3201 if (WARN_UNLESS(cttsOffsetTimeUs >= 0LL, "for %s track", trackName)) { 3202 copy->release(); 3203 mSource->stop(); 3204 mIsMalformed = true; 3205 break; 3206 } 3207 3208 timestampUs = decodingTimeUs; 3209 ALOGV("decoding time: %" PRId64 " and ctts offset time: %" PRId64, 3210 timestampUs, cttsOffsetTimeUs); 3211 3212 // Update ctts box table if necessary 3213 currCttsOffsetTimeTicks = 3214 (cttsOffsetTimeUs * mTimeScale + 500000LL) / 1000000LL; 3215 if (WARN_UNLESS(currCttsOffsetTimeTicks <= 0x0FFFFFFFFLL, "for %s track", trackName)) { 3216 copy->release(); 3217 mSource->stop(); 3218 mIsMalformed = true; 3219 break; 3220 } 3221 3222 if (mStszTableEntries->count() == 0) { 3223 // Force the first ctts table entry to have one single entry 3224 // so that we can do adjustment for the initial track start 3225 // time offset easily in writeCttsBox(). 3226 lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks; 3227 addOneCttsTableEntry(1, currCttsOffsetTimeTicks); 3228 cttsSampleCount = 0; // No sample in ctts box is pending 3229 } else { 3230 if (currCttsOffsetTimeTicks != lastCttsOffsetTimeTicks) { 3231 addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks); 3232 lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks; 3233 cttsSampleCount = 1; // One sample in ctts box is pending 3234 } else { 3235 ++cttsSampleCount; 3236 } 3237 } 3238 3239 // Update ctts time offset range 3240 if (mStszTableEntries->count() == 0) { 3241 mMinCttsOffsetTicks = currCttsOffsetTimeTicks; 3242 mMaxCttsOffsetTicks = currCttsOffsetTimeTicks; 3243 } else { 3244 if (currCttsOffsetTimeTicks > mMaxCttsOffsetTicks) { 3245 mMaxCttsOffsetTicks = currCttsOffsetTimeTicks; 3246 } else if (currCttsOffsetTimeTicks < mMinCttsOffsetTicks) { 3247 mMinCttsOffsetTicks = currCttsOffsetTimeTicks; 3248 mMinCttsOffsetTimeUs = cttsOffsetTimeUs; 3249 } 3250 } 3251 } 3252 3253 if (mOwner->isRealTimeRecording()) { 3254 if (mIsAudio) { 3255 updateDriftTime(meta_data); 3256 } 3257 } 3258 3259 if (WARN_UNLESS(timestampUs >= 0LL, "for %s track", trackName)) { 3260 copy->release(); 3261 mSource->stop(); 3262 mIsMalformed = true; 3263 break; 3264 } 3265 3266 ALOGV("%s media time stamp: %" PRId64 " and previous paused duration %" PRId64, 3267 trackName, timestampUs, previousPausedDurationUs); 3268 if (timestampUs > mTrackDurationUs) { 3269 mTrackDurationUs = timestampUs; 3270 } 3271 3272 // We need to use the time scale based ticks, rather than the 3273 // timestamp itself to determine whether we have to use a new 3274 // stts entry, since we may have rounding errors. 3275 // The calculation is intended to reduce the accumulated 3276 // rounding errors. 3277 currDurationTicks = 3278 ((timestampUs * mTimeScale + 500000LL) / 1000000LL - 3279 (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL); 3280 if (currDurationTicks < 0LL) { 3281 ALOGE("do not support out of order frames (timestamp: %lld < last: %lld for %s track", 3282 (long long)timestampUs, (long long)lastTimestampUs, trackName); 3283 copy->release(); 3284 mSource->stop(); 3285 mIsMalformed = true; 3286 break; 3287 } 3288 3289 // if the duration is different for this sample, see if it is close enough to the previous 3290 // duration that we can fudge it and use the same value, to avoid filling the stts table 3291 // with lots of near-identical entries. 3292 // "close enough" here means that the current duration needs to be adjusted by less 3293 // than 0.1 milliseconds 3294 if (lastDurationTicks && (currDurationTicks != lastDurationTicks)) { 3295 int64_t deltaUs = ((lastDurationTicks - currDurationTicks) * 1000000LL 3296 + (mTimeScale / 2)) / mTimeScale; 3297 if (deltaUs > -100 && deltaUs < 100) { 3298 // use previous ticks, and adjust timestamp as if it was actually that number 3299 // of ticks 3300 currDurationTicks = lastDurationTicks; 3301 timestampUs += deltaUs; 3302 } 3303 } 3304 mStszTableEntries->add(htonl(sampleSize)); 3305 if (mStszTableEntries->count() > 2) { 3306 3307 // Force the first sample to have its own stts entry so that 3308 // we can adjust its value later to maintain the A/V sync. 3309 if (mStszTableEntries->count() == 3 || currDurationTicks != lastDurationTicks) { 3310 addOneSttsTableEntry(sampleCount, lastDurationTicks); 3311 sampleCount = 1; 3312 } else { 3313 ++sampleCount; 3314 } 3315 3316 } 3317 if (mSamplesHaveSameSize) { 3318 if (mStszTableEntries->count() >= 2 && previousSampleSize != sampleSize) { 3319 mSamplesHaveSameSize = false; 3320 } 3321 previousSampleSize = sampleSize; 3322 } 3323 ALOGV("%s timestampUs/lastTimestampUs: %" PRId64 "/%" PRId64, 3324 trackName, timestampUs, lastTimestampUs); 3325 lastDurationUs = timestampUs - lastTimestampUs; 3326 lastDurationTicks = currDurationTicks; 3327 lastTimestampUs = timestampUs; 3328 3329 if (isSync != 0) { 3330 addOneStssTableEntry(mStszTableEntries->count()); 3331 } 3332 3333 if (mTrackingProgressStatus) { 3334 if (mPreviousTrackTimeUs <= 0) { 3335 mPreviousTrackTimeUs = mStartTimestampUs; 3336 } 3337 trackProgressStatus(timestampUs); 3338 } 3339 } 3340 if (!hasMultipleTracks) { 3341 size_t bytesWritten; 3342 off64_t offset = mOwner->addSample_l( 3343 copy, usePrefix, tiffHdrOffset, &bytesWritten); 3344 3345 if (mIsHeic) { 3346 addItemOffsetAndSize(offset, bytesWritten, isExif); 3347 } else { 3348 uint32_t count = (mOwner->use32BitFileOffset() 3349 ? mStcoTableEntries->count() 3350 : mCo64TableEntries->count()); 3351 3352 if (count == 0) { 3353 addChunkOffset(offset); 3354 } 3355 } 3356 copy->release(); 3357 copy = NULL; 3358 continue; 3359 } 3360 3361 mChunkSamples.push_back(copy); 3362 if (mIsHeic) { 3363 bufferChunk(0 /*timestampUs*/); 3364 ++nChunks; 3365 } else if (interleaveDurationUs == 0) { 3366 addOneStscTableEntry(++nChunks, 1); 3367 bufferChunk(timestampUs); 3368 } else { 3369 if (chunkTimestampUs == 0) { 3370 chunkTimestampUs = timestampUs; 3371 } else { 3372 int64_t chunkDurationUs = timestampUs - chunkTimestampUs; 3373 if (chunkDurationUs > interleaveDurationUs) { 3374 if (chunkDurationUs > mMaxChunkDurationUs) { 3375 mMaxChunkDurationUs = chunkDurationUs; 3376 } 3377 ++nChunks; 3378 if (nChunks == 1 || // First chunk 3379 lastSamplesPerChunk != mChunkSamples.size()) { 3380 lastSamplesPerChunk = mChunkSamples.size(); 3381 addOneStscTableEntry(nChunks, lastSamplesPerChunk); 3382 } 3383 bufferChunk(timestampUs); 3384 chunkTimestampUs = timestampUs; 3385 } 3386 } 3387 } 3388 3389 } 3390 3391 if (isTrackMalFormed()) { 3392 dumpTimeStamps(); 3393 err = ERROR_MALFORMED; 3394 } 3395 3396 mOwner->trackProgressStatus(mTrackId, -1, err); 3397 3398 if (mIsHeic) { 3399 if (!mChunkSamples.empty()) { 3400 bufferChunk(0); 3401 ++nChunks; 3402 } 3403 } else { 3404 // Last chunk 3405 if (!hasMultipleTracks) { 3406 addOneStscTableEntry(1, mStszTableEntries->count()); 3407 } else if (!mChunkSamples.empty()) { 3408 addOneStscTableEntry(++nChunks, mChunkSamples.size()); 3409 bufferChunk(timestampUs); 3410 } 3411 3412 // We don't really know how long the last frame lasts, since 3413 // there is no frame time after it, just repeat the previous 3414 // frame's duration. 3415 if (mStszTableEntries->count() == 1) { 3416 lastDurationUs = 0; // A single sample's duration 3417 lastDurationTicks = 0; 3418 } else { 3419 ++sampleCount; // Count for the last sample 3420 } 3421 3422 if (mStszTableEntries->count() <= 2) { 3423 addOneSttsTableEntry(1, lastDurationTicks); 3424 if (sampleCount - 1 > 0) { 3425 addOneSttsTableEntry(sampleCount - 1, lastDurationTicks); 3426 } 3427 } else { 3428 addOneSttsTableEntry(sampleCount, lastDurationTicks); 3429 } 3430 3431 // The last ctts box may not have been written yet, and this 3432 // is to make sure that we write out the last ctts box. 3433 if (currCttsOffsetTimeTicks == lastCttsOffsetTimeTicks) { 3434 if (cttsSampleCount > 0) { 3435 addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks); 3436 } 3437 } 3438 3439 mTrackDurationUs += lastDurationUs; 3440 } 3441 mReachedEOS = true; 3442 3443 sendTrackSummary(hasMultipleTracks); 3444 3445 ALOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s", 3446 count, nZeroLengthFrames, mStszTableEntries->count(), trackName); 3447 if (mIsAudio) { 3448 ALOGI("Audio track drift time: %" PRId64 " us", mOwner->getDriftTimeUs()); 3449 } 3450 3451 if (err == ERROR_END_OF_STREAM) { 3452 return OK; 3453 } 3454 return err; 3455 } 3456 3457 bool MPEG4Writer::Track::isTrackMalFormed() const { 3458 if (mIsMalformed) { 3459 return true; 3460 } 3461 3462 if (!mIsHeic && mStszTableEntries->count() == 0) { // no samples written 3463 ALOGE("The number of recorded samples is 0"); 3464 return true; 3465 } 3466 3467 if (mIsVideo && mStssTableEntries->count() == 0) { // no sync frames for video 3468 ALOGE("There are no sync frames for video track"); 3469 return true; 3470 } 3471 3472 if (OK != checkCodecSpecificData()) { // no codec specific data 3473 return true; 3474 } 3475 3476 return false; 3477 } 3478 3479 void MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) { 3480 3481 // Send track summary only if test mode is enabled. 3482 if (!isTestModeEnabled()) { 3483 return; 3484 } 3485 3486 int trackNum = (mTrackId << 28); 3487 3488 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 3489 trackNum | MEDIA_RECORDER_TRACK_INFO_TYPE, 3490 mIsAudio ? 0: 1); 3491 3492 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 3493 trackNum | MEDIA_RECORDER_TRACK_INFO_DURATION_MS, 3494 mTrackDurationUs / 1000); 3495 3496 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 3497 trackNum | MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES, 3498 mStszTableEntries->count()); 3499 3500 { 3501 // The system delay time excluding the requested initial delay that 3502 // is used to eliminate the recording sound. 3503 int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL; 3504 if (startTimeOffsetUs < 0) { // Start time offset was not set 3505 startTimeOffsetUs = kInitialDelayTimeUs; 3506 } 3507 int64_t initialDelayUs = 3508 mFirstSampleTimeRealUs - mStartTimeRealUs - startTimeOffsetUs; 3509 3510 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 3511 trackNum | MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS, 3512 (initialDelayUs) / 1000); 3513 } 3514 3515 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 3516 trackNum | MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES, 3517 mMdatSizeBytes / 1024); 3518 3519 if (hasMultipleTracks) { 3520 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 3521 trackNum | MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS, 3522 mMaxChunkDurationUs / 1000); 3523 3524 int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 3525 if (mStartTimestampUs != moovStartTimeUs) { 3526 int64_t startTimeOffsetUs = mStartTimestampUs - moovStartTimeUs; 3527 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 3528 trackNum | MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS, 3529 startTimeOffsetUs / 1000); 3530 } 3531 } 3532 } 3533 3534 void MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) { 3535 ALOGV("trackProgressStatus: %" PRId64 " us", timeUs); 3536 3537 if (mTrackEveryTimeDurationUs > 0 && 3538 timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) { 3539 ALOGV("Fire time tracking progress status at %" PRId64 " us", timeUs); 3540 mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err); 3541 mPreviousTrackTimeUs = timeUs; 3542 } 3543 } 3544 3545 void MPEG4Writer::trackProgressStatus( 3546 size_t trackId, int64_t timeUs, status_t err) { 3547 Mutex::Autolock lock(mLock); 3548 int32_t trackNum = (trackId << 28); 3549 3550 // Error notification 3551 // Do not consider ERROR_END_OF_STREAM an error 3552 if (err != OK && err != ERROR_END_OF_STREAM) { 3553 notify(MEDIA_RECORDER_TRACK_EVENT_ERROR, 3554 trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL, 3555 err); 3556 return; 3557 } 3558 3559 if (timeUs == -1) { 3560 // Send completion notification 3561 notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 3562 trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS, 3563 err); 3564 } else { 3565 // Send progress status 3566 notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 3567 trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME, 3568 timeUs / 1000); 3569 } 3570 } 3571 3572 void MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) { 3573 ALOGV("setDriftTimeUs: %" PRId64 " us", driftTimeUs); 3574 Mutex::Autolock autolock(mLock); 3575 mDriftTimeUs = driftTimeUs; 3576 } 3577 3578 int64_t MPEG4Writer::getDriftTimeUs() { 3579 ALOGV("getDriftTimeUs: %" PRId64 " us", mDriftTimeUs); 3580 Mutex::Autolock autolock(mLock); 3581 return mDriftTimeUs; 3582 } 3583 3584 bool MPEG4Writer::isRealTimeRecording() const { 3585 return mIsRealTimeRecording; 3586 } 3587 3588 bool MPEG4Writer::useNalLengthFour() { 3589 return mUse4ByteNalLength; 3590 } 3591 3592 void MPEG4Writer::Track::bufferChunk(int64_t timestampUs) { 3593 ALOGV("bufferChunk"); 3594 3595 Chunk chunk(this, timestampUs, mChunkSamples); 3596 mOwner->bufferChunk(chunk); 3597 mChunkSamples.clear(); 3598 } 3599 3600 int64_t MPEG4Writer::Track::getDurationUs() const { 3601 return mTrackDurationUs + getStartTimeOffsetTimeUs() + mOwner->getStartTimeOffsetBFramesUs(); 3602 } 3603 3604 int64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const { 3605 return mEstimatedTrackSizeBytes; 3606 } 3607 3608 int32_t MPEG4Writer::Track::getMetaSizeIncrease( 3609 int32_t angle, int32_t trackCount) const { 3610 CHECK(mIsHeic); 3611 3612 int32_t grid = (mTileWidth > 0); 3613 int32_t rotate = (angle > 0); 3614 3615 // Note that the rotation angle is in the file meta, and we don't have 3616 // it until start, so here the calculation has to assume rotation. 3617 3618 // increase to ipco 3619 int32_t increase = 20 * (grid + 1) // 'ispe' property 3620 + (8 + mCodecSpecificDataSize) // 'hvcC' property 3621 ; 3622 3623 if (rotate) { 3624 increase += 9; // 'irot' property (worst case) 3625 } 3626 3627 // increase to iref and idat 3628 if (grid) { 3629 increase += (12 + mNumTiles * 2) // 'dimg' in iref 3630 + 12; // ImageGrid in 'idat' (worst case) 3631 } 3632 3633 increase += (12 + 2); // 'cdsc' in iref 3634 3635 // increase to iloc, iinf 3636 increase += (16 // increase to 'iloc' 3637 + 21) // increase to 'iinf' 3638 * (mNumTiles + grid + 1); // "+1" is for 'Exif' 3639 3640 // When total # of properties is > 127, the properties id becomes 2-byte. 3641 // We write 4 properties at most for each image (2x'ispe', 1x'hvcC', 1x'irot'). 3642 // Set the threshold to be 30. 3643 int32_t propBytes = trackCount > 30 ? 2 : 1; 3644 3645 // increase to ipma 3646 increase += (3 + 2 * propBytes) * mNumTiles // 'ispe' + 'hvcC' 3647 + grid * (3 + propBytes) // 'ispe' for grid 3648 + rotate * propBytes; // 'irot' (either on grid or tile) 3649 3650 return increase; 3651 } 3652 3653 status_t MPEG4Writer::Track::checkCodecSpecificData() const { 3654 const char *mime; 3655 CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 3656 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) || 3657 !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) || 3658 !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime) || 3659 !strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime) || 3660 !strcasecmp(MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC, mime)) { 3661 if (!mCodecSpecificData || 3662 mCodecSpecificDataSize <= 0) { 3663 ALOGE("Missing codec specific data"); 3664 return ERROR_MALFORMED; 3665 } 3666 } else { 3667 if (mCodecSpecificData || 3668 mCodecSpecificDataSize > 0) { 3669 ALOGE("Unexepected codec specific data found"); 3670 return ERROR_MALFORMED; 3671 } 3672 } 3673 return OK; 3674 } 3675 3676 const char *MPEG4Writer::Track::getTrackType() const { 3677 return mIsAudio ? "Audio" : 3678 mIsVideo ? "Video" : 3679 mIsHeic ? "Image" : 3680 "Metadata"; 3681 } 3682 3683 void MPEG4Writer::Track::writeTrackHeader(bool use32BitOffset) { 3684 uint32_t now = getMpeg4Time(); 3685 mOwner->beginBox("trak"); 3686 writeTkhdBox(now); 3687 writeEdtsBox(); 3688 mOwner->beginBox("mdia"); 3689 writeMdhdBox(now); 3690 writeHdlrBox(); 3691 mOwner->beginBox("minf"); 3692 if (mIsAudio) { 3693 writeSmhdBox(); 3694 } else if (mIsVideo) { 3695 writeVmhdBox(); 3696 } else { 3697 writeNmhdBox(); 3698 } 3699 writeDinfBox(); 3700 writeStblBox(use32BitOffset); 3701 mOwner->endBox(); // minf 3702 mOwner->endBox(); // mdia 3703 mOwner->endBox(); // trak 3704 } 3705 3706 int64_t MPEG4Writer::Track::getMinCttsOffsetTimeUs() { 3707 // For video tracks with ctts table, this should return the minimum ctts 3708 // offset in the table. For non-video tracks or video tracks without ctts 3709 // table, this will return kMaxCttsOffsetTimeUs. 3710 if (mMinCttsOffsetTicks == mMaxCttsOffsetTicks) { 3711 return kMaxCttsOffsetTimeUs; 3712 } 3713 return mMinCttsOffsetTimeUs; 3714 } 3715 3716 void MPEG4Writer::Track::writeStblBox(bool use32BitOffset) { 3717 mOwner->beginBox("stbl"); 3718 mOwner->beginBox("stsd"); 3719 mOwner->writeInt32(0); // version=0, flags=0 3720 mOwner->writeInt32(1); // entry count 3721 if (mIsAudio) { 3722 writeAudioFourCCBox(); 3723 } else if (mIsVideo) { 3724 writeVideoFourCCBox(); 3725 } else { 3726 writeMetadataFourCCBox(); 3727 } 3728 mOwner->endBox(); // stsd 3729 writeSttsBox(); 3730 if (mIsVideo) { 3731 writeCttsBox(); 3732 writeStssBox(); 3733 } 3734 writeStszBox(); 3735 writeStscBox(); 3736 writeStcoBox(use32BitOffset); 3737 mOwner->endBox(); // stbl 3738 } 3739 3740 void MPEG4Writer::Track::writeMetadataFourCCBox() { 3741 const char *mime; 3742 bool success = mMeta->findCString(kKeyMIMEType, &mime); 3743 CHECK(success); 3744 const char *fourcc = getFourCCForMime(mime); 3745 if (fourcc == NULL) { 3746 ALOGE("Unknown mime type '%s'.", mime); 3747 TRESPASS(); 3748 } 3749 mOwner->beginBox(fourcc); // TextMetaDataSampleEntry 3750 3751 // HACK to make the metadata track compliant with the ISO standard. 3752 // 3753 // Metadata track is added from API 26 and the original implementation does not 3754 // fully followed the TextMetaDataSampleEntry specified in ISO/IEC 14496-12-2015 3755 // in that only the mime_format is written out. content_encoding and 3756 // data_reference_index have not been written out. This leads to the failure 3757 // when some MP4 parser tries to parse the metadata track according to the 3758 // standard. The hack here will make the metadata track compliant with the 3759 // standard while still maintaining backwards compatibility. This would enable 3760 // Android versions before API 29 to be able to read out the standard compliant 3761 // Metadata track generated with Android API 29 and upward. The trick is based 3762 // on the fact that the Metadata track must start with prefix application/ and 3763 // those missing fields are not used in Android's Metadata track. By writting 3764 // out the mime_format twice, the first mime_format will be used to fill out the 3765 // missing reserved, data_reference_index and content encoding fields. On the 3766 // parser side, the extracter before API 29 will read out the first mime_format 3767 // correctly and drop the second mime_format. The extractor from API 29 will 3768 // check if the reserved, data_reference_index and content encoding are filled 3769 // with application to detect if this is a standard compliant metadata track 3770 // and read out the data accordingly. 3771 mOwner->writeCString(mime); 3772 3773 mOwner->writeCString(mime); // metadata mime_format 3774 mOwner->endBox(); // mett 3775 } 3776 3777 void MPEG4Writer::Track::writeVideoFourCCBox() { 3778 const char *mime; 3779 bool success = mMeta->findCString(kKeyMIMEType, &mime); 3780 CHECK(success); 3781 const char *fourcc = getFourCCForMime(mime); 3782 if (fourcc == NULL) { 3783 ALOGE("Unknown mime type '%s'.", mime); 3784 TRESPASS(); 3785 } 3786 3787 mOwner->beginBox(fourcc); // video format 3788 mOwner->writeInt32(0); // reserved 3789 mOwner->writeInt16(0); // reserved 3790 mOwner->writeInt16(1); // data ref index 3791 mOwner->writeInt16(0); // predefined 3792 mOwner->writeInt16(0); // reserved 3793 mOwner->writeInt32(0); // predefined 3794 mOwner->writeInt32(0); // predefined 3795 mOwner->writeInt32(0); // predefined 3796 3797 int32_t width, height; 3798 success = mMeta->findInt32(kKeyWidth, &width); 3799 success = success && mMeta->findInt32(kKeyHeight, &height); 3800 CHECK(success); 3801 3802 mOwner->writeInt16(width); 3803 mOwner->writeInt16(height); 3804 mOwner->writeInt32(0x480000); // horiz resolution 3805 mOwner->writeInt32(0x480000); // vert resolution 3806 mOwner->writeInt32(0); // reserved 3807 mOwner->writeInt16(1); // frame count 3808 mOwner->writeInt8(0); // compressor string length 3809 mOwner->write(" ", 31); 3810 mOwner->writeInt16(0x18); // depth 3811 mOwner->writeInt16(-1); // predefined 3812 3813 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 3814 writeMp4vEsdsBox(); 3815 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 3816 writeD263Box(); 3817 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 3818 writeAvccBox(); 3819 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) { 3820 writeHvccBox(); 3821 } 3822 3823 writePaspBox(); 3824 writeColrBox(); 3825 mOwner->endBox(); // mp4v, s263 or avc1 3826 } 3827 3828 void MPEG4Writer::Track::writeColrBox() { 3829 ColorAspects aspects; 3830 memset(&aspects, 0, sizeof(aspects)); 3831 // TRICKY: using | instead of || because we want to execute all findInt32-s 3832 if (mMeta->findInt32(kKeyColorPrimaries, (int32_t*)&aspects.mPrimaries) 3833 | mMeta->findInt32(kKeyTransferFunction, (int32_t*)&aspects.mTransfer) 3834 | mMeta->findInt32(kKeyColorMatrix, (int32_t*)&aspects.mMatrixCoeffs) 3835 | mMeta->findInt32(kKeyColorRange, (int32_t*)&aspects.mRange)) { 3836 int32_t primaries, transfer, coeffs; 3837 bool fullRange; 3838 ColorUtils::convertCodecColorAspectsToIsoAspects( 3839 aspects, &primaries, &transfer, &coeffs, &fullRange); 3840 mOwner->beginBox("colr"); 3841 mOwner->writeFourcc("nclx"); 3842 mOwner->writeInt16(primaries); 3843 mOwner->writeInt16(transfer); 3844 mOwner->writeInt16(coeffs); 3845 mOwner->writeInt8(int8_t(fullRange ? 0x80 : 0x0)); 3846 mOwner->endBox(); // colr 3847 } 3848 } 3849 3850 void MPEG4Writer::Track::writeAudioFourCCBox() { 3851 const char *mime; 3852 bool success = mMeta->findCString(kKeyMIMEType, &mime); 3853 CHECK(success); 3854 const char *fourcc = getFourCCForMime(mime); 3855 if (fourcc == NULL) { 3856 ALOGE("Unknown mime type '%s'.", mime); 3857 TRESPASS(); 3858 } 3859 3860 mOwner->beginBox(fourcc); // audio format 3861 mOwner->writeInt32(0); // reserved 3862 mOwner->writeInt16(0); // reserved 3863 mOwner->writeInt16(0x1); // data ref index 3864 mOwner->writeInt32(0); // reserved 3865 mOwner->writeInt32(0); // reserved 3866 int32_t nChannels; 3867 CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels)); 3868 mOwner->writeInt16(nChannels); // channel count 3869 mOwner->writeInt16(16); // sample size 3870 mOwner->writeInt16(0); // predefined 3871 mOwner->writeInt16(0); // reserved 3872 3873 int32_t samplerate; 3874 success = mMeta->findInt32(kKeySampleRate, &samplerate); 3875 CHECK(success); 3876 mOwner->writeInt32(samplerate << 16); 3877 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 3878 writeMp4aEsdsBox(); 3879 } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) || 3880 !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 3881 writeDamrBox(); 3882 } 3883 mOwner->endBox(); 3884 } 3885 3886 static void generateEsdsSize(size_t dataLength, size_t* sizeGenerated, uint8_t* buffer) { 3887 size_t offset = 0, cur = 0; 3888 size_t more = 0x00; 3889 *sizeGenerated = 0; 3890 /* Start with the LSB(7 bits) of dataLength and build the byte sequence upto MSB. 3891 * Continuation flag(most significant bit) will be set on the first N-1 bytes. 3892 */ 3893 do { 3894 buffer[cur++] = (dataLength & 0x7f) | more; 3895 dataLength >>= 7; 3896 more = 0x80; 3897 ++(*sizeGenerated); 3898 } while (dataLength > 0u); 3899 --cur; 3900 // Reverse the newly formed byte sequence. 3901 while (cur > offset) { 3902 uint8_t tmp = buffer[cur]; 3903 buffer[cur--] = buffer[offset]; 3904 buffer[offset++] = tmp; 3905 } 3906 } 3907 3908 void MPEG4Writer::Track::writeMp4aEsdsBox() { 3909 CHECK(mCodecSpecificData); 3910 CHECK_GT(mCodecSpecificDataSize, 0u); 3911 3912 uint8_t sizeESDBuffer[kESDSScratchBufferSize]; 3913 uint8_t sizeDCDBuffer[kESDSScratchBufferSize]; 3914 uint8_t sizeDSIBuffer[kESDSScratchBufferSize]; 3915 size_t sizeESD = 0; 3916 size_t sizeDCD = 0; 3917 size_t sizeDSI = 0; 3918 generateEsdsSize(mCodecSpecificDataSize, &sizeDSI, sizeDSIBuffer); 3919 generateEsdsSize(mCodecSpecificDataSize + sizeDSI + 14, &sizeDCD, sizeDCDBuffer); 3920 generateEsdsSize(mCodecSpecificDataSize + sizeDSI + sizeDCD + 21, &sizeESD, sizeESDBuffer); 3921 3922 mOwner->beginBox("esds"); 3923 3924 mOwner->writeInt32(0); // version=0, flags=0 3925 mOwner->writeInt8(0x03); // ES_DescrTag 3926 mOwner->write(sizeESDBuffer, sizeESD); 3927 mOwner->writeInt16(0x0000);// ES_ID 3928 mOwner->writeInt8(0x00); 3929 3930 mOwner->writeInt8(0x04); // DecoderConfigDescrTag 3931 mOwner->write(sizeDCDBuffer, sizeDCD); 3932 mOwner->writeInt8(0x40); // objectTypeIndication ISO/IEC 14492-2 3933 mOwner->writeInt8(0x15); // streamType AudioStream 3934 3935 mOwner->writeInt16(0x03); // XXX 3936 mOwner->writeInt8(0x00); // buffer size 24-bit (0x300) 3937 3938 int32_t avgBitrate = 0; 3939 (void)mMeta->findInt32(kKeyBitRate, &avgBitrate); 3940 int32_t maxBitrate = 0; 3941 (void)mMeta->findInt32(kKeyMaxBitRate, &maxBitrate); 3942 mOwner->writeInt32(maxBitrate); 3943 mOwner->writeInt32(avgBitrate); 3944 3945 mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 3946 mOwner->write(sizeDSIBuffer, sizeDSI); 3947 mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 3948 3949 static const uint8_t kData2[] = { 3950 0x06, // SLConfigDescriptorTag 3951 0x01, 3952 0x02 3953 }; 3954 mOwner->write(kData2, sizeof(kData2)); 3955 3956 mOwner->endBox(); // esds 3957 } 3958 3959 void MPEG4Writer::Track::writeMp4vEsdsBox() { 3960 CHECK(mCodecSpecificData); 3961 CHECK_GT(mCodecSpecificDataSize, 0u); 3962 3963 uint8_t sizeESDBuffer[kESDSScratchBufferSize]; 3964 uint8_t sizeDCDBuffer[kESDSScratchBufferSize]; 3965 uint8_t sizeDSIBuffer[kESDSScratchBufferSize]; 3966 size_t sizeESD = 0; 3967 size_t sizeDCD = 0; 3968 size_t sizeDSI = 0; 3969 generateEsdsSize(mCodecSpecificDataSize, &sizeDSI, sizeDSIBuffer); 3970 generateEsdsSize(mCodecSpecificDataSize + sizeDSI + 14, &sizeDCD, sizeDCDBuffer); 3971 generateEsdsSize(mCodecSpecificDataSize + sizeDSI + sizeDCD + 21, &sizeESD, sizeESDBuffer); 3972 3973 mOwner->beginBox("esds"); 3974 3975 mOwner->writeInt32(0); // version=0, flags=0 3976 3977 mOwner->writeInt8(0x03); // ES_DescrTag 3978 mOwner->write(sizeESDBuffer, sizeESD); 3979 mOwner->writeInt16(0x0000); // ES_ID 3980 mOwner->writeInt8(0x1f); 3981 3982 mOwner->writeInt8(0x04); // DecoderConfigDescrTag 3983 mOwner->write(sizeDCDBuffer, sizeDCD); 3984 mOwner->writeInt8(0x20); // objectTypeIndication ISO/IEC 14492-2 3985 mOwner->writeInt8(0x11); // streamType VisualStream 3986 3987 static const uint8_t kData[] = { 3988 0x01, 0x77, 0x00, // buffer size 96000 bytes 3989 }; 3990 mOwner->write(kData, sizeof(kData)); 3991 3992 int32_t avgBitrate = 0; 3993 (void)mMeta->findInt32(kKeyBitRate, &avgBitrate); 3994 int32_t maxBitrate = 0; 3995 (void)mMeta->findInt32(kKeyMaxBitRate, &maxBitrate); 3996 mOwner->writeInt32(maxBitrate); 3997 mOwner->writeInt32(avgBitrate); 3998 3999 mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 4000 4001 mOwner->write(sizeDSIBuffer, sizeDSI); 4002 mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 4003 4004 static const uint8_t kData2[] = { 4005 0x06, // SLConfigDescriptorTag 4006 0x01, 4007 0x02 4008 }; 4009 mOwner->write(kData2, sizeof(kData2)); 4010 4011 mOwner->endBox(); // esds 4012 } 4013 4014 void MPEG4Writer::Track::writeTkhdBox(uint32_t now) { 4015 mOwner->beginBox("tkhd"); 4016 // Flags = 7 to indicate that the track is enabled, and 4017 // part of the presentation 4018 mOwner->writeInt32(0x07); // version=0, flags=7 4019 mOwner->writeInt32(now); // creation time 4020 mOwner->writeInt32(now); // modification time 4021 mOwner->writeInt32(mTrackId); // track id starts with 1 4022 mOwner->writeInt32(0); // reserved 4023 int64_t trakDurationUs = getDurationUs(); 4024 int32_t mvhdTimeScale = mOwner->getTimeScale(); 4025 int32_t tkhdDuration = 4026 (trakDurationUs * mvhdTimeScale + 5E5) / 1E6; 4027 mOwner->writeInt32(tkhdDuration); // in mvhd timescale 4028 mOwner->writeInt32(0); // reserved 4029 mOwner->writeInt32(0); // reserved 4030 mOwner->writeInt16(0); // layer 4031 mOwner->writeInt16(0); // alternate group 4032 mOwner->writeInt16(mIsAudio ? 0x100 : 0); // volume 4033 mOwner->writeInt16(0); // reserved 4034 4035 mOwner->writeCompositionMatrix(mRotation); // matrix 4036 4037 if (!mIsVideo) { 4038 mOwner->writeInt32(0); 4039 mOwner->writeInt32(0); 4040 } else { 4041 int32_t width, height; 4042 bool success = mMeta->findInt32(kKeyDisplayWidth, &width); 4043 success = success && mMeta->findInt32(kKeyDisplayHeight, &height); 4044 4045 // Use width/height if display width/height are not present. 4046 if (!success) { 4047 success = mMeta->findInt32(kKeyWidth, &width); 4048 success = success && mMeta->findInt32(kKeyHeight, &height); 4049 } 4050 CHECK(success); 4051 4052 mOwner->writeInt32(width << 16); // 32-bit fixed-point value 4053 mOwner->writeInt32(height << 16); // 32-bit fixed-point value 4054 } 4055 mOwner->endBox(); // tkhd 4056 } 4057 4058 void MPEG4Writer::Track::writeVmhdBox() { 4059 mOwner->beginBox("vmhd"); 4060 mOwner->writeInt32(0x01); // version=0, flags=1 4061 mOwner->writeInt16(0); // graphics mode 4062 mOwner->writeInt16(0); // opcolor 4063 mOwner->writeInt16(0); 4064 mOwner->writeInt16(0); 4065 mOwner->endBox(); 4066 } 4067 4068 void MPEG4Writer::Track::writeSmhdBox() { 4069 mOwner->beginBox("smhd"); 4070 mOwner->writeInt32(0); // version=0, flags=0 4071 mOwner->writeInt16(0); // balance 4072 mOwner->writeInt16(0); // reserved 4073 mOwner->endBox(); 4074 } 4075 4076 void MPEG4Writer::Track::writeNmhdBox() { 4077 mOwner->beginBox("nmhd"); 4078 mOwner->writeInt32(0); // version=0, flags=0 4079 mOwner->endBox(); 4080 } 4081 4082 void MPEG4Writer::Track::writeHdlrBox() { 4083 mOwner->beginBox("hdlr"); 4084 mOwner->writeInt32(0); // version=0, flags=0 4085 mOwner->writeInt32(0); // component type: should be mhlr 4086 mOwner->writeFourcc(mIsAudio ? "soun" : (mIsVideo ? "vide" : "meta")); // component subtype 4087 mOwner->writeInt32(0); // reserved 4088 mOwner->writeInt32(0); // reserved 4089 mOwner->writeInt32(0); // reserved 4090 // Removing "r" for the name string just makes the string 4 byte aligned 4091 mOwner->writeCString(mIsAudio ? "SoundHandle": (mIsVideo ? "VideoHandle" : "MetadHandle")); 4092 mOwner->endBox(); 4093 } 4094 4095 void MPEG4Writer::Track::writeEdtsBox(){ 4096 ALOGV("%s : getStartTimeOffsetTimeUs of track:%" PRId64 " us", getTrackType(), 4097 getStartTimeOffsetTimeUs()); 4098 4099 // Prepone video playback. 4100 if (mMinCttsOffsetTicks != mMaxCttsOffsetTicks) { 4101 int32_t mvhdTimeScale = mOwner->getTimeScale(); 4102 uint32_t tkhdDuration = (getDurationUs() * mvhdTimeScale + 5E5) / 1E6; 4103 int64_t mediaTime = ((kMaxCttsOffsetTimeUs - getMinCttsOffsetTimeUs()) 4104 * mTimeScale + 5E5) / 1E6; 4105 if (tkhdDuration > 0 && mediaTime > 0) { 4106 addOneElstTableEntry(tkhdDuration, mediaTime, 1, 0); 4107 } 4108 } 4109 4110 if (mElstTableEntries->count() == 0) { 4111 return; 4112 } 4113 4114 mOwner->beginBox("edts"); 4115 mOwner->beginBox("elst"); 4116 mOwner->writeInt32(0); // version=0, flags=0 4117 mElstTableEntries->write(mOwner); 4118 mOwner->endBox(); // elst; 4119 mOwner->endBox(); // edts 4120 } 4121 4122 void MPEG4Writer::Track::writeMdhdBox(uint32_t now) { 4123 int64_t trakDurationUs = getDurationUs(); 4124 int64_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6; 4125 mOwner->beginBox("mdhd"); 4126 4127 if (mdhdDuration > UINT32_MAX) { 4128 mOwner->writeInt32((1 << 24)); // version=1, flags=0 4129 mOwner->writeInt64((int64_t)now); // creation time 4130 mOwner->writeInt64((int64_t)now); // modification time 4131 mOwner->writeInt32(mTimeScale); // media timescale 4132 mOwner->writeInt64(mdhdDuration); // media timescale 4133 } else { 4134 mOwner->writeInt32(0); // version=0, flags=0 4135 mOwner->writeInt32(now); // creation time 4136 mOwner->writeInt32(now); // modification time 4137 mOwner->writeInt32(mTimeScale); // media timescale 4138 mOwner->writeInt32((int32_t)mdhdDuration); // use media timescale 4139 } 4140 // Language follows the three letter standard ISO-639-2/T 4141 // 'e', 'n', 'g' for "English", for instance. 4142 // Each character is packed as the difference between its ASCII value and 0x60. 4143 // For "English", these are 00101, 01110, 00111. 4144 // XXX: Where is the padding bit located: 0x15C7? 4145 const char *lang = NULL; 4146 int16_t langCode = 0; 4147 if (mMeta->findCString(kKeyMediaLanguage, &lang) && lang && strnlen(lang, 3) > 2) { 4148 langCode = ((lang[0] & 0x1f) << 10) | ((lang[1] & 0x1f) << 5) | (lang[2] & 0x1f); 4149 } 4150 mOwner->writeInt16(langCode); // language code 4151 mOwner->writeInt16(0); // predefined 4152 mOwner->endBox(); 4153 } 4154 4155 void MPEG4Writer::Track::writeDamrBox() { 4156 // 3gpp2 Spec AMRSampleEntry fields 4157 mOwner->beginBox("damr"); 4158 mOwner->writeCString(" "); // vendor: 4 bytes 4159 mOwner->writeInt8(0); // decoder version 4160 mOwner->writeInt16(0x83FF); // mode set: all enabled 4161 mOwner->writeInt8(0); // mode change period 4162 mOwner->writeInt8(1); // frames per sample 4163 mOwner->endBox(); 4164 } 4165 4166 void MPEG4Writer::Track::writeUrlBox() { 4167 // The table index here refers to the sample description index 4168 // in the sample table entries. 4169 mOwner->beginBox("url "); 4170 mOwner->writeInt32(1); // version=0, flags=1 (self-contained) 4171 mOwner->endBox(); // url 4172 } 4173 4174 void MPEG4Writer::Track::writeDrefBox() { 4175 mOwner->beginBox("dref"); 4176 mOwner->writeInt32(0); // version=0, flags=0 4177 mOwner->writeInt32(1); // entry count (either url or urn) 4178 writeUrlBox(); 4179 mOwner->endBox(); // dref 4180 } 4181 4182 void MPEG4Writer::Track::writeDinfBox() { 4183 mOwner->beginBox("dinf"); 4184 writeDrefBox(); 4185 mOwner->endBox(); // dinf 4186 } 4187 4188 void MPEG4Writer::Track::writeAvccBox() { 4189 CHECK(mCodecSpecificData); 4190 CHECK_GE(mCodecSpecificDataSize, 5u); 4191 4192 // Patch avcc's lengthSize field to match the number 4193 // of bytes we use to indicate the size of a nal unit. 4194 uint8_t *ptr = (uint8_t *)mCodecSpecificData; 4195 ptr[4] = (ptr[4] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1); 4196 mOwner->beginBox("avcC"); 4197 mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 4198 mOwner->endBox(); // avcC 4199 } 4200 4201 4202 void MPEG4Writer::Track::writeHvccBox() { 4203 CHECK(mCodecSpecificData); 4204 CHECK_GE(mCodecSpecificDataSize, 5u); 4205 4206 // Patch avcc's lengthSize field to match the number 4207 // of bytes we use to indicate the size of a nal unit. 4208 uint8_t *ptr = (uint8_t *)mCodecSpecificData; 4209 ptr[21] = (ptr[21] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1); 4210 mOwner->beginBox("hvcC"); 4211 mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 4212 mOwner->endBox(); // hvcC 4213 } 4214 4215 void MPEG4Writer::Track::writeD263Box() { 4216 mOwner->beginBox("d263"); 4217 mOwner->writeInt32(0); // vendor 4218 mOwner->writeInt8(0); // decoder version 4219 mOwner->writeInt8(10); // level: 10 4220 mOwner->writeInt8(0); // profile: 0 4221 mOwner->endBox(); // d263 4222 } 4223 4224 // This is useful if the pixel is not square 4225 void MPEG4Writer::Track::writePaspBox() { 4226 mOwner->beginBox("pasp"); 4227 mOwner->writeInt32(1 << 16); // hspacing 4228 mOwner->writeInt32(1 << 16); // vspacing 4229 mOwner->endBox(); // pasp 4230 } 4231 4232 int64_t MPEG4Writer::Track::getStartTimeOffsetTimeUs() const { 4233 int64_t trackStartTimeOffsetUs = 0; 4234 int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 4235 if (mStartTimestampUs != -1 && mStartTimestampUs != moovStartTimeUs) { 4236 CHECK_GT(mStartTimestampUs, moovStartTimeUs); 4237 trackStartTimeOffsetUs = mStartTimestampUs - moovStartTimeUs; 4238 } 4239 return trackStartTimeOffsetUs; 4240 } 4241 4242 int32_t MPEG4Writer::Track::getStartTimeOffsetScaledTime() const { 4243 return (getStartTimeOffsetTimeUs() * mTimeScale + 500000LL) / 1000000LL; 4244 } 4245 4246 void MPEG4Writer::Track::writeSttsBox() { 4247 mOwner->beginBox("stts"); 4248 mOwner->writeInt32(0); // version=0, flags=0 4249 if (mMinCttsOffsetTicks == mMaxCttsOffsetTicks) { 4250 // For non-vdeio tracks or video tracks without ctts table, 4251 // adjust duration of first sample for tracks to account for 4252 // first sample not starting at the media start time. 4253 // TODO: consider signaling this using some offset 4254 // as this is not quite correct. 4255 uint32_t duration; 4256 CHECK(mSttsTableEntries->get(duration, 1)); 4257 duration = htonl(duration); // Back to host byte order 4258 int32_t startTimeOffsetScaled = (((getStartTimeOffsetTimeUs() + 4259 mOwner->getStartTimeOffsetBFramesUs()) * mTimeScale) + 500000LL) / 1000000LL; 4260 mSttsTableEntries->set(htonl((int32_t)duration + startTimeOffsetScaled), 1); 4261 } 4262 mSttsTableEntries->write(mOwner); 4263 mOwner->endBox(); // stts 4264 } 4265 4266 void MPEG4Writer::Track::writeCttsBox() { 4267 // There is no B frame at all 4268 if (mMinCttsOffsetTicks == mMaxCttsOffsetTicks) { 4269 return; 4270 } 4271 4272 // Do not write ctts box when there is no need to have it. 4273 if (mCttsTableEntries->count() == 0) { 4274 return; 4275 } 4276 4277 ALOGV("ctts box has %d entries with range [%" PRId64 ", %" PRId64 "]", 4278 mCttsTableEntries->count(), mMinCttsOffsetTicks, mMaxCttsOffsetTicks); 4279 4280 mOwner->beginBox("ctts"); 4281 mOwner->writeInt32(0); // version=0, flags=0 4282 int64_t deltaTimeUs = kMaxCttsOffsetTimeUs - getStartTimeOffsetTimeUs(); 4283 int64_t delta = (deltaTimeUs * mTimeScale + 500000LL) / 1000000LL; 4284 mCttsTableEntries->adjustEntries([delta](size_t /* ix */, uint32_t (&value)[2]) { 4285 // entries are <count, ctts> pairs; adjust only ctts 4286 uint32_t duration = htonl(value[1]); // back to host byte order 4287 // Prevent overflow and underflow 4288 if (delta > duration) { 4289 duration = 0; 4290 } else if (delta < 0 && UINT32_MAX + delta < duration) { 4291 duration = UINT32_MAX; 4292 } else { 4293 duration -= delta; 4294 } 4295 value[1] = htonl(duration); 4296 }); 4297 mCttsTableEntries->write(mOwner); 4298 mOwner->endBox(); // ctts 4299 } 4300 4301 void MPEG4Writer::Track::writeStssBox() { 4302 mOwner->beginBox("stss"); 4303 mOwner->writeInt32(0); // version=0, flags=0 4304 mStssTableEntries->write(mOwner); 4305 mOwner->endBox(); // stss 4306 } 4307 4308 void MPEG4Writer::Track::writeStszBox() { 4309 mOwner->beginBox("stsz"); 4310 mOwner->writeInt32(0); // version=0, flags=0 4311 mOwner->writeInt32(0); 4312 mStszTableEntries->write(mOwner); 4313 mOwner->endBox(); // stsz 4314 } 4315 4316 void MPEG4Writer::Track::writeStscBox() { 4317 mOwner->beginBox("stsc"); 4318 mOwner->writeInt32(0); // version=0, flags=0 4319 mStscTableEntries->write(mOwner); 4320 mOwner->endBox(); // stsc 4321 } 4322 4323 void MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) { 4324 mOwner->beginBox(use32BitOffset? "stco": "co64"); 4325 mOwner->writeInt32(0); // version=0, flags=0 4326 if (use32BitOffset) { 4327 mStcoTableEntries->write(mOwner); 4328 } else { 4329 mCo64TableEntries->write(mOwner); 4330 } 4331 mOwner->endBox(); // stco or co64 4332 } 4333 4334 void MPEG4Writer::writeUdtaBox() { 4335 beginBox("udta"); 4336 writeGeoDataBox(); 4337 endBox(); 4338 } 4339 4340 void MPEG4Writer::writeHdlr(const char *handlerType) { 4341 beginBox("hdlr"); 4342 writeInt32(0); // Version, Flags 4343 writeInt32(0); // Predefined 4344 writeFourcc(handlerType); 4345 writeInt32(0); // Reserved[0] 4346 writeInt32(0); // Reserved[1] 4347 writeInt32(0); // Reserved[2] 4348 writeInt8(0); // Name (empty) 4349 endBox(); 4350 } 4351 4352 void MPEG4Writer::writeKeys() { 4353 size_t count = mMetaKeys->countEntries(); 4354 4355 beginBox("keys"); 4356 writeInt32(0); // Version, Flags 4357 writeInt32(count); // Entry_count 4358 for (size_t i = 0; i < count; i++) { 4359 AMessage::Type type; 4360 const char *key = mMetaKeys->getEntryNameAt(i, &type); 4361 size_t n = strlen(key); 4362 writeInt32(n + 8); 4363 writeFourcc("mdta"); 4364 write(key, n); // write without the \0 4365 } 4366 endBox(); 4367 } 4368 4369 void MPEG4Writer::writeIlst() { 4370 size_t count = mMetaKeys->countEntries(); 4371 4372 beginBox("ilst"); 4373 for (size_t i = 0; i < count; i++) { 4374 beginBox(i + 1); // key id (1-based) 4375 beginBox("data"); 4376 AMessage::Type type; 4377 const char *key = mMetaKeys->getEntryNameAt(i, &type); 4378 switch (type) { 4379 case AMessage::kTypeString: 4380 { 4381 AString val; 4382 CHECK(mMetaKeys->findString(key, &val)); 4383 writeInt32(1); // type = UTF8 4384 writeInt32(0); // default country/language 4385 write(val.c_str(), strlen(val.c_str())); // write without \0 4386 break; 4387 } 4388 4389 case AMessage::kTypeFloat: 4390 { 4391 float val; 4392 CHECK(mMetaKeys->findFloat(key, &val)); 4393 writeInt32(23); // type = float32 4394 writeInt32(0); // default country/language 4395 writeInt32(*reinterpret_cast<int32_t *>(&val)); 4396 break; 4397 } 4398 4399 case AMessage::kTypeInt32: 4400 { 4401 int32_t val; 4402 CHECK(mMetaKeys->findInt32(key, &val)); 4403 writeInt32(67); // type = signed int32 4404 writeInt32(0); // default country/language 4405 writeInt32(val); 4406 break; 4407 } 4408 4409 default: 4410 { 4411 ALOGW("Unsupported key type, writing 0 instead"); 4412 writeInt32(77); // type = unsigned int32 4413 writeInt32(0); // default country/language 4414 writeInt32(0); 4415 break; 4416 } 4417 } 4418 endBox(); // data 4419 endBox(); // key id 4420 } 4421 endBox(); // ilst 4422 } 4423 4424 void MPEG4Writer::writeMoovLevelMetaBox() { 4425 size_t count = mMetaKeys->countEntries(); 4426 if (count == 0) { 4427 return; 4428 } 4429 4430 beginBox("meta"); 4431 writeHdlr("mdta"); 4432 writeKeys(); 4433 writeIlst(); 4434 endBox(); 4435 } 4436 4437 void MPEG4Writer::writeIlocBox() { 4438 beginBox("iloc"); 4439 // Use version 1 to allow construction method 1 that refers to 4440 // data in idat box inside meta box. 4441 writeInt32(0x01000000); // Version = 1, Flags = 0 4442 writeInt16(0x4400); // offset_size = length_size = 4 4443 // base_offset_size = index_size = 0 4444 4445 // 16-bit item_count 4446 size_t itemCount = mItems.size(); 4447 if (itemCount > 65535) { 4448 ALOGW("Dropping excess items: itemCount %zu", itemCount); 4449 itemCount = 65535; 4450 } 4451 writeInt16((uint16_t)itemCount); 4452 4453 for (size_t i = 0; i < itemCount; i++) { 4454 writeInt16(mItems[i].itemId); 4455 bool isGrid = mItems[i].isGrid(); 4456 4457 writeInt16(isGrid ? 1 : 0); // construction_method 4458 writeInt16(0); // data_reference_index = 0 4459 writeInt16(1); // extent_count = 1 4460 4461 if (isGrid) { 4462 // offset into the 'idat' box 4463 writeInt32(mNumGrids++ * 8); 4464 writeInt32(8); 4465 } else { 4466 writeInt32(mItems[i].offset); 4467 writeInt32(mItems[i].size); 4468 } 4469 } 4470 endBox(); 4471 } 4472 4473 void MPEG4Writer::writeInfeBox( 4474 uint16_t itemId, const char *itemType, uint32_t flags) { 4475 beginBox("infe"); 4476 writeInt32(0x02000000 | flags); // Version = 2, Flags = 0 4477 writeInt16(itemId); 4478 writeInt16(0); //item_protection_index = 0 4479 writeFourcc(itemType); 4480 writeCString(""); // item_name 4481 endBox(); 4482 } 4483 4484 void MPEG4Writer::writeIinfBox() { 4485 beginBox("iinf"); 4486 writeInt32(0); // Version = 0, Flags = 0 4487 4488 // 16-bit item_count 4489 size_t itemCount = mItems.size(); 4490 if (itemCount > 65535) { 4491 ALOGW("Dropping excess items: itemCount %zu", itemCount); 4492 itemCount = 65535; 4493 } 4494 4495 writeInt16((uint16_t)itemCount); 4496 for (size_t i = 0; i < itemCount; i++) { 4497 writeInfeBox(mItems[i].itemId, mItems[i].itemType, 4498 (mItems[i].isImage() && mItems[i].isHidden) ? 1 : 0); 4499 } 4500 4501 endBox(); 4502 } 4503 4504 void MPEG4Writer::writeIdatBox() { 4505 beginBox("idat"); 4506 4507 for (size_t i = 0; i < mItems.size(); i++) { 4508 if (mItems[i].isGrid()) { 4509 writeInt8(0); // version 4510 // flags == 1 means 32-bit width,height 4511 int8_t flags = (mItems[i].width > 65535 || mItems[i].height > 65535); 4512 writeInt8(flags); 4513 writeInt8(mItems[i].rows - 1); 4514 writeInt8(mItems[i].cols - 1); 4515 if (flags) { 4516 writeInt32(mItems[i].width); 4517 writeInt32(mItems[i].height); 4518 } else { 4519 writeInt16((uint16_t)mItems[i].width); 4520 writeInt16((uint16_t)mItems[i].height); 4521 } 4522 } 4523 } 4524 4525 endBox(); 4526 } 4527 4528 void MPEG4Writer::writeIrefBox() { 4529 beginBox("iref"); 4530 writeInt32(0); // Version = 0, Flags = 0 4531 { 4532 for (size_t i = 0; i < mItems.size(); i++) { 4533 for (size_t r = 0; r < mItems[i].refsList.size(); r++) { 4534 const ItemRefs &refs = mItems[i].refsList[r]; 4535 beginBox(refs.key); 4536 writeInt16(mItems[i].itemId); 4537 size_t refCount = refs.value.size(); 4538 if (refCount > 65535) { 4539 ALOGW("too many entries in %s", refs.key); 4540 refCount = 65535; 4541 } 4542 writeInt16((uint16_t)refCount); 4543 for (size_t refIndex = 0; refIndex < refCount; refIndex++) { 4544 writeInt16(refs.value[refIndex]); 4545 } 4546 endBox(); 4547 } 4548 } 4549 } 4550 endBox(); 4551 } 4552 4553 void MPEG4Writer::writePitmBox() { 4554 beginBox("pitm"); 4555 writeInt32(0); // Version = 0, Flags = 0 4556 writeInt16(mPrimaryItemId); 4557 endBox(); 4558 } 4559 4560 void MPEG4Writer::writeIpcoBox() { 4561 beginBox("ipco"); 4562 size_t numProperties = mProperties.size(); 4563 if (numProperties > 32767) { 4564 ALOGW("Dropping excess properties: numProperties %zu", numProperties); 4565 numProperties = 32767; 4566 } 4567 for (size_t propIndex = 0; propIndex < numProperties; propIndex++) { 4568 switch (mProperties[propIndex].type) { 4569 case FOURCC('h', 'v', 'c', 'C'): 4570 { 4571 beginBox("hvcC"); 4572 sp<ABuffer> hvcc = mProperties[propIndex].hvcc; 4573 // Patch avcc's lengthSize field to match the number 4574 // of bytes we use to indicate the size of a nal unit. 4575 uint8_t *ptr = (uint8_t *)hvcc->data(); 4576 ptr[21] = (ptr[21] & 0xfc) | (useNalLengthFour() ? 3 : 1); 4577 write(hvcc->data(), hvcc->size()); 4578 endBox(); 4579 break; 4580 } 4581 case FOURCC('i', 's', 'p', 'e'): 4582 { 4583 beginBox("ispe"); 4584 writeInt32(0); // Version = 0, Flags = 0 4585 writeInt32(mProperties[propIndex].width); 4586 writeInt32(mProperties[propIndex].height); 4587 endBox(); 4588 break; 4589 } 4590 case FOURCC('i', 'r', 'o', 't'): 4591 { 4592 beginBox("irot"); 4593 writeInt8(mProperties[propIndex].rotation); 4594 endBox(); 4595 break; 4596 } 4597 default: 4598 ALOGW("Skipping unrecognized property: type 0x%08x", 4599 mProperties[propIndex].type); 4600 } 4601 } 4602 endBox(); 4603 } 4604 4605 void MPEG4Writer::writeIpmaBox() { 4606 beginBox("ipma"); 4607 uint32_t flags = (mProperties.size() > 127) ? 1 : 0; 4608 writeInt32(flags); // Version = 0 4609 4610 writeInt32(mAssociationEntryCount); 4611 for (size_t itemIndex = 0; itemIndex < mItems.size(); itemIndex++) { 4612 const Vector<uint16_t> &properties = mItems[itemIndex].properties; 4613 if (properties.empty()) { 4614 continue; 4615 } 4616 writeInt16(mItems[itemIndex].itemId); 4617 4618 size_t entryCount = properties.size(); 4619 if (entryCount > 255) { 4620 ALOGW("Dropping excess associations: entryCount %zu", entryCount); 4621 entryCount = 255; 4622 } 4623 writeInt8((uint8_t)entryCount); 4624 for (size_t propIndex = 0; propIndex < entryCount; propIndex++) { 4625 if (flags & 1) { 4626 writeInt16((1 << 15) | properties[propIndex]); 4627 } else { 4628 writeInt8((1 << 7) | properties[propIndex]); 4629 } 4630 } 4631 } 4632 endBox(); 4633 } 4634 4635 void MPEG4Writer::writeIprpBox() { 4636 beginBox("iprp"); 4637 writeIpcoBox(); 4638 writeIpmaBox(); 4639 endBox(); 4640 } 4641 4642 void MPEG4Writer::writeFileLevelMetaBox() { 4643 // patch up the mPrimaryItemId and count items with prop associations 4644 uint16_t firstVisibleItemId = 0; 4645 uint16_t firstImageItemId = 0; 4646 for (size_t index = 0; index < mItems.size(); index++) { 4647 if (!mItems[index].isImage()) continue; 4648 4649 if (mItems[index].isPrimary) { 4650 mPrimaryItemId = mItems[index].itemId; 4651 } 4652 if (!firstImageItemId) { 4653 firstImageItemId = mItems[index].itemId; 4654 } 4655 if (!firstVisibleItemId && !mItems[index].isHidden) { 4656 firstVisibleItemId = mItems[index].itemId; 4657 } 4658 if (!mItems[index].properties.empty()) { 4659 mAssociationEntryCount++; 4660 } 4661 } 4662 4663 if (!firstImageItemId) { 4664 ALOGE("no valid image was found"); 4665 return; 4666 } 4667 4668 if (mPrimaryItemId == 0) { 4669 if (firstVisibleItemId > 0) { 4670 ALOGW("didn't find primary, using first visible image"); 4671 mPrimaryItemId = firstVisibleItemId; 4672 } else { 4673 ALOGW("no primary and no visible item, using first image"); 4674 mPrimaryItemId = firstImageItemId; 4675 } 4676 } 4677 4678 for (List<Track *>::iterator it = mTracks.begin(); 4679 it != mTracks.end(); ++it) { 4680 if ((*it)->isHeic()) { 4681 (*it)->flushItemRefs(); 4682 } 4683 } 4684 4685 beginBox("meta"); 4686 writeInt32(0); // Version = 0, Flags = 0 4687 writeHdlr("pict"); 4688 writeIlocBox(); 4689 writeIinfBox(); 4690 writePitmBox(); 4691 writeIprpBox(); 4692 if (mNumGrids > 0) { 4693 writeIdatBox(); 4694 } 4695 if (mHasRefs) { 4696 writeIrefBox(); 4697 } 4698 endBox(); 4699 } 4700 4701 uint16_t MPEG4Writer::addProperty_l(const ItemProperty &prop) { 4702 char typeStr[5]; 4703 MakeFourCCString(prop.type, typeStr); 4704 ALOGV("addProperty_l: %s", typeStr); 4705 4706 mProperties.push_back(prop); 4707 4708 // returning 1-based property index 4709 return mProperties.size(); 4710 } 4711 4712 uint16_t MPEG4Writer::addItem_l(const ItemInfo &info) { 4713 ALOGV("addItem_l: type %s, offset %u, size %u", 4714 info.itemType, info.offset, info.size); 4715 4716 size_t index = mItems.size(); 4717 mItems.push_back(info); 4718 4719 // make the item id start at kItemIdBase 4720 mItems.editItemAt(index).itemId = index + kItemIdBase; 4721 4722 #if (LOG_NDEBUG==0) 4723 if (!info.properties.empty()) { 4724 AString str; 4725 for (size_t i = 0; i < info.properties.size(); i++) { 4726 if (i > 0) { 4727 str.append(", "); 4728 } 4729 str.append(info.properties[i]); 4730 } 4731 ALOGV("addItem_l: id %d, properties: %s", mItems[index].itemId, str.c_str()); 4732 } 4733 #endif // (LOG_NDEBUG==0) 4734 4735 return mItems[index].itemId; 4736 } 4737 4738 void MPEG4Writer::addRefs_l(uint16_t itemId, const ItemRefs &refs) { 4739 if (refs.value.empty()) { 4740 return; 4741 } 4742 if (itemId < kItemIdBase) { 4743 ALOGW("itemId shouldn't be smaller than kItemIdBase"); 4744 return; 4745 } 4746 4747 size_t index = itemId - kItemIdBase; 4748 mItems.editItemAt(index).refsList.push_back(refs); 4749 mHasRefs = true; 4750 } 4751 4752 /* 4753 * Geodata is stored according to ISO-6709 standard. 4754 */ 4755 void MPEG4Writer::writeGeoDataBox() { 4756 beginBox("\xA9xyz"); 4757 /* 4758 * For historical reasons, any user data start 4759 * with "\0xA9", must be followed by its assoicated 4760 * language code. 4761 * 0x0012: text string length 4762 * 0x15c7: lang (locale) code: en 4763 */ 4764 writeInt32(0x001215c7); 4765 writeLatitude(mLatitudex10000); 4766 writeLongitude(mLongitudex10000); 4767 writeInt8(0x2F); 4768 endBox(); 4769 } 4770 4771 } // namespace android 4772