MPEG4Writer.cpp revision 3d53e1c0dd7760f3ca58ff75e74cd7fcf4bc08cc
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        ALOGE("failed parsing codec specific data");
2265        return ERROR_MALFORMED;
2266    }
2267
2268    mCodecSpecificData = malloc(mCodecSpecificDataSize);
2269    if (mCodecSpecificData == NULL) {
2270        mCodecSpecificDataSize = 0;
2271        ALOGE("Failed allocating codec specific data");
2272        return NO_MEMORY;
2273    }
2274    status_t err = paramSets.makeHvcc((uint8_t *)mCodecSpecificData,
2275            &mCodecSpecificDataSize, mOwner->useNalLengthFour() ? 4 : 2);
2276    if (err != OK) {
2277        ALOGE("failed constructing HVCC atom");
2278        return err;
2279    }
2280
2281    return OK;
2282}
2283
2284/*
2285 * Updates the drift time from the audio track so that
2286 * the video track can get the updated drift time information
2287 * from the file writer. The fluctuation of the drift time of the audio
2288 * encoding path is smoothed out with a simple filter by giving a larger
2289 * weight to more recently drift time. The filter coefficients, 0.5 and 0.5,
2290 * are heuristically determined.
2291 */
2292void MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) {
2293    int64_t driftTimeUs = 0;
2294    if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) {
2295        int64_t prevDriftTimeUs = mOwner->getDriftTimeUs();
2296        int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1;
2297        mOwner->setDriftTimeUs(timeUs);
2298    }
2299}
2300
2301status_t MPEG4Writer::Track::threadEntry() {
2302    int32_t count = 0;
2303    const int64_t interleaveDurationUs = mOwner->interleaveDuration();
2304    const bool hasMultipleTracks = (mOwner->numTracks() > 1);
2305    int64_t chunkTimestampUs = 0;
2306    int32_t nChunks = 0;
2307    int32_t nActualFrames = 0;        // frames containing non-CSD data (non-0 length)
2308    int32_t nZeroLengthFrames = 0;
2309    int64_t lastTimestampUs = 0;      // Previous sample time stamp
2310    int64_t lastDurationUs = 0;       // Between the previous two samples
2311    int64_t currDurationTicks = 0;    // Timescale based ticks
2312    int64_t lastDurationTicks = 0;    // Timescale based ticks
2313    int32_t sampleCount = 1;          // Sample count in the current stts table entry
2314    uint32_t previousSampleSize = 0;  // Size of the previous sample
2315    int64_t previousPausedDurationUs = 0;
2316    int64_t timestampUs = 0;
2317    int64_t cttsOffsetTimeUs = 0;
2318    int64_t currCttsOffsetTimeTicks = 0;   // Timescale based ticks
2319    int64_t lastCttsOffsetTimeTicks = -1;  // Timescale based ticks
2320    int32_t cttsSampleCount = 0;           // Sample count in the current ctts table entry
2321    uint32_t lastSamplesPerChunk = 0;
2322
2323    if (mIsAudio) {
2324        prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0);
2325    } else {
2326        prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0);
2327    }
2328
2329    if (mOwner->isRealTimeRecording()) {
2330        androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
2331    }
2332
2333    sp<MetaData> meta_data;
2334
2335    status_t err = OK;
2336    MediaBuffer *buffer;
2337    const char *trackName = mIsAudio ? "Audio" : "Video";
2338    while (!mDone && (err = mSource->read(&buffer)) == OK) {
2339        if (buffer->range_length() == 0) {
2340            buffer->release();
2341            buffer = NULL;
2342            ++nZeroLengthFrames;
2343            continue;
2344        }
2345
2346        // If the codec specific data has not been received yet, delay pause.
2347        // After the codec specific data is received, discard what we received
2348        // when the track is to be paused.
2349        if (mPaused && !mResumed) {
2350            buffer->release();
2351            buffer = NULL;
2352            continue;
2353        }
2354
2355        ++count;
2356
2357        int32_t isCodecConfig;
2358        if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig)
2359                && isCodecConfig) {
2360            // if config format (at track addition) already had CSD, keep that
2361            // UNLESS we have not received any frames yet.
2362            // TODO: for now the entire CSD has to come in one frame for encoders, even though
2363            // they need to be spread out for decoders.
2364            if (mGotAllCodecSpecificData && nActualFrames > 0) {
2365                ALOGI("ignoring additional CSD for video track after first frame");
2366            } else {
2367                mMeta = mSource->getFormat(); // get output format after format change
2368
2369                if (mIsAvc) {
2370                    status_t err = makeAVCCodecSpecificData(
2371                            (const uint8_t *)buffer->data()
2372                                + buffer->range_offset(),
2373                            buffer->range_length());
2374                    CHECK_EQ((status_t)OK, err);
2375                } else if (mIsHevc) {
2376                    status_t err = makeHEVCCodecSpecificData(
2377                            (const uint8_t *)buffer->data()
2378                                + buffer->range_offset(),
2379                            buffer->range_length());
2380                    CHECK_EQ((status_t)OK, err);
2381                } else if (mIsMPEG4) {
2382                    copyCodecSpecificData((const uint8_t *)buffer->data() + buffer->range_offset(),
2383                            buffer->range_length());
2384                }
2385            }
2386
2387            buffer->release();
2388            buffer = NULL;
2389
2390            mGotAllCodecSpecificData = true;
2391            continue;
2392        }
2393
2394        ++nActualFrames;
2395
2396        // Make a deep copy of the MediaBuffer and Metadata and release
2397        // the original as soon as we can
2398        MediaBuffer *copy = new MediaBuffer(buffer->range_length());
2399        memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(),
2400                buffer->range_length());
2401        copy->set_range(0, buffer->range_length());
2402        meta_data = new MetaData(*buffer->meta_data().get());
2403        buffer->release();
2404        buffer = NULL;
2405
2406        if (mIsAvc || mIsHevc) StripStartcode(copy);
2407
2408        size_t sampleSize = copy->range_length();
2409        if (mIsAvc || mIsHevc) {
2410            if (mOwner->useNalLengthFour()) {
2411                sampleSize += 4;
2412            } else {
2413                sampleSize += 2;
2414            }
2415        }
2416
2417        // Max file size or duration handling
2418        mMdatSizeBytes += sampleSize;
2419        updateTrackSizeEstimate();
2420
2421        if (mOwner->exceedsFileSizeLimit()) {
2422            ALOGW("Recorded file size exceeds limit %" PRId64 "bytes",
2423                    mOwner->mMaxFileSizeLimitBytes);
2424            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
2425            break;
2426        }
2427        if (mOwner->exceedsFileDurationLimit()) {
2428            ALOGW("Recorded file duration exceeds limit %" PRId64 "microseconds",
2429                    mOwner->mMaxFileDurationLimitUs);
2430            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
2431            break;
2432        }
2433
2434
2435        int32_t isSync = false;
2436        meta_data->findInt32(kKeyIsSyncFrame, &isSync);
2437        CHECK(meta_data->findInt64(kKeyTime, &timestampUs));
2438
2439////////////////////////////////////////////////////////////////////////////////
2440        if (mStszTableEntries->count() == 0) {
2441            mFirstSampleTimeRealUs = systemTime() / 1000;
2442            mStartTimestampUs = timestampUs;
2443            mOwner->setStartTimestampUs(mStartTimestampUs);
2444            previousPausedDurationUs = mStartTimestampUs;
2445        }
2446
2447        if (mResumed) {
2448            int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs;
2449            if (WARN_UNLESS(durExcludingEarlierPausesUs >= 0ll, "for %s track", trackName)) {
2450                copy->release();
2451                return ERROR_MALFORMED;
2452            }
2453
2454            int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs;
2455            if (WARN_UNLESS(pausedDurationUs >= lastDurationUs, "for %s track", trackName)) {
2456                copy->release();
2457                return ERROR_MALFORMED;
2458            }
2459
2460            previousPausedDurationUs += pausedDurationUs - lastDurationUs;
2461            mResumed = false;
2462        }
2463
2464        timestampUs -= previousPausedDurationUs;
2465        if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) {
2466            copy->release();
2467            return ERROR_MALFORMED;
2468        }
2469
2470        if (!mIsAudio) {
2471            /*
2472             * Composition time: timestampUs
2473             * Decoding time: decodingTimeUs
2474             * Composition time offset = composition time - decoding time
2475             */
2476            int64_t decodingTimeUs;
2477            CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs));
2478            decodingTimeUs -= previousPausedDurationUs;
2479            cttsOffsetTimeUs =
2480                    timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs;
2481            if (WARN_UNLESS(cttsOffsetTimeUs >= 0ll, "for %s track", trackName)) {
2482                copy->release();
2483                return ERROR_MALFORMED;
2484            }
2485
2486            timestampUs = decodingTimeUs;
2487            ALOGV("decoding time: %" PRId64 " and ctts offset time: %" PRId64,
2488                timestampUs, cttsOffsetTimeUs);
2489
2490            // Update ctts box table if necessary
2491            currCttsOffsetTimeTicks =
2492                    (cttsOffsetTimeUs * mTimeScale + 500000LL) / 1000000LL;
2493            if (WARN_UNLESS(currCttsOffsetTimeTicks <= 0x0FFFFFFFFLL, "for %s track", trackName)) {
2494                copy->release();
2495                return ERROR_MALFORMED;
2496            }
2497
2498            if (mStszTableEntries->count() == 0) {
2499                // Force the first ctts table entry to have one single entry
2500                // so that we can do adjustment for the initial track start
2501                // time offset easily in writeCttsBox().
2502                lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks;
2503                addOneCttsTableEntry(1, currCttsOffsetTimeTicks);
2504                cttsSampleCount = 0;      // No sample in ctts box is pending
2505            } else {
2506                if (currCttsOffsetTimeTicks != lastCttsOffsetTimeTicks) {
2507                    addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
2508                    lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks;
2509                    cttsSampleCount = 1;  // One sample in ctts box is pending
2510                } else {
2511                    ++cttsSampleCount;
2512                }
2513            }
2514
2515            // Update ctts time offset range
2516            if (mStszTableEntries->count() == 0) {
2517                mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2518                mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2519            } else {
2520                if (currCttsOffsetTimeTicks > mMaxCttsOffsetTimeUs) {
2521                    mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2522                } else if (currCttsOffsetTimeTicks < mMinCttsOffsetTimeUs) {
2523                    mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2524                }
2525            }
2526
2527        }
2528
2529        if (mOwner->isRealTimeRecording()) {
2530            if (mIsAudio) {
2531                updateDriftTime(meta_data);
2532            }
2533        }
2534
2535        if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) {
2536            copy->release();
2537            return ERROR_MALFORMED;
2538        }
2539
2540        ALOGV("%s media time stamp: %" PRId64 " and previous paused duration %" PRId64,
2541                trackName, timestampUs, previousPausedDurationUs);
2542        if (timestampUs > mTrackDurationUs) {
2543            mTrackDurationUs = timestampUs;
2544        }
2545
2546        // We need to use the time scale based ticks, rather than the
2547        // timestamp itself to determine whether we have to use a new
2548        // stts entry, since we may have rounding errors.
2549        // The calculation is intended to reduce the accumulated
2550        // rounding errors.
2551        currDurationTicks =
2552            ((timestampUs * mTimeScale + 500000LL) / 1000000LL -
2553                (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL);
2554        if (currDurationTicks < 0ll) {
2555            ALOGE("do not support out of order frames (timestamp: %lld < last: %lld for %s track",
2556                    (long long)timestampUs, (long long)lastTimestampUs, trackName);
2557            copy->release();
2558            mSource->stop();
2559            return UNKNOWN_ERROR;
2560        }
2561
2562        // if the duration is different for this sample, see if it is close enough to the previous
2563        // duration that we can fudge it and use the same value, to avoid filling the stts table
2564        // with lots of near-identical entries.
2565        // "close enough" here means that the current duration needs to be adjusted by less
2566        // than 0.1 milliseconds
2567        if (lastDurationTicks && (currDurationTicks != lastDurationTicks)) {
2568            int64_t deltaUs = ((lastDurationTicks - currDurationTicks) * 1000000LL
2569                    + (mTimeScale / 2)) / mTimeScale;
2570            if (deltaUs > -100 && deltaUs < 100) {
2571                // use previous ticks, and adjust timestamp as if it was actually that number
2572                // of ticks
2573                currDurationTicks = lastDurationTicks;
2574                timestampUs += deltaUs;
2575            }
2576        }
2577
2578        mStszTableEntries->add(htonl(sampleSize));
2579        if (mStszTableEntries->count() > 2) {
2580
2581            // Force the first sample to have its own stts entry so that
2582            // we can adjust its value later to maintain the A/V sync.
2583            if (mStszTableEntries->count() == 3 || currDurationTicks != lastDurationTicks) {
2584                addOneSttsTableEntry(sampleCount, lastDurationTicks);
2585                sampleCount = 1;
2586            } else {
2587                ++sampleCount;
2588            }
2589
2590        }
2591        if (mSamplesHaveSameSize) {
2592            if (mStszTableEntries->count() >= 2 && previousSampleSize != sampleSize) {
2593                mSamplesHaveSameSize = false;
2594            }
2595            previousSampleSize = sampleSize;
2596        }
2597        ALOGV("%s timestampUs/lastTimestampUs: %" PRId64 "/%" PRId64,
2598                trackName, timestampUs, lastTimestampUs);
2599        lastDurationUs = timestampUs - lastTimestampUs;
2600        lastDurationTicks = currDurationTicks;
2601        lastTimestampUs = timestampUs;
2602
2603        if (isSync != 0) {
2604            addOneStssTableEntry(mStszTableEntries->count());
2605        }
2606
2607        if (mTrackingProgressStatus) {
2608            if (mPreviousTrackTimeUs <= 0) {
2609                mPreviousTrackTimeUs = mStartTimestampUs;
2610            }
2611            trackProgressStatus(timestampUs);
2612        }
2613        if (!hasMultipleTracks) {
2614            off64_t offset = (mIsAvc || mIsHevc) ? mOwner->addLengthPrefixedSample_l(copy)
2615                                 : mOwner->addSample_l(copy);
2616
2617            uint32_t count = (mOwner->use32BitFileOffset()
2618                        ? mStcoTableEntries->count()
2619                        : mCo64TableEntries->count());
2620
2621            if (count == 0) {
2622                addChunkOffset(offset);
2623            }
2624            copy->release();
2625            copy = NULL;
2626            continue;
2627        }
2628
2629        mChunkSamples.push_back(copy);
2630        if (interleaveDurationUs == 0) {
2631            addOneStscTableEntry(++nChunks, 1);
2632            bufferChunk(timestampUs);
2633        } else {
2634            if (chunkTimestampUs == 0) {
2635                chunkTimestampUs = timestampUs;
2636            } else {
2637                int64_t chunkDurationUs = timestampUs - chunkTimestampUs;
2638                if (chunkDurationUs > interleaveDurationUs) {
2639                    if (chunkDurationUs > mMaxChunkDurationUs) {
2640                        mMaxChunkDurationUs = chunkDurationUs;
2641                    }
2642                    ++nChunks;
2643                    if (nChunks == 1 ||  // First chunk
2644                        lastSamplesPerChunk != mChunkSamples.size()) {
2645                        lastSamplesPerChunk = mChunkSamples.size();
2646                        addOneStscTableEntry(nChunks, lastSamplesPerChunk);
2647                    }
2648                    bufferChunk(timestampUs);
2649                    chunkTimestampUs = timestampUs;
2650                }
2651            }
2652        }
2653
2654    }
2655
2656    if (isTrackMalFormed()) {
2657        err = ERROR_MALFORMED;
2658    }
2659
2660    mOwner->trackProgressStatus(mTrackId, -1, err);
2661
2662    // Last chunk
2663    if (!hasMultipleTracks) {
2664        addOneStscTableEntry(1, mStszTableEntries->count());
2665    } else if (!mChunkSamples.empty()) {
2666        addOneStscTableEntry(++nChunks, mChunkSamples.size());
2667        bufferChunk(timestampUs);
2668    }
2669
2670    // We don't really know how long the last frame lasts, since
2671    // there is no frame time after it, just repeat the previous
2672    // frame's duration.
2673    if (mStszTableEntries->count() == 1) {
2674        lastDurationUs = 0;  // A single sample's duration
2675        lastDurationTicks = 0;
2676    } else {
2677        ++sampleCount;  // Count for the last sample
2678    }
2679
2680    if (mStszTableEntries->count() <= 2) {
2681        addOneSttsTableEntry(1, lastDurationTicks);
2682        if (sampleCount - 1 > 0) {
2683            addOneSttsTableEntry(sampleCount - 1, lastDurationTicks);
2684        }
2685    } else {
2686        addOneSttsTableEntry(sampleCount, lastDurationTicks);
2687    }
2688
2689    // The last ctts box may not have been written yet, and this
2690    // is to make sure that we write out the last ctts box.
2691    if (currCttsOffsetTimeTicks == lastCttsOffsetTimeTicks) {
2692        if (cttsSampleCount > 0) {
2693            addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
2694        }
2695    }
2696
2697    mTrackDurationUs += lastDurationUs;
2698    mReachedEOS = true;
2699
2700    sendTrackSummary(hasMultipleTracks);
2701
2702    ALOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s",
2703            count, nZeroLengthFrames, mStszTableEntries->count(), trackName);
2704    if (mIsAudio) {
2705        ALOGI("Audio track drift time: %" PRId64 " us", mOwner->getDriftTimeUs());
2706    }
2707
2708    if (err == ERROR_END_OF_STREAM) {
2709        return OK;
2710    }
2711    return err;
2712}
2713
2714bool MPEG4Writer::Track::isTrackMalFormed() const {
2715    if (mStszTableEntries->count() == 0) {                      // no samples written
2716        ALOGE("The number of recorded samples is 0");
2717        return true;
2718    }
2719
2720    if (!mIsAudio && mStssTableEntries->count() == 0) {  // no sync frames for video
2721        ALOGE("There are no sync frames for video track");
2722        return true;
2723    }
2724
2725    if (OK != checkCodecSpecificData()) {         // no codec specific data
2726        return true;
2727    }
2728
2729    return false;
2730}
2731
2732void MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) {
2733
2734    // Send track summary only if test mode is enabled.
2735    if (!isTestModeEnabled()) {
2736        return;
2737    }
2738
2739    int trackNum = (mTrackId << 28);
2740
2741    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
2742                    trackNum | MEDIA_RECORDER_TRACK_INFO_TYPE,
2743                    mIsAudio? 0: 1);
2744
2745    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
2746                    trackNum | MEDIA_RECORDER_TRACK_INFO_DURATION_MS,
2747                    mTrackDurationUs / 1000);
2748
2749    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
2750                    trackNum | MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES,
2751                    mStszTableEntries->count());
2752
2753    {
2754        // The system delay time excluding the requested initial delay that
2755        // is used to eliminate the recording sound.
2756        int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL;
2757        if (startTimeOffsetUs < 0) {  // Start time offset was not set
2758            startTimeOffsetUs = kInitialDelayTimeUs;
2759        }
2760        int64_t initialDelayUs =
2761            mFirstSampleTimeRealUs - mStartTimeRealUs - startTimeOffsetUs;
2762
2763        mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
2764                    trackNum | MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS,
2765                    (initialDelayUs) / 1000);
2766    }
2767
2768    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
2769                    trackNum | MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES,
2770                    mMdatSizeBytes / 1024);
2771
2772    if (hasMultipleTracks) {
2773        mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
2774                    trackNum | MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS,
2775                    mMaxChunkDurationUs / 1000);
2776
2777        int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
2778        if (mStartTimestampUs != moovStartTimeUs) {
2779            int64_t startTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
2780            mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
2781                    trackNum | MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS,
2782                    startTimeOffsetUs / 1000);
2783        }
2784    }
2785}
2786
2787void MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) {
2788    ALOGV("trackProgressStatus: %" PRId64 " us", timeUs);
2789
2790    if (mTrackEveryTimeDurationUs > 0 &&
2791        timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) {
2792        ALOGV("Fire time tracking progress status at %" PRId64 " us", timeUs);
2793        mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err);
2794        mPreviousTrackTimeUs = timeUs;
2795    }
2796}
2797
2798void MPEG4Writer::trackProgressStatus(
2799        size_t trackId, int64_t timeUs, status_t err) {
2800    Mutex::Autolock lock(mLock);
2801    int32_t trackNum = (trackId << 28);
2802
2803    // Error notification
2804    // Do not consider ERROR_END_OF_STREAM an error
2805    if (err != OK && err != ERROR_END_OF_STREAM) {
2806        notify(MEDIA_RECORDER_TRACK_EVENT_ERROR,
2807               trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL,
2808               err);
2809        return;
2810    }
2811
2812    if (timeUs == -1) {
2813        // Send completion notification
2814        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
2815               trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS,
2816               err);
2817    } else {
2818        // Send progress status
2819        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
2820               trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME,
2821               timeUs / 1000);
2822    }
2823}
2824
2825void MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) {
2826    ALOGV("setDriftTimeUs: %" PRId64 " us", driftTimeUs);
2827    Mutex::Autolock autolock(mLock);
2828    mDriftTimeUs = driftTimeUs;
2829}
2830
2831int64_t MPEG4Writer::getDriftTimeUs() {
2832    ALOGV("getDriftTimeUs: %" PRId64 " us", mDriftTimeUs);
2833    Mutex::Autolock autolock(mLock);
2834    return mDriftTimeUs;
2835}
2836
2837bool MPEG4Writer::isRealTimeRecording() const {
2838    return mIsRealTimeRecording;
2839}
2840
2841bool MPEG4Writer::useNalLengthFour() {
2842    return mUse4ByteNalLength;
2843}
2844
2845void MPEG4Writer::Track::bufferChunk(int64_t timestampUs) {
2846    ALOGV("bufferChunk");
2847
2848    Chunk chunk(this, timestampUs, mChunkSamples);
2849    mOwner->bufferChunk(chunk);
2850    mChunkSamples.clear();
2851}
2852
2853int64_t MPEG4Writer::Track::getDurationUs() const {
2854    return mTrackDurationUs;
2855}
2856
2857int64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const {
2858    return mEstimatedTrackSizeBytes;
2859}
2860
2861status_t MPEG4Writer::Track::checkCodecSpecificData() const {
2862    const char *mime;
2863    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
2864    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) ||
2865        !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) ||
2866        !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime) ||
2867        !strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) {
2868        if (!mCodecSpecificData ||
2869            mCodecSpecificDataSize <= 0) {
2870            ALOGE("Missing codec specific data");
2871            return ERROR_MALFORMED;
2872        }
2873    } else {
2874        if (mCodecSpecificData ||
2875            mCodecSpecificDataSize > 0) {
2876            ALOGE("Unexepected codec specific data found");
2877            return ERROR_MALFORMED;
2878        }
2879    }
2880    return OK;
2881}
2882
2883void MPEG4Writer::Track::writeTrackHeader(bool use32BitOffset) {
2884
2885    ALOGV("%s track time scale: %d",
2886        mIsAudio? "Audio": "Video", mTimeScale);
2887
2888    uint32_t now = getMpeg4Time();
2889    mOwner->beginBox("trak");
2890        writeTkhdBox(now);
2891        mOwner->beginBox("mdia");
2892            writeMdhdBox(now);
2893            writeHdlrBox();
2894            mOwner->beginBox("minf");
2895                if (mIsAudio) {
2896                    writeSmhdBox();
2897                } else {
2898                    writeVmhdBox();
2899                }
2900                writeDinfBox();
2901                writeStblBox(use32BitOffset);
2902            mOwner->endBox();  // minf
2903        mOwner->endBox();  // mdia
2904    mOwner->endBox();  // trak
2905}
2906
2907void MPEG4Writer::Track::writeStblBox(bool use32BitOffset) {
2908    mOwner->beginBox("stbl");
2909    mOwner->beginBox("stsd");
2910    mOwner->writeInt32(0);               // version=0, flags=0
2911    mOwner->writeInt32(1);               // entry count
2912    if (mIsAudio) {
2913        writeAudioFourCCBox();
2914    } else {
2915        writeVideoFourCCBox();
2916    }
2917    mOwner->endBox();  // stsd
2918    writeSttsBox();
2919    writeCttsBox();
2920    if (!mIsAudio) {
2921        writeStssBox();
2922    }
2923    writeStszBox();
2924    writeStscBox();
2925    writeStcoBox(use32BitOffset);
2926    mOwner->endBox();  // stbl
2927}
2928
2929void MPEG4Writer::Track::writeVideoFourCCBox() {
2930    const char *mime;
2931    bool success = mMeta->findCString(kKeyMIMEType, &mime);
2932    CHECK(success);
2933    const char *fourcc = getFourCCForMime(mime);
2934    if (fourcc == NULL) {
2935        ALOGE("Unknown mime type '%s'.", mime);
2936        CHECK(!"should not be here, unknown mime type.");
2937    }
2938
2939    mOwner->beginBox(fourcc);        // video format
2940    mOwner->writeInt32(0);           // reserved
2941    mOwner->writeInt16(0);           // reserved
2942    mOwner->writeInt16(1);           // data ref index
2943    mOwner->writeInt16(0);           // predefined
2944    mOwner->writeInt16(0);           // reserved
2945    mOwner->writeInt32(0);           // predefined
2946    mOwner->writeInt32(0);           // predefined
2947    mOwner->writeInt32(0);           // predefined
2948
2949    int32_t width, height;
2950    success = mMeta->findInt32(kKeyWidth, &width);
2951    success = success && mMeta->findInt32(kKeyHeight, &height);
2952    CHECK(success);
2953
2954    mOwner->writeInt16(width);
2955    mOwner->writeInt16(height);
2956    mOwner->writeInt32(0x480000);    // horiz resolution
2957    mOwner->writeInt32(0x480000);    // vert resolution
2958    mOwner->writeInt32(0);           // reserved
2959    mOwner->writeInt16(1);           // frame count
2960    mOwner->writeInt8(0);            // compressor string length
2961    mOwner->write("                               ", 31);
2962    mOwner->writeInt16(0x18);        // depth
2963    mOwner->writeInt16(-1);          // predefined
2964
2965    CHECK_LT(23 + mCodecSpecificDataSize, 128);
2966
2967    if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
2968        writeMp4vEsdsBox();
2969    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
2970        writeD263Box();
2971    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
2972        writeAvccBox();
2973    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) {
2974        writeHvccBox();
2975    }
2976
2977    writePaspBox();
2978    writeColrBox();
2979    mOwner->endBox();  // mp4v, s263 or avc1
2980}
2981
2982void MPEG4Writer::Track::writeColrBox() {
2983    ColorAspects aspects;
2984    memset(&aspects, 0, sizeof(aspects));
2985    // TRICKY: using | instead of || because we want to execute all findInt32-s
2986    if (mMeta->findInt32(kKeyColorPrimaries, (int32_t*)&aspects.mPrimaries)
2987            | mMeta->findInt32(kKeyTransferFunction, (int32_t*)&aspects.mTransfer)
2988            | mMeta->findInt32(kKeyColorMatrix, (int32_t*)&aspects.mMatrixCoeffs)
2989            | mMeta->findInt32(kKeyColorRange, (int32_t*)&aspects.mRange)) {
2990        int32_t primaries, transfer, coeffs;
2991        bool fullRange;
2992        ColorUtils::convertCodecColorAspectsToIsoAspects(
2993                aspects, &primaries, &transfer, &coeffs, &fullRange);
2994        mOwner->beginBox("colr");
2995        mOwner->writeFourcc("nclx");
2996        mOwner->writeInt16(primaries);
2997        mOwner->writeInt16(transfer);
2998        mOwner->writeInt16(coeffs);
2999        mOwner->writeInt8(fullRange ? 128 : 0);
3000        mOwner->endBox(); // colr
3001    }
3002}
3003
3004void MPEG4Writer::Track::writeAudioFourCCBox() {
3005    const char *mime;
3006    bool success = mMeta->findCString(kKeyMIMEType, &mime);
3007    CHECK(success);
3008    const char *fourcc = getFourCCForMime(mime);
3009    if (fourcc == NULL) {
3010        ALOGE("Unknown mime type '%s'.", mime);
3011        CHECK(!"should not be here, unknown mime type.");
3012    }
3013
3014    mOwner->beginBox(fourcc);        // audio format
3015    mOwner->writeInt32(0);           // reserved
3016    mOwner->writeInt16(0);           // reserved
3017    mOwner->writeInt16(0x1);         // data ref index
3018    mOwner->writeInt32(0);           // reserved
3019    mOwner->writeInt32(0);           // reserved
3020    int32_t nChannels;
3021    CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels));
3022    mOwner->writeInt16(nChannels);   // channel count
3023    mOwner->writeInt16(16);          // sample size
3024    mOwner->writeInt16(0);           // predefined
3025    mOwner->writeInt16(0);           // reserved
3026
3027    int32_t samplerate;
3028    success = mMeta->findInt32(kKeySampleRate, &samplerate);
3029    CHECK(success);
3030    mOwner->writeInt32(samplerate << 16);
3031    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
3032        writeMp4aEsdsBox();
3033    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) ||
3034               !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
3035        writeDamrBox();
3036    }
3037    mOwner->endBox();
3038}
3039
3040void MPEG4Writer::Track::writeMp4aEsdsBox() {
3041    mOwner->beginBox("esds");
3042    CHECK(mCodecSpecificData);
3043    CHECK_GT(mCodecSpecificDataSize, 0);
3044
3045    // Make sure all sizes encode to a single byte.
3046    CHECK_LT(mCodecSpecificDataSize + 23, 128);
3047
3048    mOwner->writeInt32(0);     // version=0, flags=0
3049    mOwner->writeInt8(0x03);   // ES_DescrTag
3050    mOwner->writeInt8(23 + mCodecSpecificDataSize);
3051    mOwner->writeInt16(0x0000);// ES_ID
3052    mOwner->writeInt8(0x00);
3053
3054    mOwner->writeInt8(0x04);   // DecoderConfigDescrTag
3055    mOwner->writeInt8(15 + mCodecSpecificDataSize);
3056    mOwner->writeInt8(0x40);   // objectTypeIndication ISO/IEC 14492-2
3057    mOwner->writeInt8(0x15);   // streamType AudioStream
3058
3059    mOwner->writeInt16(0x03);  // XXX
3060    mOwner->writeInt8(0x00);   // buffer size 24-bit
3061    int32_t bitRate;
3062    bool success = mMeta->findInt32(kKeyBitRate, &bitRate);
3063    mOwner->writeInt32(success ? bitRate : 96000); // max bit rate
3064    mOwner->writeInt32(success ? bitRate : 96000); // avg bit rate
3065
3066    mOwner->writeInt8(0x05);   // DecoderSpecificInfoTag
3067    mOwner->writeInt8(mCodecSpecificDataSize);
3068    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
3069
3070    static const uint8_t kData2[] = {
3071        0x06,  // SLConfigDescriptorTag
3072        0x01,
3073        0x02
3074    };
3075    mOwner->write(kData2, sizeof(kData2));
3076
3077    mOwner->endBox();  // esds
3078}
3079
3080void MPEG4Writer::Track::writeMp4vEsdsBox() {
3081    CHECK(mCodecSpecificData);
3082    CHECK_GT(mCodecSpecificDataSize, 0);
3083    mOwner->beginBox("esds");
3084
3085    mOwner->writeInt32(0);    // version=0, flags=0
3086
3087    mOwner->writeInt8(0x03);  // ES_DescrTag
3088    mOwner->writeInt8(23 + mCodecSpecificDataSize);
3089    mOwner->writeInt16(0x0000);  // ES_ID
3090    mOwner->writeInt8(0x1f);
3091
3092    mOwner->writeInt8(0x04);  // DecoderConfigDescrTag
3093    mOwner->writeInt8(15 + mCodecSpecificDataSize);
3094    mOwner->writeInt8(0x20);  // objectTypeIndication ISO/IEC 14492-2
3095    mOwner->writeInt8(0x11);  // streamType VisualStream
3096
3097    static const uint8_t kData[] = {
3098        0x01, 0x77, 0x00,
3099        0x00, 0x03, 0xe8, 0x00,
3100        0x00, 0x03, 0xe8, 0x00
3101    };
3102    mOwner->write(kData, sizeof(kData));
3103
3104    mOwner->writeInt8(0x05);  // DecoderSpecificInfoTag
3105
3106    mOwner->writeInt8(mCodecSpecificDataSize);
3107    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
3108
3109    static const uint8_t kData2[] = {
3110        0x06,  // SLConfigDescriptorTag
3111        0x01,
3112        0x02
3113    };
3114    mOwner->write(kData2, sizeof(kData2));
3115
3116    mOwner->endBox();  // esds
3117}
3118
3119void MPEG4Writer::Track::writeTkhdBox(uint32_t now) {
3120    mOwner->beginBox("tkhd");
3121    // Flags = 7 to indicate that the track is enabled, and
3122    // part of the presentation
3123    mOwner->writeInt32(0x07);          // version=0, flags=7
3124    mOwner->writeInt32(now);           // creation time
3125    mOwner->writeInt32(now);           // modification time
3126    mOwner->writeInt32(mTrackId);      // track id starts with 1
3127    mOwner->writeInt32(0);             // reserved
3128    int64_t trakDurationUs = getDurationUs();
3129    int32_t mvhdTimeScale = mOwner->getTimeScale();
3130    int32_t tkhdDuration =
3131        (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
3132    mOwner->writeInt32(tkhdDuration);  // in mvhd timescale
3133    mOwner->writeInt32(0);             // reserved
3134    mOwner->writeInt32(0);             // reserved
3135    mOwner->writeInt16(0);             // layer
3136    mOwner->writeInt16(0);             // alternate group
3137    mOwner->writeInt16(mIsAudio ? 0x100 : 0);  // volume
3138    mOwner->writeInt16(0);             // reserved
3139
3140    mOwner->writeCompositionMatrix(mRotation);       // matrix
3141
3142    if (mIsAudio) {
3143        mOwner->writeInt32(0);
3144        mOwner->writeInt32(0);
3145    } else {
3146        int32_t width, height;
3147        bool success = mMeta->findInt32(kKeyWidth, &width);
3148        success = success && mMeta->findInt32(kKeyHeight, &height);
3149        CHECK(success);
3150
3151        mOwner->writeInt32(width << 16);   // 32-bit fixed-point value
3152        mOwner->writeInt32(height << 16);  // 32-bit fixed-point value
3153    }
3154    mOwner->endBox();  // tkhd
3155}
3156
3157void MPEG4Writer::Track::writeVmhdBox() {
3158    mOwner->beginBox("vmhd");
3159    mOwner->writeInt32(0x01);        // version=0, flags=1
3160    mOwner->writeInt16(0);           // graphics mode
3161    mOwner->writeInt16(0);           // opcolor
3162    mOwner->writeInt16(0);
3163    mOwner->writeInt16(0);
3164    mOwner->endBox();
3165}
3166
3167void MPEG4Writer::Track::writeSmhdBox() {
3168    mOwner->beginBox("smhd");
3169    mOwner->writeInt32(0);           // version=0, flags=0
3170    mOwner->writeInt16(0);           // balance
3171    mOwner->writeInt16(0);           // reserved
3172    mOwner->endBox();
3173}
3174
3175void MPEG4Writer::Track::writeHdlrBox() {
3176    mOwner->beginBox("hdlr");
3177    mOwner->writeInt32(0);             // version=0, flags=0
3178    mOwner->writeInt32(0);             // component type: should be mhlr
3179    mOwner->writeFourcc(mIsAudio ? "soun" : "vide");  // component subtype
3180    mOwner->writeInt32(0);             // reserved
3181    mOwner->writeInt32(0);             // reserved
3182    mOwner->writeInt32(0);             // reserved
3183    // Removing "r" for the name string just makes the string 4 byte aligned
3184    mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle");  // name
3185    mOwner->endBox();
3186}
3187
3188void MPEG4Writer::Track::writeMdhdBox(uint32_t now) {
3189    int64_t trakDurationUs = getDurationUs();
3190    mOwner->beginBox("mdhd");
3191    mOwner->writeInt32(0);             // version=0, flags=0
3192    mOwner->writeInt32(now);           // creation time
3193    mOwner->writeInt32(now);           // modification time
3194    mOwner->writeInt32(mTimeScale);    // media timescale
3195    int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6;
3196    mOwner->writeInt32(mdhdDuration);  // use media timescale
3197    // Language follows the three letter standard ISO-639-2/T
3198    // 'e', 'n', 'g' for "English", for instance.
3199    // Each character is packed as the difference between its ASCII value and 0x60.
3200    // For "English", these are 00101, 01110, 00111.
3201    // XXX: Where is the padding bit located: 0x15C7?
3202    mOwner->writeInt16(0);             // language code
3203    mOwner->writeInt16(0);             // predefined
3204    mOwner->endBox();
3205}
3206
3207void MPEG4Writer::Track::writeDamrBox() {
3208    // 3gpp2 Spec AMRSampleEntry fields
3209    mOwner->beginBox("damr");
3210    mOwner->writeCString("   ");  // vendor: 4 bytes
3211    mOwner->writeInt8(0);         // decoder version
3212    mOwner->writeInt16(0x83FF);   // mode set: all enabled
3213    mOwner->writeInt8(0);         // mode change period
3214    mOwner->writeInt8(1);         // frames per sample
3215    mOwner->endBox();
3216}
3217
3218void MPEG4Writer::Track::writeUrlBox() {
3219    // The table index here refers to the sample description index
3220    // in the sample table entries.
3221    mOwner->beginBox("url ");
3222    mOwner->writeInt32(1);  // version=0, flags=1 (self-contained)
3223    mOwner->endBox();  // url
3224}
3225
3226void MPEG4Writer::Track::writeDrefBox() {
3227    mOwner->beginBox("dref");
3228    mOwner->writeInt32(0);  // version=0, flags=0
3229    mOwner->writeInt32(1);  // entry count (either url or urn)
3230    writeUrlBox();
3231    mOwner->endBox();  // dref
3232}
3233
3234void MPEG4Writer::Track::writeDinfBox() {
3235    mOwner->beginBox("dinf");
3236    writeDrefBox();
3237    mOwner->endBox();  // dinf
3238}
3239
3240void MPEG4Writer::Track::writeAvccBox() {
3241    CHECK(mCodecSpecificData);
3242    CHECK_GE(mCodecSpecificDataSize, 5);
3243
3244    // Patch avcc's lengthSize field to match the number
3245    // of bytes we use to indicate the size of a nal unit.
3246    uint8_t *ptr = (uint8_t *)mCodecSpecificData;
3247    ptr[4] = (ptr[4] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1);
3248    mOwner->beginBox("avcC");
3249    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
3250    mOwner->endBox();  // avcC
3251}
3252
3253
3254void MPEG4Writer::Track::writeHvccBox() {
3255    CHECK(mCodecSpecificData);
3256    CHECK_GE(mCodecSpecificDataSize, 5);
3257
3258    // Patch avcc's lengthSize field to match the number
3259    // of bytes we use to indicate the size of a nal unit.
3260    uint8_t *ptr = (uint8_t *)mCodecSpecificData;
3261    ptr[21] = (ptr[21] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1);
3262    mOwner->beginBox("hvcC");
3263    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
3264    mOwner->endBox();  // hvcC
3265}
3266
3267void MPEG4Writer::Track::writeD263Box() {
3268    mOwner->beginBox("d263");
3269    mOwner->writeInt32(0);  // vendor
3270    mOwner->writeInt8(0);   // decoder version
3271    mOwner->writeInt8(10);  // level: 10
3272    mOwner->writeInt8(0);   // profile: 0
3273    mOwner->endBox();  // d263
3274}
3275
3276// This is useful if the pixel is not square
3277void MPEG4Writer::Track::writePaspBox() {
3278    mOwner->beginBox("pasp");
3279    mOwner->writeInt32(1 << 16);  // hspacing
3280    mOwner->writeInt32(1 << 16);  // vspacing
3281    mOwner->endBox();  // pasp
3282}
3283
3284int32_t MPEG4Writer::Track::getStartTimeOffsetScaledTime() const {
3285    int64_t trackStartTimeOffsetUs = 0;
3286    int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
3287    if (mStartTimestampUs != moovStartTimeUs) {
3288        CHECK_GT(mStartTimestampUs, moovStartTimeUs);
3289        trackStartTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
3290    }
3291    return (trackStartTimeOffsetUs *  mTimeScale + 500000LL) / 1000000LL;
3292}
3293
3294void MPEG4Writer::Track::writeSttsBox() {
3295    mOwner->beginBox("stts");
3296    mOwner->writeInt32(0);  // version=0, flags=0
3297    uint32_t duration;
3298    CHECK(mSttsTableEntries->get(duration, 1));
3299    duration = htonl(duration);  // Back to host byte order
3300    mSttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime()), 1);
3301    mSttsTableEntries->write(mOwner);
3302    mOwner->endBox();  // stts
3303}
3304
3305void MPEG4Writer::Track::writeCttsBox() {
3306    if (mIsAudio) {  // ctts is not for audio
3307        return;
3308    }
3309
3310    // There is no B frame at all
3311    if (mMinCttsOffsetTimeUs == mMaxCttsOffsetTimeUs) {
3312        return;
3313    }
3314
3315    // Do not write ctts box when there is no need to have it.
3316    if (mCttsTableEntries->count() == 0) {
3317        return;
3318    }
3319
3320    ALOGV("ctts box has %d entries with range [%" PRId64 ", %" PRId64 "]",
3321            mCttsTableEntries->count(), mMinCttsOffsetTimeUs, mMaxCttsOffsetTimeUs);
3322
3323    mOwner->beginBox("ctts");
3324    mOwner->writeInt32(0);  // version=0, flags=0
3325    uint32_t duration;
3326    CHECK(mCttsTableEntries->get(duration, 1));
3327    duration = htonl(duration);  // Back host byte order
3328    mCttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime() - mMinCttsOffsetTimeUs), 1);
3329    mCttsTableEntries->write(mOwner);
3330    mOwner->endBox();  // ctts
3331}
3332
3333void MPEG4Writer::Track::writeStssBox() {
3334    mOwner->beginBox("stss");
3335    mOwner->writeInt32(0);  // version=0, flags=0
3336    mStssTableEntries->write(mOwner);
3337    mOwner->endBox();  // stss
3338}
3339
3340void MPEG4Writer::Track::writeStszBox() {
3341    mOwner->beginBox("stsz");
3342    mOwner->writeInt32(0);  // version=0, flags=0
3343    mOwner->writeInt32(0);
3344    mStszTableEntries->write(mOwner);
3345    mOwner->endBox();  // stsz
3346}
3347
3348void MPEG4Writer::Track::writeStscBox() {
3349    mOwner->beginBox("stsc");
3350    mOwner->writeInt32(0);  // version=0, flags=0
3351    mStscTableEntries->write(mOwner);
3352    mOwner->endBox();  // stsc
3353}
3354
3355void MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) {
3356    mOwner->beginBox(use32BitOffset? "stco": "co64");
3357    mOwner->writeInt32(0);  // version=0, flags=0
3358    if (use32BitOffset) {
3359        mStcoTableEntries->write(mOwner);
3360    } else {
3361        mCo64TableEntries->write(mOwner);
3362    }
3363    mOwner->endBox();  // stco or co64
3364}
3365
3366void MPEG4Writer::writeUdtaBox() {
3367    beginBox("udta");
3368    writeGeoDataBox();
3369    endBox();
3370}
3371
3372void MPEG4Writer::writeHdlr() {
3373    beginBox("hdlr");
3374    writeInt32(0); // Version, Flags
3375    writeInt32(0); // Predefined
3376    writeFourcc("mdta");
3377    writeInt32(0); // Reserved[0]
3378    writeInt32(0); // Reserved[1]
3379    writeInt32(0); // Reserved[2]
3380    writeInt8(0);  // Name (empty)
3381    endBox();
3382}
3383
3384void MPEG4Writer::writeKeys() {
3385    size_t count = mMetaKeys->countEntries();
3386
3387    beginBox("keys");
3388    writeInt32(0);     // Version, Flags
3389    writeInt32(count); // Entry_count
3390    for (size_t i = 0; i < count; i++) {
3391        AMessage::Type type;
3392        const char *key = mMetaKeys->getEntryNameAt(i, &type);
3393        size_t n = strlen(key);
3394        writeInt32(n + 8);
3395        writeFourcc("mdta");
3396        write(key, n); // write without the \0
3397    }
3398    endBox();
3399}
3400
3401void MPEG4Writer::writeIlst() {
3402    size_t count = mMetaKeys->countEntries();
3403
3404    beginBox("ilst");
3405    for (size_t i = 0; i < count; i++) {
3406        beginBox(i + 1); // key id (1-based)
3407        beginBox("data");
3408        AMessage::Type type;
3409        const char *key = mMetaKeys->getEntryNameAt(i, &type);
3410        switch (type) {
3411            case AMessage::kTypeString:
3412            {
3413                AString val;
3414                CHECK(mMetaKeys->findString(key, &val));
3415                writeInt32(1); // type = UTF8
3416                writeInt32(0); // default country/language
3417                write(val.c_str(), strlen(val.c_str())); // write without \0
3418                break;
3419            }
3420
3421            case AMessage::kTypeFloat:
3422            {
3423                float val;
3424                CHECK(mMetaKeys->findFloat(key, &val));
3425                writeInt32(23); // type = float32
3426                writeInt32(0);  // default country/language
3427                writeInt32(*reinterpret_cast<int32_t *>(&val));
3428                break;
3429            }
3430
3431            case AMessage::kTypeInt32:
3432            {
3433                int32_t val;
3434                CHECK(mMetaKeys->findInt32(key, &val));
3435                writeInt32(67); // type = signed int32
3436                writeInt32(0);  // default country/language
3437                writeInt32(val);
3438                break;
3439            }
3440
3441            default:
3442            {
3443                ALOGW("Unsupported key type, writing 0 instead");
3444                writeInt32(77); // type = unsigned int32
3445                writeInt32(0);  // default country/language
3446                writeInt32(0);
3447                break;
3448            }
3449        }
3450        endBox(); // data
3451        endBox(); // key id
3452    }
3453    endBox(); // ilst
3454}
3455
3456void MPEG4Writer::writeMetaBox() {
3457    size_t count = mMetaKeys->countEntries();
3458    if (count == 0) {
3459        return;
3460    }
3461
3462    beginBox("meta");
3463    writeHdlr();
3464    writeKeys();
3465    writeIlst();
3466    endBox();
3467}
3468
3469/*
3470 * Geodata is stored according to ISO-6709 standard.
3471 */
3472void MPEG4Writer::writeGeoDataBox() {
3473    beginBox("\xA9xyz");
3474    /*
3475     * For historical reasons, any user data start
3476     * with "\0xA9", must be followed by its assoicated
3477     * language code.
3478     * 0x0012: text string length
3479     * 0x15c7: lang (locale) code: en
3480     */
3481    writeInt32(0x001215c7);
3482    writeLatitude(mLatitudex10000);
3483    writeLongitude(mLongitudex10000);
3484    writeInt8(0x2F);
3485    endBox();
3486}
3487
3488}  // namespace android
3489