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