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