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