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