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