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