Home | History | Annotate | Download | only in libstagefright
      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 &paramSets);
    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, &paramSetLen);
   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, &paramSetLen);
   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 &paramSets) {
   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, &timestampUs));
   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