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