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