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