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