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