MPEG4Writer.cpp revision 37187916a486504acaf83bea30147eb5fbf46ae5
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 <ctype.h>
24#include <pthread.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
37#include "include/ESDS.h"
38
39namespace android {
40
41static const uint8_t kNalUnitTypeSeqParamSet = 0x07;
42static const uint8_t kNalUnitTypePicParamSet = 0x08;
43
44class MPEG4Writer::Track {
45public:
46    Track(MPEG4Writer *owner, const sp<MediaSource> &source);
47
48    ~Track();
49
50    status_t start(MetaData *params);
51    status_t stop();
52    status_t pause();
53    bool reachedEOS();
54
55    int64_t getDurationUs() const;
56    int64_t getEstimatedTrackSizeBytes() const;
57    void writeTrackHeader(int32_t trackID, bool use32BitOffset = true);
58    void bufferChunk(int64_t timestampUs);
59    bool isAvc() const { return mIsAvc; }
60    bool isAudio() const { return mIsAudio; }
61    bool isMPEG4() const { return mIsMPEG4; }
62    void addChunkOffset(off_t offset) { mChunkOffsets.push_back(offset); }
63
64private:
65    MPEG4Writer *mOwner;
66    sp<MetaData> mMeta;
67    sp<MediaSource> mSource;
68    volatile bool mDone;
69    volatile bool mPaused;
70    volatile bool mResumed;
71    bool mIsAvc;
72    bool mIsAudio;
73    bool mIsMPEG4;
74    int64_t mTrackDurationUs;
75
76    // For realtime applications, we need to adjust the media clock
77    // for video track based on the audio media clock
78    bool mIsRealTimeRecording;
79    int64_t mMaxTimeStampUs;
80    int64_t mEstimatedTrackSizeBytes;
81    int64_t mMaxWriteTimeUs;
82    int32_t mTimeScale;
83
84    pthread_t mThread;
85
86    // mNumSamples is used to track how many samples in mSampleSizes List.
87    // This is to reduce the cost associated with mSampleSizes.size() call,
88    // since it is O(n). Ideally, the fix should be in List class.
89    size_t              mNumSamples;
90    List<size_t>        mSampleSizes;
91    bool                mSamplesHaveSameSize;
92
93    List<MediaBuffer *> mChunkSamples;
94    List<off_t>         mChunkOffsets;
95
96    struct StscTableEntry {
97
98        StscTableEntry(uint32_t chunk, uint32_t samples, uint32_t id)
99            : firstChunk(chunk),
100              samplesPerChunk(samples),
101              sampleDescriptionId(id) {}
102
103        uint32_t firstChunk;
104        uint32_t samplesPerChunk;
105        uint32_t sampleDescriptionId;
106    };
107    List<StscTableEntry> mStscTableEntries;
108
109    List<int32_t> mStssTableEntries;
110    List<int64_t> mChunkDurations;
111
112    struct SttsTableEntry {
113
114        SttsTableEntry(uint32_t count, uint32_t durationUs)
115            : sampleCount(count), sampleDurationUs(durationUs) {}
116
117        uint32_t sampleCount;
118        uint32_t sampleDurationUs;
119    };
120    List<SttsTableEntry> mSttsTableEntries;
121
122    // Sequence parameter set or picture parameter set
123    struct AVCParamSet {
124        AVCParamSet(uint16_t length, const uint8_t *data)
125            : mLength(length), mData(data) {}
126
127        uint16_t mLength;
128        const uint8_t *mData;
129    };
130    List<AVCParamSet> mSeqParamSets;
131    List<AVCParamSet> mPicParamSets;
132    uint8_t mProfileIdc;
133    uint8_t mProfileCompatible;
134    uint8_t mLevelIdc;
135
136    void *mCodecSpecificData;
137    size_t mCodecSpecificDataSize;
138    bool mGotAllCodecSpecificData;
139    bool mTrackingProgressStatus;
140
141    bool mReachedEOS;
142    int64_t mStartTimestampUs;
143    int64_t mPreviousTrackTimeUs;
144    int64_t mTrackEveryTimeDurationUs;
145
146    static void *ThreadWrapper(void *me);
147    status_t threadEntry();
148
149    const uint8_t *parseParamSet(
150        const uint8_t *data, size_t length, int type, size_t *paramSetLen);
151
152    status_t makeAVCCodecSpecificData(
153            const uint8_t *data, size_t size);
154    status_t copyAVCCodecSpecificData(
155            const uint8_t *data, size_t size);
156    status_t parseAVCCodecSpecificData(
157            const uint8_t *data, size_t size);
158
159    // Track authoring progress status
160    void trackProgressStatus(int64_t timeUs, status_t err = OK);
161    void initTrackingProgressStatus(MetaData *params);
162
163    // Utilities for collecting statistical data
164    void logStatisticalData(bool isAudio);
165    void findMinAvgMaxSampleDurationMs(
166            int32_t *min, int32_t *avg, int32_t *max);
167    void findMinMaxChunkDurations(int64_t *min, int64_t *max);
168
169    void getCodecSpecificDataFromInputFormatIfPossible();
170
171    // Determine the track time scale
172    // If it is an audio track, try to use the sampling rate as
173    // the time scale; however, if user chooses the overwrite
174    // value, the user-supplied time scale will be used.
175    void setTimeScale();
176
177    Track(const Track &);
178    Track &operator=(const Track &);
179};
180
181#define USE_NALLEN_FOUR         1
182
183MPEG4Writer::MPEG4Writer(const char *filename)
184    : mFile(fopen(filename, "wb")),
185      mUse32BitOffset(true),
186      mPaused(false),
187      mStarted(false),
188      mOffset(0),
189      mMdatOffset(0),
190      mEstimatedMoovBoxSize(0),
191      mInterleaveDurationUs(1000000) {
192    CHECK(mFile != NULL);
193}
194
195MPEG4Writer::MPEG4Writer(int fd)
196    : mFile(fdopen(fd, "wb")),
197      mUse32BitOffset(true),
198      mPaused(false),
199      mStarted(false),
200      mOffset(0),
201      mMdatOffset(0),
202      mEstimatedMoovBoxSize(0),
203      mInterleaveDurationUs(1000000) {
204    CHECK(mFile != NULL);
205}
206
207MPEG4Writer::~MPEG4Writer() {
208    stop();
209
210    for (List<Track *>::iterator it = mTracks.begin();
211         it != mTracks.end(); ++it) {
212        delete *it;
213    }
214    mTracks.clear();
215}
216
217status_t MPEG4Writer::addSource(const sp<MediaSource> &source) {
218    Track *track = new Track(this, source);
219    mTracks.push_back(track);
220
221    return OK;
222}
223
224status_t MPEG4Writer::startTracks(MetaData *params) {
225    for (List<Track *>::iterator it = mTracks.begin();
226         it != mTracks.end(); ++it) {
227        status_t err = (*it)->start(params);
228
229        if (err != OK) {
230            for (List<Track *>::iterator it2 = mTracks.begin();
231                 it2 != it; ++it2) {
232                (*it2)->stop();
233            }
234
235            return err;
236        }
237    }
238    return OK;
239}
240
241int64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) {
242    // This implementation is highly experimental/heurisitic.
243    //
244    // Statistical analysis shows that metadata usually accounts
245    // for a small portion of the total file size, usually < 0.6%.
246    // Currently, lets set to 0.4% for now.
247
248    // The default MIN_MOOV_BOX_SIZE is set to 0.4% x 1MB,
249    // where 1MB is the common file size limit for MMS application.
250    // The default MAX _MOOV_BOX_SIZE value is based on about 4
251    // minute video recording with a bit rate about 3 Mbps, because
252    // statistics also show that most of the video captured are going
253    // to be less than 3 minutes.
254
255    // If the estimation is wrong, we will pay the price of wasting
256    // some reserved space. This should not happen so often statistically.
257    static const int32_t factor = mUse32BitOffset? 1: 2;
258    static const int64_t MIN_MOOV_BOX_SIZE = 4 * 1024;  // 4 KB
259    static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000);
260    int64_t size = MIN_MOOV_BOX_SIZE;
261
262    if (mMaxFileSizeLimitBytes != 0) {
263        size = mMaxFileSizeLimitBytes * 4 / 1000;
264    } else if (mMaxFileDurationLimitUs != 0) {
265        if (bitRate <= 0) {
266            // We could not estimate the file size since bitRate is not set.
267            size = MIN_MOOV_BOX_SIZE;
268        } else {
269            size = ((mMaxFileDurationLimitUs * bitRate * 4) / 1000 / 8000000);
270        }
271    }
272    if (size < MIN_MOOV_BOX_SIZE) {
273        size = MIN_MOOV_BOX_SIZE;
274    }
275
276    // Any long duration recording will be probably end up with
277    // non-streamable mp4 file.
278    if (size > MAX_MOOV_BOX_SIZE) {
279        size = MAX_MOOV_BOX_SIZE;
280    }
281
282    LOGI("limits: %lld/%lld bytes/us, bit rate: %d bps and the estimated"
283         " moov size %lld bytes",
284         mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size);
285    return factor * size;
286}
287
288status_t MPEG4Writer::start(MetaData *param) {
289    if (mFile == NULL) {
290        return UNKNOWN_ERROR;
291    }
292
293    int32_t use64BitOffset;
294    if (param &&
295        param->findInt32(kKey64BitFileOffset, &use64BitOffset) &&
296        use64BitOffset) {
297        mUse32BitOffset = false;
298    }
299
300    // System property can overwrite the file offset bits parameter
301    char value[PROPERTY_VALUE_MAX];
302    if (property_get("media.stagefright.record-64bits", value, NULL)
303        && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
304        mUse32BitOffset = false;
305    }
306
307    mStartTimestampUs = -1;
308
309    if (mStarted) {
310        if (mPaused) {
311            mPaused = false;
312            return startTracks(param);
313        }
314        return OK;
315    }
316
317    if (!param ||
318        !param->findInt32(kKeyTimeScale, &mTimeScale)) {
319        mTimeScale = 1000;
320    }
321    CHECK(mTimeScale > 0);
322    LOGV("movie time scale: %d", mTimeScale);
323
324    mStreamableFile = true;
325    mWriteMoovBoxToMemory = false;
326    mMoovBoxBuffer = NULL;
327    mMoovBoxBufferOffset = 0;
328
329    beginBox("ftyp");
330      {
331        int32_t fileType;
332        if (param && param->findInt32(kKeyFileType, &fileType) &&
333            fileType != OUTPUT_FORMAT_MPEG_4) {
334            writeFourcc("3gp4");
335        } else {
336            writeFourcc("isom");
337        }
338      }
339      writeInt32(0);
340      writeFourcc("isom");
341      writeFourcc("3gp4");
342    endBox();
343
344    mFreeBoxOffset = mOffset;
345
346    if (mEstimatedMoovBoxSize == 0) {
347        int32_t bitRate = -1;
348        if (param) {
349            param->findInt32(kKeyBitRate, &bitRate);
350        }
351        mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate);
352    }
353    CHECK(mEstimatedMoovBoxSize >= 8);
354    fseeko(mFile, mFreeBoxOffset, SEEK_SET);
355    writeInt32(mEstimatedMoovBoxSize);
356    write("free", 4);
357
358    mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize;
359    mOffset = mMdatOffset;
360    fseeko(mFile, mMdatOffset, SEEK_SET);
361    if (mUse32BitOffset) {
362        write("????mdat", 8);
363    } else {
364        write("\x00\x00\x00\x01mdat????????", 16);
365    }
366
367    status_t err = startWriterThread();
368    if (err != OK) {
369        return err;
370    }
371
372    err = startTracks(param);
373    if (err != OK) {
374        return err;
375    }
376
377    mStarted = true;
378    return OK;
379}
380
381status_t MPEG4Writer::pause() {
382    if (mFile == NULL) {
383        return OK;
384    }
385    mPaused = true;
386    status_t err = OK;
387    for (List<Track *>::iterator it = mTracks.begin();
388         it != mTracks.end(); ++it) {
389        status_t status = (*it)->pause();
390        if (status != OK) {
391            err = status;
392        }
393    }
394    return err;
395}
396
397void MPEG4Writer::stopWriterThread() {
398    LOGV("stopWriterThread");
399
400    {
401        Mutex::Autolock autolock(mLock);
402
403        mDone = true;
404        mChunkReadyCondition.signal();
405    }
406
407    void *dummy;
408    pthread_join(mThread, &dummy);
409}
410
411status_t MPEG4Writer::stop() {
412    if (mFile == NULL) {
413        return OK;
414    }
415
416    status_t err = OK;
417    int64_t maxDurationUs = 0;
418    for (List<Track *>::iterator it = mTracks.begin();
419         it != mTracks.end(); ++it) {
420        status_t status = (*it)->stop();
421        if (err == OK && status != OK) {
422            err = status;
423        }
424
425        int64_t durationUs = (*it)->getDurationUs();
426        if (durationUs > maxDurationUs) {
427            maxDurationUs = durationUs;
428        }
429    }
430
431    stopWriterThread();
432
433    // Do not write out movie header on error.
434    if (err != OK) {
435        fflush(mFile);
436        fclose(mFile);
437        mFile = NULL;
438        mStarted = false;
439        return err;
440    }
441
442    // Fix up the size of the 'mdat' chunk.
443    if (mUse32BitOffset) {
444        fseeko(mFile, mMdatOffset, SEEK_SET);
445        int32_t size = htonl(static_cast<int32_t>(mOffset - mMdatOffset));
446        fwrite(&size, 1, 4, mFile);
447    } else {
448        fseeko(mFile, mMdatOffset + 8, SEEK_SET);
449        int64_t size = mOffset - mMdatOffset;
450        size = hton64(size);
451        fwrite(&size, 1, 8, mFile);
452    }
453    fseeko(mFile, mOffset, SEEK_SET);
454
455    time_t now = time(NULL);
456    const off_t moovOffset = mOffset;
457    mWriteMoovBoxToMemory = true;
458    mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize);
459    mMoovBoxBufferOffset = 0;
460    CHECK(mMoovBoxBuffer != NULL);
461    int32_t duration = (maxDurationUs * mTimeScale + 5E5) / 1E6;
462
463    beginBox("moov");
464
465      beginBox("mvhd");
466        writeInt32(0);             // version=0, flags=0
467        writeInt32(now);           // creation time
468        writeInt32(now);           // modification time
469        writeInt32(mTimeScale);    // mvhd timescale
470        writeInt32(duration);
471        writeInt32(0x10000);       // rate: 1.0
472        writeInt16(0x100);         // volume
473        writeInt16(0);             // reserved
474        writeInt32(0);             // reserved
475        writeInt32(0);             // reserved
476        writeInt32(0x10000);       // matrix
477        writeInt32(0);
478        writeInt32(0);
479        writeInt32(0);
480        writeInt32(0x10000);
481        writeInt32(0);
482        writeInt32(0);
483        writeInt32(0);
484        writeInt32(0x40000000);
485        writeInt32(0);             // predefined
486        writeInt32(0);             // predefined
487        writeInt32(0);             // predefined
488        writeInt32(0);             // predefined
489        writeInt32(0);             // predefined
490        writeInt32(0);             // predefined
491        writeInt32(mTracks.size() + 1);  // nextTrackID
492      endBox();  // mvhd
493
494      int32_t id = 1;
495      for (List<Track *>::iterator it = mTracks.begin();
496           it != mTracks.end(); ++it, ++id) {
497          (*it)->writeTrackHeader(id, mUse32BitOffset);
498      }
499    endBox();  // moov
500
501    mWriteMoovBoxToMemory = false;
502    if (mStreamableFile) {
503        CHECK(mMoovBoxBufferOffset + 8 <= mEstimatedMoovBoxSize);
504
505        // Moov box
506        fseeko(mFile, mFreeBoxOffset, SEEK_SET);
507        mOffset = mFreeBoxOffset;
508        write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, mFile);
509
510        // Free box
511        fseeko(mFile, mOffset, SEEK_SET);
512        writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset);
513        write("free", 4);
514
515        // Free temp memory
516        free(mMoovBoxBuffer);
517        mMoovBoxBuffer = NULL;
518        mMoovBoxBufferOffset = 0;
519    } else {
520        LOGI("The mp4 file will not be streamable.");
521    }
522
523    CHECK(mBoxes.empty());
524
525    fflush(mFile);
526    fclose(mFile);
527    mFile = NULL;
528    mStarted = false;
529    return err;
530}
531
532status_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) {
533    mInterleaveDurationUs = durationUs;
534    return OK;
535}
536
537void MPEG4Writer::lock() {
538    mLock.lock();
539}
540
541void MPEG4Writer::unlock() {
542    mLock.unlock();
543}
544
545off_t MPEG4Writer::addSample_l(MediaBuffer *buffer) {
546    off_t old_offset = mOffset;
547
548    fwrite((const uint8_t *)buffer->data() + buffer->range_offset(),
549           1, buffer->range_length(), mFile);
550
551    mOffset += buffer->range_length();
552
553    return old_offset;
554}
555
556static void StripStartcode(MediaBuffer *buffer) {
557    if (buffer->range_length() < 4) {
558        return;
559    }
560
561    const uint8_t *ptr =
562        (const uint8_t *)buffer->data() + buffer->range_offset();
563
564    if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) {
565        buffer->set_range(
566                buffer->range_offset() + 4, buffer->range_length() - 4);
567    }
568}
569
570off_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) {
571    off_t old_offset = mOffset;
572
573    size_t length = buffer->range_length();
574
575#if USE_NALLEN_FOUR
576    uint8_t x = length >> 24;
577    fwrite(&x, 1, 1, mFile);
578    x = (length >> 16) & 0xff;
579    fwrite(&x, 1, 1, mFile);
580    x = (length >> 8) & 0xff;
581    fwrite(&x, 1, 1, mFile);
582    x = length & 0xff;
583    fwrite(&x, 1, 1, mFile);
584#else
585    CHECK(length < 65536);
586
587    uint8_t x = length >> 8;
588    fwrite(&x, 1, 1, mFile);
589    x = length & 0xff;
590    fwrite(&x, 1, 1, mFile);
591#endif
592
593    fwrite((const uint8_t *)buffer->data() + buffer->range_offset(),
594           1, length, mFile);
595
596#if USE_NALLEN_FOUR
597    mOffset += length + 4;
598#else
599    mOffset += length + 2;
600#endif
601
602    return old_offset;
603}
604
605size_t MPEG4Writer::write(
606        const void *ptr, size_t size, size_t nmemb, FILE *stream) {
607
608    const size_t bytes = size * nmemb;
609    if (mWriteMoovBoxToMemory) {
610        off_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes;
611        if (moovBoxSize > mEstimatedMoovBoxSize) {
612            for (List<off_t>::iterator it = mBoxes.begin();
613                 it != mBoxes.end(); ++it) {
614                (*it) += mOffset;
615            }
616            fseeko(mFile, mOffset, SEEK_SET);
617            fwrite(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, stream);
618            fwrite(ptr, size, nmemb, stream);
619            mOffset += (bytes + mMoovBoxBufferOffset);
620            free(mMoovBoxBuffer);
621            mMoovBoxBuffer = NULL;
622            mMoovBoxBufferOffset = 0;
623            mWriteMoovBoxToMemory = false;
624            mStreamableFile = false;
625        } else {
626            memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes);
627            mMoovBoxBufferOffset += bytes;
628        }
629    } else {
630        fwrite(ptr, size, nmemb, stream);
631        mOffset += bytes;
632    }
633    return bytes;
634}
635
636void MPEG4Writer::beginBox(const char *fourcc) {
637    CHECK_EQ(strlen(fourcc), 4);
638
639    mBoxes.push_back(mWriteMoovBoxToMemory?
640            mMoovBoxBufferOffset: mOffset);
641
642    writeInt32(0);
643    writeFourcc(fourcc);
644}
645
646void MPEG4Writer::endBox() {
647    CHECK(!mBoxes.empty());
648
649    off_t offset = *--mBoxes.end();
650    mBoxes.erase(--mBoxes.end());
651
652    if (mWriteMoovBoxToMemory) {
653       int32_t x = htonl(mMoovBoxBufferOffset - offset);
654       memcpy(mMoovBoxBuffer + offset, &x, 4);
655    } else {
656        fseeko(mFile, offset, SEEK_SET);
657        writeInt32(mOffset - offset);
658        mOffset -= 4;
659        fseeko(mFile, mOffset, SEEK_SET);
660    }
661}
662
663void MPEG4Writer::writeInt8(int8_t x) {
664    write(&x, 1, 1, mFile);
665}
666
667void MPEG4Writer::writeInt16(int16_t x) {
668    x = htons(x);
669    write(&x, 1, 2, mFile);
670}
671
672void MPEG4Writer::writeInt32(int32_t x) {
673    x = htonl(x);
674    write(&x, 1, 4, mFile);
675}
676
677void MPEG4Writer::writeInt64(int64_t x) {
678    x = hton64(x);
679    write(&x, 1, 8, mFile);
680}
681
682void MPEG4Writer::writeCString(const char *s) {
683    size_t n = strlen(s);
684    write(s, 1, n + 1, mFile);
685}
686
687void MPEG4Writer::writeFourcc(const char *s) {
688    CHECK_EQ(strlen(s), 4);
689    write(s, 1, 4, mFile);
690}
691
692void MPEG4Writer::write(const void *data, size_t size) {
693    write(data, 1, size, mFile);
694}
695
696bool MPEG4Writer::exceedsFileSizeLimit() {
697    // No limit
698    if (mMaxFileSizeLimitBytes == 0) {
699        return false;
700    }
701
702    int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize);
703    for (List<Track *>::iterator it = mTracks.begin();
704         it != mTracks.end(); ++it) {
705        nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes();
706    }
707    return (nTotalBytesEstimate >= mMaxFileSizeLimitBytes);
708}
709
710bool MPEG4Writer::exceedsFileDurationLimit() {
711    // No limit
712    if (mMaxFileDurationLimitUs == 0) {
713        return false;
714    }
715
716    for (List<Track *>::iterator it = mTracks.begin();
717         it != mTracks.end(); ++it) {
718        if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) {
719            return true;
720        }
721    }
722    return false;
723}
724
725bool MPEG4Writer::reachedEOS() {
726    bool allDone = true;
727    for (List<Track *>::iterator it = mTracks.begin();
728         it != mTracks.end(); ++it) {
729        if (!(*it)->reachedEOS()) {
730            allDone = false;
731            break;
732        }
733    }
734
735    return allDone;
736}
737
738void MPEG4Writer::setStartTimestampUs(int64_t timeUs) {
739    LOGI("setStartTimestampUs: %lld", timeUs);
740    CHECK(timeUs >= 0);
741    Mutex::Autolock autoLock(mLock);
742    if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) {
743        mStartTimestampUs = timeUs;
744        LOGI("Earliest track starting time: %lld", mStartTimestampUs);
745    }
746}
747
748int64_t MPEG4Writer::getStartTimestampUs() {
749    Mutex::Autolock autoLock(mLock);
750    return mStartTimestampUs;
751}
752
753size_t MPEG4Writer::numTracks() {
754    Mutex::Autolock autolock(mLock);
755    return mTracks.size();
756}
757
758////////////////////////////////////////////////////////////////////////////////
759
760MPEG4Writer::Track::Track(
761        MPEG4Writer *owner, const sp<MediaSource> &source)
762    : mOwner(owner),
763      mMeta(source->getFormat()),
764      mSource(source),
765      mDone(false),
766      mPaused(false),
767      mResumed(false),
768      mTrackDurationUs(0),
769      mEstimatedTrackSizeBytes(0),
770      mSamplesHaveSameSize(true),
771      mCodecSpecificData(NULL),
772      mCodecSpecificDataSize(0),
773      mGotAllCodecSpecificData(false),
774      mReachedEOS(false) {
775    getCodecSpecificDataFromInputFormatIfPossible();
776
777    const char *mime;
778    mMeta->findCString(kKeyMIMEType, &mime);
779    mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
780    mIsAudio = !strncasecmp(mime, "audio/", 6);
781    mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
782               !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC);
783
784    setTimeScale();
785}
786
787void MPEG4Writer::Track::setTimeScale() {
788    LOGV("setTimeScale");
789    // Default time scale
790    mTimeScale = 90000;
791
792    if (mIsAudio) {
793        // Use the sampling rate as the default time scale for audio track.
794        int32_t sampleRate;
795        bool success = mMeta->findInt32(kKeySampleRate, &sampleRate);
796        CHECK(success);
797        mTimeScale = sampleRate;
798    }
799
800    // If someone would like to overwrite the timescale, use user-supplied value.
801    int32_t timeScale;
802    if (mMeta->findInt32(kKeyTimeScale, &timeScale)) {
803        mTimeScale = timeScale;
804    }
805
806    CHECK(mTimeScale > 0);
807}
808
809void MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() {
810    const char *mime;
811    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
812
813    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
814        uint32_t type;
815        const void *data;
816        size_t size;
817        if (mMeta->findData(kKeyAVCC, &type, &data, &size)) {
818            mCodecSpecificData = malloc(size);
819            mCodecSpecificDataSize = size;
820            memcpy(mCodecSpecificData, data, size);
821            mGotAllCodecSpecificData = true;
822        }
823    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
824            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
825        uint32_t type;
826        const void *data;
827        size_t size;
828        if (mMeta->findData(kKeyESDS, &type, &data, &size)) {
829            ESDS esds(data, size);
830            if (esds.getCodecSpecificInfo(&data, &size) == OK) {
831                mCodecSpecificData = malloc(size);
832                mCodecSpecificDataSize = size;
833                memcpy(mCodecSpecificData, data, size);
834                mGotAllCodecSpecificData = true;
835            }
836        }
837    }
838}
839
840MPEG4Writer::Track::~Track() {
841    stop();
842
843    if (mCodecSpecificData != NULL) {
844        free(mCodecSpecificData);
845        mCodecSpecificData = NULL;
846    }
847}
848
849void MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) {
850    LOGV("initTrackingProgressStatus");
851    mPreviousTrackTimeUs = -1;
852    mTrackingProgressStatus = false;
853    mTrackEveryTimeDurationUs = 0;
854    {
855        int64_t timeUs;
856        if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) {
857            LOGV("Receive request to track progress status for every %lld us", timeUs);
858            mTrackEveryTimeDurationUs = timeUs;
859            mTrackingProgressStatus = true;
860        }
861    }
862}
863
864// static
865void *MPEG4Writer::ThreadWrapper(void *me) {
866    LOGV("ThreadWrapper: %p", me);
867    MPEG4Writer *writer = static_cast<MPEG4Writer *>(me);
868    writer->threadFunc();
869    return NULL;
870}
871
872void MPEG4Writer::bufferChunk(const Chunk& chunk) {
873    LOGV("bufferChunk: %p", chunk.mTrack);
874    Mutex::Autolock autolock(mLock);
875    CHECK_EQ(mDone, false);
876
877    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
878         it != mChunkInfos.end(); ++it) {
879
880        if (chunk.mTrack == it->mTrack) {  // Found owner
881            it->mChunks.push_back(chunk);
882            mChunkReadyCondition.signal();
883            return;
884        }
885    }
886
887    CHECK("Received a chunk for a unknown track" == 0);
888}
889
890void MPEG4Writer::writeFirstChunk(ChunkInfo* info) {
891    LOGV("writeFirstChunk: %p", info->mTrack);
892
893    List<Chunk>::iterator chunkIt = info->mChunks.begin();
894    for (List<MediaBuffer *>::iterator it = chunkIt->mSamples.begin();
895         it != chunkIt->mSamples.end(); ++it) {
896
897        off_t offset = info->mTrack->isAvc()
898                            ? addLengthPrefixedSample_l(*it)
899                            : addSample_l(*it);
900        if (it == chunkIt->mSamples.begin()) {
901            info->mTrack->addChunkOffset(offset);
902        }
903    }
904
905    // Done with the current chunk.
906    // Release all the samples in this chunk.
907    while (!chunkIt->mSamples.empty()) {
908        List<MediaBuffer *>::iterator it = chunkIt->mSamples.begin();
909        (*it)->release();
910        (*it) = NULL;
911        chunkIt->mSamples.erase(it);
912    }
913    chunkIt->mSamples.clear();
914    info->mChunks.erase(chunkIt);
915}
916
917void MPEG4Writer::writeChunks() {
918    LOGV("writeChunks");
919    size_t outstandingChunks = 0;
920    while (!mChunkInfos.empty()) {
921        List<ChunkInfo>::iterator it = mChunkInfos.begin();
922        while (!it->mChunks.empty()) {
923            CHECK_EQ(OK, writeOneChunk());
924            ++outstandingChunks;
925        }
926        it->mTrack = NULL;
927        mChunkInfos.erase(it);
928    }
929    mChunkInfos.clear();
930    LOGD("%d chunks are written in the last batch", outstandingChunks);
931}
932
933status_t MPEG4Writer::writeOneChunk() {
934    LOGV("writeOneChunk");
935
936    // Find the smallest timestamp, and write that chunk out
937    // XXX: What if some track is just too slow?
938    int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL;
939    Track *track = NULL;
940    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
941         it != mChunkInfos.end(); ++it) {
942        if (!it->mChunks.empty()) {
943            List<Chunk>::iterator chunkIt = it->mChunks.begin();
944            if (chunkIt->mTimeStampUs < minTimestampUs) {
945                minTimestampUs = chunkIt->mTimeStampUs;
946                track = it->mTrack;
947            }
948        }
949    }
950
951    if (track == NULL) {
952        LOGV("Nothing to be written after all");
953        return OK;
954    }
955
956    if (mIsFirstChunk) {
957        mIsFirstChunk = false;
958    }
959    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
960         it != mChunkInfos.end(); ++it) {
961        if (it->mTrack == track) {
962            writeFirstChunk(&(*it));
963        }
964    }
965    return OK;
966}
967
968void MPEG4Writer::threadFunc() {
969    LOGV("threadFunc");
970
971    while (!mDone) {
972        {
973            Mutex::Autolock autolock(mLock);
974            mChunkReadyCondition.wait(mLock);
975            CHECK_EQ(writeOneChunk(), OK);
976        }
977    }
978
979    {
980        // Write ALL samples
981        Mutex::Autolock autolock(mLock);
982        writeChunks();
983    }
984}
985
986status_t MPEG4Writer::startWriterThread() {
987    LOGV("startWriterThread");
988
989    mDone = false;
990    mIsFirstChunk = true;
991    mDriftTimeUs = 0;
992    for (List<Track *>::iterator it = mTracks.begin();
993         it != mTracks.end(); ++it) {
994        ChunkInfo info;
995        info.mTrack = *it;
996        mChunkInfos.push_back(info);
997    }
998
999    pthread_attr_t attr;
1000    pthread_attr_init(&attr);
1001    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
1002    pthread_create(&mThread, &attr, ThreadWrapper, this);
1003    pthread_attr_destroy(&attr);
1004    return OK;
1005}
1006
1007status_t MPEG4Writer::Track::start(MetaData *params) {
1008    if (!mDone && mPaused) {
1009        mPaused = false;
1010        mResumed = true;
1011        return OK;
1012    }
1013
1014    int64_t startTimeUs;
1015    if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) {
1016        startTimeUs = 0;
1017    }
1018
1019    mIsRealTimeRecording = true;
1020    {
1021        int32_t isNotRealTime;
1022        if (params && params->findInt32(kKeyNotRealTime, &isNotRealTime)) {
1023            mIsRealTimeRecording = (isNotRealTime == 0);
1024        }
1025    }
1026
1027    initTrackingProgressStatus(params);
1028
1029    sp<MetaData> meta = new MetaData;
1030    meta->setInt64(kKeyTime, startTimeUs);
1031    status_t err = mSource->start(meta.get());
1032    if (err != OK) {
1033        mDone = mReachedEOS = true;
1034        return err;
1035    }
1036
1037    pthread_attr_t attr;
1038    pthread_attr_init(&attr);
1039    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
1040
1041    mDone = false;
1042    mTrackDurationUs = 0;
1043    mReachedEOS = false;
1044    mEstimatedTrackSizeBytes = 0;
1045
1046    pthread_create(&mThread, &attr, ThreadWrapper, this);
1047    pthread_attr_destroy(&attr);
1048
1049    return OK;
1050}
1051
1052status_t MPEG4Writer::Track::pause() {
1053    mPaused = true;
1054    return OK;
1055}
1056
1057status_t MPEG4Writer::Track::stop() {
1058    if (mDone) {
1059        return OK;
1060    }
1061
1062    mDone = true;
1063
1064    void *dummy;
1065    pthread_join(mThread, &dummy);
1066
1067    status_t err = (status_t) dummy;
1068
1069    {
1070        status_t status = mSource->stop();
1071        if (err == OK && status != OK && status != ERROR_END_OF_STREAM) {
1072            err = status;
1073        }
1074    }
1075
1076    return err;
1077}
1078
1079bool MPEG4Writer::Track::reachedEOS() {
1080    return mReachedEOS;
1081}
1082
1083// static
1084void *MPEG4Writer::Track::ThreadWrapper(void *me) {
1085    Track *track = static_cast<Track *>(me);
1086
1087    status_t err = track->threadEntry();
1088    return (void *) err;
1089}
1090
1091#include <ctype.h>
1092static void hexdump(const void *_data, size_t size) {
1093    const uint8_t *data = (const uint8_t *)_data;
1094    size_t offset = 0;
1095    while (offset < size) {
1096        printf("0x%04x  ", offset);
1097
1098        size_t n = size - offset;
1099        if (n > 16) {
1100            n = 16;
1101        }
1102
1103        for (size_t i = 0; i < 16; ++i) {
1104            if (i == 8) {
1105                printf(" ");
1106            }
1107
1108            if (offset + i < size) {
1109                printf("%02x ", data[offset + i]);
1110            } else {
1111                printf("   ");
1112            }
1113        }
1114
1115        printf(" ");
1116
1117        for (size_t i = 0; i < n; ++i) {
1118            if (isprint(data[offset + i])) {
1119                printf("%c", data[offset + i]);
1120            } else {
1121                printf(".");
1122            }
1123        }
1124
1125        printf("\n");
1126
1127        offset += 16;
1128    }
1129}
1130
1131static void getNalUnitType(uint8_t byte, uint8_t* type) {
1132    LOGV("getNalUnitType: %d", byte);
1133
1134    // nal_unit_type: 5-bit unsigned integer
1135    *type = (byte & 0x1F);
1136}
1137
1138static const uint8_t *findNextStartCode(
1139        const uint8_t *data, size_t length) {
1140
1141    LOGV("findNextStartCode: %p %d", data, length);
1142
1143    size_t bytesLeft = length;
1144    while (bytesLeft > 4  &&
1145            memcmp("\x00\x00\x00\x01", &data[length - bytesLeft], 4)) {
1146        --bytesLeft;
1147    }
1148    if (bytesLeft <= 4) {
1149        bytesLeft = 0; // Last parameter set
1150    }
1151    return &data[length - bytesLeft];
1152}
1153
1154const uint8_t *MPEG4Writer::Track::parseParamSet(
1155        const uint8_t *data, size_t length, int type, size_t *paramSetLen) {
1156
1157    LOGV("parseParamSet");
1158    CHECK(type == kNalUnitTypeSeqParamSet ||
1159          type == kNalUnitTypePicParamSet);
1160
1161    const uint8_t *nextStartCode = findNextStartCode(data, length);
1162    *paramSetLen = nextStartCode - data;
1163    if (*paramSetLen == 0) {
1164        LOGE("Param set is malformed, since its length is 0");
1165        return NULL;
1166    }
1167
1168    AVCParamSet paramSet(*paramSetLen, data);
1169    if (type == kNalUnitTypeSeqParamSet) {
1170        if (*paramSetLen < 4) {
1171            LOGE("Seq parameter set malformed");
1172            return NULL;
1173        }
1174        if (mSeqParamSets.empty()) {
1175            mProfileIdc = data[1];
1176            mProfileCompatible = data[2];
1177            mLevelIdc = data[3];
1178        } else {
1179            if (mProfileIdc != data[1] ||
1180                mProfileCompatible != data[2] ||
1181                mLevelIdc != data[3]) {
1182                LOGE("Inconsistent profile/level found in seq parameter sets");
1183                return NULL;
1184            }
1185        }
1186        mSeqParamSets.push_back(paramSet);
1187    } else {
1188        mPicParamSets.push_back(paramSet);
1189    }
1190    return nextStartCode;
1191}
1192
1193status_t MPEG4Writer::Track::copyAVCCodecSpecificData(
1194        const uint8_t *data, size_t size) {
1195    LOGV("copyAVCCodecSpecificData");
1196
1197    // 2 bytes for each of the parameter set length field
1198    // plus the 7 bytes for the header
1199    if (size < 4 + 7) {
1200        LOGE("Codec specific data length too short: %d", size);
1201        return ERROR_MALFORMED;
1202    }
1203
1204    mCodecSpecificDataSize = size;
1205    mCodecSpecificData = malloc(size);
1206    memcpy(mCodecSpecificData, data, size);
1207    return OK;
1208}
1209
1210status_t MPEG4Writer::Track::parseAVCCodecSpecificData(
1211        const uint8_t *data, size_t size) {
1212
1213    LOGV("parseAVCCodecSpecificData");
1214    // Data starts with a start code.
1215    // SPS and PPS are separated with start codes.
1216    // Also, SPS must come before PPS
1217    uint8_t type = kNalUnitTypeSeqParamSet;
1218    bool gotSps = false;
1219    bool gotPps = false;
1220    const uint8_t *tmp = data;
1221    const uint8_t *nextStartCode = data;
1222    size_t bytesLeft = size;
1223    size_t paramSetLen = 0;
1224    mCodecSpecificDataSize = 0;
1225    while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) {
1226        getNalUnitType(*(tmp + 4), &type);
1227        if (type == kNalUnitTypeSeqParamSet) {
1228            if (gotPps) {
1229                LOGE("SPS must come before PPS");
1230                return ERROR_MALFORMED;
1231            }
1232            if (!gotSps) {
1233                gotSps = true;
1234            }
1235            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
1236        } else if (type == kNalUnitTypePicParamSet) {
1237            if (!gotSps) {
1238                LOGE("SPS must come before PPS");
1239                return ERROR_MALFORMED;
1240            }
1241            if (!gotPps) {
1242                gotPps = true;
1243            }
1244            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
1245        } else {
1246            LOGE("Only SPS and PPS Nal units are expected");
1247            return ERROR_MALFORMED;
1248        }
1249
1250        if (nextStartCode == NULL) {
1251            return ERROR_MALFORMED;
1252        }
1253
1254        // Move on to find the next parameter set
1255        bytesLeft -= nextStartCode - tmp;
1256        tmp = nextStartCode;
1257        mCodecSpecificDataSize += (2 + paramSetLen);
1258    }
1259
1260    {
1261        // Check on the number of seq parameter sets
1262        size_t nSeqParamSets = mSeqParamSets.size();
1263        if (nSeqParamSets == 0) {
1264            LOGE("Cound not find sequence parameter set");
1265            return ERROR_MALFORMED;
1266        }
1267
1268        if (nSeqParamSets > 0x1F) {
1269            LOGE("Too many seq parameter sets (%d) found", nSeqParamSets);
1270            return ERROR_MALFORMED;
1271        }
1272    }
1273
1274    {
1275        // Check on the number of pic parameter sets
1276        size_t nPicParamSets = mPicParamSets.size();
1277        if (nPicParamSets == 0) {
1278            LOGE("Cound not find picture parameter set");
1279            return ERROR_MALFORMED;
1280        }
1281        if (nPicParamSets > 0xFF) {
1282            LOGE("Too many pic parameter sets (%d) found", nPicParamSets);
1283            return ERROR_MALFORMED;
1284        }
1285    }
1286
1287    {
1288        // Check on the profiles
1289        // These profiles requires additional parameter set extensions
1290        if (mProfileIdc == 100 || mProfileIdc == 110 ||
1291            mProfileIdc == 122 || mProfileIdc == 144) {
1292            LOGE("Sorry, no support for profile_idc: %d!", mProfileIdc);
1293            return BAD_VALUE;
1294        }
1295    }
1296
1297    return OK;
1298}
1299
1300status_t MPEG4Writer::Track::makeAVCCodecSpecificData(
1301        const uint8_t *data, size_t size) {
1302    // hexdump(data, size);
1303
1304    if (mCodecSpecificData != NULL) {
1305        LOGE("Already have codec specific data");
1306        return ERROR_MALFORMED;
1307    }
1308
1309    if (size < 4) {
1310        LOGE("Codec specific data length too short: %d", size);
1311        return ERROR_MALFORMED;
1312    }
1313
1314    // Data is in the form of AVCCodecSpecificData
1315    if (memcmp("\x00\x00\x00\x01", data, 4)) {
1316        return copyAVCCodecSpecificData(data, size);
1317    }
1318
1319    if (parseAVCCodecSpecificData(data, size) != OK) {
1320        return ERROR_MALFORMED;
1321    }
1322
1323    // ISO 14496-15: AVC file format
1324    mCodecSpecificDataSize += 7;  // 7 more bytes in the header
1325    mCodecSpecificData = malloc(mCodecSpecificDataSize);
1326    uint8_t *header = (uint8_t *)mCodecSpecificData;
1327    header[0] = 1;                     // version
1328    header[1] = mProfileIdc;           // profile indication
1329    header[2] = mProfileCompatible;    // profile compatibility
1330    header[3] = mLevelIdc;
1331
1332    // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne
1333#if USE_NALLEN_FOUR
1334    header[4] = 0xfc | 3;  // length size == 4 bytes
1335#else
1336    header[4] = 0xfc | 1;  // length size == 2 bytes
1337#endif
1338
1339    // 3-bit '111' followed by 5-bit numSequenceParameterSets
1340    int nSequenceParamSets = mSeqParamSets.size();
1341    header[5] = 0xe0 | nSequenceParamSets;
1342    header += 6;
1343    for (List<AVCParamSet>::iterator it = mSeqParamSets.begin();
1344         it != mSeqParamSets.end(); ++it) {
1345        // 16-bit sequence parameter set length
1346        uint16_t seqParamSetLength = it->mLength;
1347        header[0] = seqParamSetLength >> 8;
1348        header[1] = seqParamSetLength & 0xff;
1349
1350        // SPS NAL unit (sequence parameter length bytes)
1351        memcpy(&header[2], it->mData, seqParamSetLength);
1352        header += (2 + seqParamSetLength);
1353    }
1354
1355    // 8-bit nPictureParameterSets
1356    int nPictureParamSets = mPicParamSets.size();
1357    header[0] = nPictureParamSets;
1358    header += 1;
1359    for (List<AVCParamSet>::iterator it = mPicParamSets.begin();
1360         it != mPicParamSets.end(); ++it) {
1361        // 16-bit picture parameter set length
1362        uint16_t picParamSetLength = it->mLength;
1363        header[0] = picParamSetLength >> 8;
1364        header[1] = picParamSetLength & 0xff;
1365
1366        // PPS Nal unit (picture parameter set length bytes)
1367        memcpy(&header[2], it->mData, picParamSetLength);
1368        header += (2 + picParamSetLength);
1369    }
1370
1371    return OK;
1372}
1373
1374static bool collectStatisticalData() {
1375    char value[PROPERTY_VALUE_MAX];
1376    if (property_get("media.stagefright.record-stats", value, NULL)
1377        && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
1378        return true;
1379    }
1380    return false;
1381}
1382
1383status_t MPEG4Writer::Track::threadEntry() {
1384    int32_t count = 0;
1385    const int64_t interleaveDurationUs = mOwner->interleaveDuration();
1386    int64_t chunkTimestampUs = 0;
1387    int32_t nChunks = 0;
1388    int32_t nZeroLengthFrames = 0;
1389    int64_t lastTimestampUs = 0;  // Previous sample time stamp in ms
1390    int64_t lastDurationUs = 0;   // Between the previous two samples in ms
1391    int64_t currDurationTicks = 0;  // Timescale based ticks
1392    int64_t lastDurationTicks = 0;  // Timescale based ticks
1393    int32_t sampleCount = 1;      // Sample count in the current stts table entry
1394    uint32_t previousSampleSize = 0;  // Size of the previous sample
1395    int64_t previousPausedDurationUs = 0;
1396    int64_t timestampUs;
1397
1398    int64_t wallClockTimeUs = 0;
1399    int64_t lastWallClockTimeUs = 0;
1400
1401    sp<MetaData> meta_data;
1402    bool collectStats = collectStatisticalData();
1403
1404    mNumSamples = 0;
1405    mMaxWriteTimeUs = 0;
1406    status_t err = OK;
1407    MediaBuffer *buffer;
1408    while (!mDone && (err = mSource->read(&buffer)) == OK) {
1409        if (buffer->range_length() == 0) {
1410            buffer->release();
1411            buffer = NULL;
1412            ++nZeroLengthFrames;
1413            continue;
1414        }
1415
1416        // If the codec specific data has not been received yet, delay pause.
1417        // After the codec specific data is received, discard what we received
1418        // when the track is to be paused.
1419        if (mPaused && !mResumed) {
1420            buffer->release();
1421            buffer = NULL;
1422            continue;
1423        }
1424
1425        ++count;
1426
1427        int32_t isCodecConfig;
1428        if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig)
1429                && isCodecConfig) {
1430            CHECK(!mGotAllCodecSpecificData);
1431
1432            if (mIsAvc) {
1433                status_t err = makeAVCCodecSpecificData(
1434                        (const uint8_t *)buffer->data()
1435                            + buffer->range_offset(),
1436                        buffer->range_length());
1437                CHECK_EQ(OK, err);
1438            } else if (mIsMPEG4) {
1439                mCodecSpecificDataSize = buffer->range_length();
1440                mCodecSpecificData = malloc(mCodecSpecificDataSize);
1441                memcpy(mCodecSpecificData,
1442                        (const uint8_t *)buffer->data()
1443                            + buffer->range_offset(),
1444                       buffer->range_length());
1445            }
1446
1447            buffer->release();
1448            buffer = NULL;
1449
1450            mGotAllCodecSpecificData = true;
1451            continue;
1452        }
1453
1454        // Make a deep copy of the MediaBuffer and Metadata and release
1455        // the original as soon as we can
1456        MediaBuffer *copy = new MediaBuffer(buffer->range_length());
1457        memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(),
1458                buffer->range_length());
1459        copy->set_range(0, buffer->range_length());
1460        meta_data = new MetaData(*buffer->meta_data().get());
1461        buffer->release();
1462        buffer = NULL;
1463
1464        if (mIsAvc) StripStartcode(copy);
1465
1466        size_t sampleSize;
1467        sampleSize = mIsAvc
1468#if USE_NALLEN_FOUR
1469                ? copy->range_length() + 4
1470#else
1471                ? copy->range_length() + 2
1472#endif
1473                : copy->range_length();
1474
1475        // Max file size or duration handling
1476        mEstimatedTrackSizeBytes += sampleSize;
1477        if (mOwner->exceedsFileSizeLimit()) {
1478            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
1479            break;
1480        }
1481        if (mOwner->exceedsFileDurationLimit()) {
1482            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
1483            break;
1484        }
1485
1486
1487        int32_t isSync = false;
1488        meta_data->findInt32(kKeyIsSyncFrame, &isSync);
1489
1490        CHECK(meta_data->findInt64(kKeyTime, &timestampUs));
1491
1492////////////////////////////////////////////////////////////////////////////////
1493        if (mSampleSizes.empty()) {
1494            mStartTimestampUs = timestampUs;
1495            mOwner->setStartTimestampUs(mStartTimestampUs);
1496        }
1497
1498        if (mResumed) {
1499            previousPausedDurationUs += (timestampUs - mTrackDurationUs - lastDurationUs);
1500            mResumed = false;
1501        }
1502
1503        timestampUs -= previousPausedDurationUs;
1504        if (mIsRealTimeRecording && !mIsAudio) {
1505            // The minor adjustment on the timestamp is heuristic/experimental
1506            // We are adjusting the timestamp to reduce the fluctuation of the duration
1507            // of neighboring samples. This in turn helps reduce the track header size,
1508            // especially, the number of entries in the "stts" box.
1509            if (mNumSamples > 1) {
1510                int64_t durationUs = timestampUs + mOwner->getDriftTimeUs() - lastTimestampUs;
1511                int64_t diffUs = (durationUs > lastDurationUs)
1512                            ? durationUs - lastDurationUs
1513                            : lastDurationUs - durationUs;
1514                if (diffUs <= 5000) {  // XXX: Magic number 5ms
1515                    timestampUs = lastTimestampUs + lastDurationUs;
1516                } else {
1517                    timestampUs += mOwner->getDriftTimeUs();
1518                }
1519            }
1520        }
1521        CHECK(timestampUs >= 0);
1522        if (mNumSamples > 1) {
1523            if (timestampUs <= lastTimestampUs) {
1524                LOGW("Drop a frame, since it arrives too late!");
1525                copy->release();
1526                copy = NULL;
1527                continue;
1528            }
1529        }
1530
1531        LOGV("time stamp: %lld and previous paused duration %lld",
1532                timestampUs, previousPausedDurationUs);
1533        if (timestampUs > mTrackDurationUs) {
1534            mTrackDurationUs = timestampUs;
1535        }
1536
1537        mSampleSizes.push_back(sampleSize);
1538        ++mNumSamples;
1539        if (mNumSamples > 2) {
1540            // We need to use the time scale based ticks, rather than the
1541            // timestamp itself to determine whether we have to use a new
1542            // stts entry, since we may have rounding errors.
1543            // The calculation is intended to reduce the accumulated
1544            // rounding errors.
1545            currDurationTicks =
1546                     ((timestampUs * mTimeScale + 500000LL) / 1000000LL -
1547                     (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL);
1548
1549            if (currDurationTicks != lastDurationTicks) {
1550                SttsTableEntry sttsEntry(sampleCount, lastDurationUs);
1551                mSttsTableEntries.push_back(sttsEntry);
1552                sampleCount = 1;
1553            } else {
1554                ++sampleCount;
1555            }
1556        }
1557        if (mSamplesHaveSameSize) {
1558            if (mNumSamples >= 2 && previousSampleSize != sampleSize) {
1559                mSamplesHaveSameSize = false;
1560            }
1561            previousSampleSize = sampleSize;
1562        }
1563        lastDurationUs = timestampUs - lastTimestampUs;
1564        lastDurationTicks = currDurationTicks;
1565        lastTimestampUs = timestampUs;
1566        if (mIsRealTimeRecording && mIsAudio) {
1567            wallClockTimeUs = systemTime() / 1000;
1568            int64_t wallClockDurationUs = wallClockTimeUs - lastWallClockTimeUs;
1569            if (mNumSamples > 2) {
1570                mOwner->addDriftTimeUs(lastDurationUs - wallClockDurationUs);
1571            }
1572            lastWallClockTimeUs = wallClockTimeUs;
1573        }
1574
1575        if (isSync != 0) {
1576            mStssTableEntries.push_back(mNumSamples);
1577        }
1578
1579        if (mTrackingProgressStatus) {
1580            if (mPreviousTrackTimeUs <= 0) {
1581                mPreviousTrackTimeUs = mStartTimestampUs;
1582            }
1583            trackProgressStatus(timestampUs);
1584        }
1585        if (mOwner->numTracks() == 1) {
1586            off_t offset = mIsAvc? mOwner->addLengthPrefixedSample_l(copy)
1587                                 : mOwner->addSample_l(copy);
1588            if (mChunkOffsets.empty()) {
1589                mChunkOffsets.push_back(offset);
1590            }
1591            copy->release();
1592            copy = NULL;
1593            continue;
1594        }
1595
1596        mChunkSamples.push_back(copy);
1597        if (interleaveDurationUs == 0) {
1598            StscTableEntry stscEntry(++nChunks, 1, 1);
1599            mStscTableEntries.push_back(stscEntry);
1600            bufferChunk(timestampUs);
1601        } else {
1602            if (chunkTimestampUs == 0) {
1603                chunkTimestampUs = timestampUs;
1604            } else {
1605                if (timestampUs - chunkTimestampUs > interleaveDurationUs) {
1606                    ++nChunks;
1607                    if (collectStats) {
1608                        mChunkDurations.push_back(timestampUs - chunkTimestampUs);
1609                    }
1610                    if (nChunks == 1 ||  // First chunk
1611                        (--(mStscTableEntries.end()))->samplesPerChunk !=
1612                         mChunkSamples.size()) {
1613                        StscTableEntry stscEntry(nChunks,
1614                                mChunkSamples.size(), 1);
1615                        mStscTableEntries.push_back(stscEntry);
1616                    }
1617                    bufferChunk(timestampUs);
1618                    chunkTimestampUs = timestampUs;
1619                }
1620            }
1621        }
1622
1623    }
1624
1625    if (mSampleSizes.empty()) {
1626        err = ERROR_MALFORMED;
1627    }
1628    mOwner->trackProgressStatus(this, -1, err);
1629
1630    // Last chunk
1631    if (mOwner->numTracks() == 1) {
1632        StscTableEntry stscEntry(1, mNumSamples, 1);
1633        mStscTableEntries.push_back(stscEntry);
1634    } else if (!mChunkSamples.empty()) {
1635        ++nChunks;
1636        StscTableEntry stscEntry(nChunks, mChunkSamples.size(), 1);
1637        mStscTableEntries.push_back(stscEntry);
1638        bufferChunk(timestampUs);
1639    }
1640
1641    // We don't really know how long the last frame lasts, since
1642    // there is no frame time after it, just repeat the previous
1643    // frame's duration.
1644    if (mNumSamples == 1) {
1645        lastDurationUs = 0;  // A single sample's duration
1646    } else {
1647        ++sampleCount;  // Count for the last sample
1648    }
1649    SttsTableEntry sttsEntry(sampleCount, lastDurationUs);
1650    mSttsTableEntries.push_back(sttsEntry);
1651    mTrackDurationUs += lastDurationUs;
1652    mReachedEOS = true;
1653    LOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. Max write time: %lld us - %s",
1654            count, nZeroLengthFrames, mNumSamples, mMaxWriteTimeUs, mIsAudio? "audio": "video");
1655
1656    logStatisticalData(mIsAudio);
1657    if (err == ERROR_END_OF_STREAM) {
1658        return OK;
1659    }
1660    return err;
1661}
1662
1663void MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) {
1664    LOGV("trackProgressStatus: %lld us", timeUs);
1665    if (mTrackEveryTimeDurationUs > 0 &&
1666        timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) {
1667        LOGV("Fire time tracking progress status at %lld us", timeUs);
1668        mOwner->trackProgressStatus(this, timeUs - mPreviousTrackTimeUs, err);
1669        mPreviousTrackTimeUs = timeUs;
1670    }
1671}
1672
1673void MPEG4Writer::trackProgressStatus(
1674        const MPEG4Writer::Track* track, int64_t timeUs, status_t err) {
1675    Mutex::Autolock lock(mLock);
1676    int32_t nTracks = mTracks.size();
1677    CHECK(nTracks >= 1);
1678    CHECK(nTracks < 64);  // Arbitrary number
1679
1680    int32_t trackNum = 0;
1681#if 0
1682    // In the worst case, we can put the trackNum
1683    // along with MEDIA_RECORDER_INFO_COMPLETION_STATUS
1684    // to report the progress.
1685    for (List<Track *>::iterator it = mTracks.begin();
1686         it != mTracks.end(); ++it, ++trackNum) {
1687        if (track == (*it)) {
1688            break;
1689        }
1690    }
1691#endif
1692    CHECK(trackNum < nTracks);
1693    trackNum <<= 16;
1694
1695    // Error notification
1696    // Do not consider ERROR_END_OF_STREAM an error
1697    if (err != OK && err != ERROR_END_OF_STREAM) {
1698        notify(MEDIA_RECORDER_EVENT_ERROR,
1699               trackNum | MEDIA_RECORDER_ERROR_UNKNOWN,
1700               err);
1701        return;
1702    }
1703
1704    if (timeUs == -1) {
1705        // Send completion notification
1706        notify(MEDIA_RECORDER_EVENT_INFO,
1707               trackNum | MEDIA_RECORDER_INFO_COMPLETION_STATUS,
1708               err);
1709        return;
1710    } else {
1711        // Send progress status
1712        notify(MEDIA_RECORDER_EVENT_INFO,
1713               trackNum | MEDIA_RECORDER_INFO_PROGRESS_TIME_STATUS,
1714               timeUs / 1000);
1715    }
1716}
1717
1718void MPEG4Writer::Track::findMinAvgMaxSampleDurationMs(
1719        int32_t *min, int32_t *avg, int32_t *max) {
1720    CHECK(!mSampleSizes.empty());
1721    int32_t avgSampleDurationMs = mTrackDurationUs / 1000 / mNumSamples;
1722    int32_t minSampleDurationMs = 0x7FFFFFFF;
1723    int32_t maxSampleDurationMs = 0;
1724    for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin();
1725        it != mSttsTableEntries.end(); ++it) {
1726        int32_t sampleDurationMs =
1727            (static_cast<int32_t>(it->sampleDurationUs) + 500) / 1000;
1728        if (sampleDurationMs > maxSampleDurationMs) {
1729            maxSampleDurationMs = sampleDurationMs;
1730        } else if (sampleDurationMs < minSampleDurationMs) {
1731            minSampleDurationMs = sampleDurationMs;
1732        }
1733        LOGI("sample duration: %d ms", sampleDurationMs);
1734    }
1735    CHECK(minSampleDurationMs != 0);
1736    CHECK(avgSampleDurationMs != 0);
1737    CHECK(maxSampleDurationMs != 0);
1738    *min = minSampleDurationMs;
1739    *avg = avgSampleDurationMs;
1740    *max = maxSampleDurationMs;
1741}
1742
1743// Don't count the last duration
1744void MPEG4Writer::Track::findMinMaxChunkDurations(int64_t *min, int64_t *max) {
1745    int64_t duration = mOwner->interleaveDuration();
1746    int64_t minChunkDuration = duration;
1747    int64_t maxChunkDuration = duration;
1748    if (mChunkDurations.size() > 1) {
1749        for (List<int64_t>::iterator it = mChunkDurations.begin();
1750            it != --mChunkDurations.end(); ++it) {
1751            if (minChunkDuration > (*it)) {
1752                minChunkDuration = (*it);
1753            } else if (maxChunkDuration < (*it)) {
1754                maxChunkDuration = (*it);
1755            }
1756        }
1757    }
1758    *min = minChunkDuration;
1759    *max = maxChunkDuration;
1760}
1761
1762void MPEG4Writer::Track::logStatisticalData(bool isAudio) {
1763    if (mTrackDurationUs <= 0 || mSampleSizes.empty()) {
1764        LOGI("nothing is recorded");
1765        return;
1766    }
1767
1768    bool collectStats = collectStatisticalData();
1769
1770    if (collectStats) {
1771        LOGI("%s track - duration %lld us, total %d frames",
1772                isAudio? "audio": "video", mTrackDurationUs,
1773                mNumSamples);
1774        int32_t min, avg, max;
1775        findMinAvgMaxSampleDurationMs(&min, &avg, &max);
1776        LOGI("min/avg/max sample duration (ms): %d/%d/%d", min, avg, max);
1777        if (!isAudio) {
1778            float avgFps = 1000.0 / avg;
1779            float minFps = 1000.0 / max;
1780            float maxFps = 1000.0 / min;
1781            LOGI("min/avg/max frame rate (fps): %.2f/%.2f/%.2f",
1782                minFps, avgFps, maxFps);
1783        }
1784
1785        int64_t totalBytes = 0;
1786        for (List<size_t>::iterator it = mSampleSizes.begin();
1787            it != mSampleSizes.end(); ++it) {
1788            totalBytes += (*it);
1789        }
1790        float bitRate = (totalBytes * 8000000.0) / mTrackDurationUs;
1791        LOGI("avg bit rate (bps): %.2f", bitRate);
1792
1793        int64_t duration = mOwner->interleaveDuration();
1794        if (duration != 0) {  // If interleaving is enabled
1795            int64_t minChunk, maxChunk;
1796            findMinMaxChunkDurations(&minChunk, &maxChunk);
1797            LOGI("min/avg/max chunk duration (ms): %lld/%lld/%lld",
1798                minChunk, duration, maxChunk);
1799        }
1800    }
1801}
1802
1803void MPEG4Writer::addDriftTimeUs(int64_t driftTimeUs) {
1804    LOGV("addDriftTimeUs: %lld us", driftTimeUs);
1805    Mutex::Autolock autolock(mLock);
1806    mDriftTimeUs += driftTimeUs;
1807}
1808
1809int64_t MPEG4Writer::getDriftTimeUs() {
1810    LOGV("getDriftTimeUs: %lld us", mDriftTimeUs);
1811    Mutex::Autolock autolock(mLock);
1812    return mDriftTimeUs;
1813}
1814
1815void MPEG4Writer::Track::bufferChunk(int64_t timestampUs) {
1816    LOGV("bufferChunk");
1817
1818    int64_t startTimeUs = systemTime() / 1000;
1819    Chunk chunk(this, timestampUs, mChunkSamples);
1820    mOwner->bufferChunk(chunk);
1821    mChunkSamples.clear();
1822    int64_t endTimeUs = systemTime() / 1000;
1823    if (mMaxWriteTimeUs < endTimeUs - startTimeUs) {
1824        mMaxWriteTimeUs = endTimeUs - startTimeUs;
1825    }
1826}
1827
1828int64_t MPEG4Writer::Track::getDurationUs() const {
1829    return mTrackDurationUs;
1830}
1831
1832int64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const {
1833    return mEstimatedTrackSizeBytes;
1834}
1835
1836void MPEG4Writer::Track::writeTrackHeader(
1837        int32_t trackID, bool use32BitOffset) {
1838    const char *mime;
1839    bool success = mMeta->findCString(kKeyMIMEType, &mime);
1840    CHECK(success);
1841
1842    LOGV("%s track time scale: %d",
1843        mIsAudio? "Audio": "Video", mTimeScale);
1844
1845    time_t now = time(NULL);
1846    int32_t mvhdTimeScale = mOwner->getTimeScale();
1847    int64_t trakDurationUs = getDurationUs();
1848
1849    mOwner->beginBox("trak");
1850
1851      mOwner->beginBox("tkhd");
1852        // Flags = 7 to indicate that the track is enabled, and
1853        // part of the presentation
1854        mOwner->writeInt32(0x07);          // version=0, flags=7
1855        mOwner->writeInt32(now);           // creation time
1856        mOwner->writeInt32(now);           // modification time
1857        mOwner->writeInt32(trackID);
1858        mOwner->writeInt32(0);             // reserved
1859        int32_t tkhdDuration =
1860            (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
1861        mOwner->writeInt32(tkhdDuration);  // in mvhd timescale
1862        mOwner->writeInt32(0);             // reserved
1863        mOwner->writeInt32(0);             // reserved
1864        mOwner->writeInt16(0);             // layer
1865        mOwner->writeInt16(0);             // alternate group
1866        mOwner->writeInt16(mIsAudio ? 0x100 : 0);  // volume
1867        mOwner->writeInt16(0);             // reserved
1868
1869        mOwner->writeInt32(0x10000);       // matrix
1870        mOwner->writeInt32(0);
1871        mOwner->writeInt32(0);
1872        mOwner->writeInt32(0);
1873        mOwner->writeInt32(0x10000);
1874        mOwner->writeInt32(0);
1875        mOwner->writeInt32(0);
1876        mOwner->writeInt32(0);
1877        mOwner->writeInt32(0x40000000);
1878
1879        if (mIsAudio) {
1880            mOwner->writeInt32(0);
1881            mOwner->writeInt32(0);
1882        } else {
1883            int32_t width, height;
1884            bool success = mMeta->findInt32(kKeyWidth, &width);
1885            success = success && mMeta->findInt32(kKeyHeight, &height);
1886            CHECK(success);
1887
1888            mOwner->writeInt32(width << 16);   // 32-bit fixed-point value
1889            mOwner->writeInt32(height << 16);  // 32-bit fixed-point value
1890        }
1891      mOwner->endBox();  // tkhd
1892
1893      int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
1894      if (mStartTimestampUs != moovStartTimeUs) {
1895        mOwner->beginBox("edts");
1896          mOwner->beginBox("elst");
1897            mOwner->writeInt32(0);           // version=0, flags=0: 32-bit time
1898            mOwner->writeInt32(2);           // never ends with an empty list
1899
1900            // First elst entry: specify the starting time offset
1901            int64_t offsetUs = mStartTimestampUs - moovStartTimeUs;
1902            int32_t seg = (offsetUs * mvhdTimeScale + 5E5) / 1E6;
1903            mOwner->writeInt32(seg);         // in mvhd timecale
1904            mOwner->writeInt32(-1);          // starting time offset
1905            mOwner->writeInt32(1 << 16);     // rate = 1.0
1906
1907            // Second elst entry: specify the track duration
1908            seg = (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
1909            mOwner->writeInt32(seg);         // in mvhd timescale
1910            mOwner->writeInt32(0);
1911            mOwner->writeInt32(1 << 16);
1912          mOwner->endBox();
1913        mOwner->endBox();
1914      }
1915
1916      mOwner->beginBox("mdia");
1917
1918        mOwner->beginBox("mdhd");
1919          mOwner->writeInt32(0);             // version=0, flags=0
1920          mOwner->writeInt32(now);           // creation time
1921          mOwner->writeInt32(now);           // modification time
1922          mOwner->writeInt32(mTimeScale);    // media timescale
1923          int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6;
1924          mOwner->writeInt32(mdhdDuration);  // use media timescale
1925          // Language follows the three letter standard ISO-639-2/T
1926          // 'e', 'n', 'g' for "English", for instance.
1927          // Each character is packed as the difference between its ASCII value and 0x60.
1928          // For "English", these are 00101, 01110, 00111.
1929          // XXX: Where is the padding bit located: 0x15C7?
1930          mOwner->writeInt16(0);             // language code
1931          mOwner->writeInt16(0);             // predefined
1932        mOwner->endBox();
1933
1934        mOwner->beginBox("hdlr");
1935          mOwner->writeInt32(0);             // version=0, flags=0
1936          mOwner->writeInt32(0);             // component type: should be mhlr
1937          mOwner->writeFourcc(mIsAudio ? "soun" : "vide");  // component subtype
1938          mOwner->writeInt32(0);             // reserved
1939          mOwner->writeInt32(0);             // reserved
1940          mOwner->writeInt32(0);             // reserved
1941          // Removing "r" for the name string just makes the string 4 byte aligned
1942          mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle");  // name
1943        mOwner->endBox();
1944
1945        mOwner->beginBox("minf");
1946          if (mIsAudio) {
1947              mOwner->beginBox("smhd");
1948              mOwner->writeInt32(0);           // version=0, flags=0
1949              mOwner->writeInt16(0);           // balance
1950              mOwner->writeInt16(0);           // reserved
1951              mOwner->endBox();
1952          } else {
1953              mOwner->beginBox("vmhd");
1954              mOwner->writeInt32(0x01);        // version=0, flags=1
1955              mOwner->writeInt16(0);           // graphics mode
1956              mOwner->writeInt16(0);           // opcolor
1957              mOwner->writeInt16(0);
1958              mOwner->writeInt16(0);
1959              mOwner->endBox();
1960          }
1961
1962          mOwner->beginBox("dinf");
1963            mOwner->beginBox("dref");
1964              mOwner->writeInt32(0);  // version=0, flags=0
1965              mOwner->writeInt32(1);  // entry count (either url or urn)
1966              // The table index here refers to the sample description index
1967              // in the sample table entries.
1968              mOwner->beginBox("url ");
1969                mOwner->writeInt32(1);  // version=0, flags=1 (self-contained)
1970              mOwner->endBox();  // url
1971            mOwner->endBox();  // dref
1972          mOwner->endBox();  // dinf
1973
1974        mOwner->beginBox("stbl");
1975
1976          mOwner->beginBox("stsd");
1977            mOwner->writeInt32(0);               // version=0, flags=0
1978            mOwner->writeInt32(1);               // entry count
1979            if (mIsAudio) {
1980                const char *fourcc = NULL;
1981                if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) {
1982                    fourcc = "samr";
1983                } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
1984                    fourcc = "sawb";
1985                } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
1986                    fourcc = "mp4a";
1987                } else {
1988                    LOGE("Unknown mime type '%s'.", mime);
1989                    CHECK(!"should not be here, unknown mime type.");
1990                }
1991
1992                mOwner->beginBox(fourcc);          // audio format
1993                  mOwner->writeInt32(0);           // reserved
1994                  mOwner->writeInt16(0);           // reserved
1995                  mOwner->writeInt16(0x1);         // data ref index
1996                  mOwner->writeInt32(0);           // reserved
1997                  mOwner->writeInt32(0);           // reserved
1998                  int32_t nChannels;
1999                  CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels));
2000                  mOwner->writeInt16(nChannels);   // channel count
2001                  mOwner->writeInt16(16);          // sample size
2002                  mOwner->writeInt16(0);           // predefined
2003                  mOwner->writeInt16(0);           // reserved
2004
2005                  int32_t samplerate;
2006                  bool success = mMeta->findInt32(kKeySampleRate, &samplerate);
2007                  CHECK(success);
2008                  mOwner->writeInt32(samplerate << 16);
2009                  if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
2010                    mOwner->beginBox("esds");
2011                        CHECK(mCodecSpecificData);
2012                        CHECK(mCodecSpecificDataSize > 0);
2013
2014                        mOwner->writeInt32(0);     // version=0, flags=0
2015                        mOwner->writeInt8(0x03);   // ES_DescrTag
2016                        mOwner->writeInt8(23 + mCodecSpecificDataSize);
2017                        mOwner->writeInt16(0x0000);// ES_ID
2018                        mOwner->writeInt8(0x00);
2019
2020                        mOwner->writeInt8(0x04);   // DecoderConfigDescrTag
2021                        mOwner->writeInt8(15 + mCodecSpecificDataSize);
2022                        mOwner->writeInt8(0x40);   // objectTypeIndication ISO/IEC 14492-2
2023                        mOwner->writeInt8(0x15);   // streamType AudioStream
2024
2025                        mOwner->writeInt16(0x03);  // XXX
2026                        mOwner->writeInt8(0x00);   // buffer size 24-bit
2027                        mOwner->writeInt32(96000); // max bit rate
2028                        mOwner->writeInt32(96000); // avg bit rate
2029
2030                        mOwner->writeInt8(0x05);   // DecoderSpecificInfoTag
2031                        mOwner->writeInt8(mCodecSpecificDataSize);
2032                        mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
2033
2034                        static const uint8_t kData2[] = {
2035                            0x06,  // SLConfigDescriptorTag
2036                            0x01,
2037                            0x02
2038                        };
2039                        mOwner->write(kData2, sizeof(kData2));
2040
2041                    mOwner->endBox();  // esds
2042                  } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) ||
2043                             !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
2044                    // 3gpp2 Spec AMRSampleEntry fields
2045                    mOwner->beginBox("damr");
2046                      mOwner->writeCString("   ");  // vendor: 4 bytes
2047                      mOwner->writeInt8(0);         // decoder version
2048                      mOwner->writeInt16(0x83FF);   // mode set: all enabled
2049                      mOwner->writeInt8(0);         // mode change period
2050                      mOwner->writeInt8(1);         // frames per sample
2051                    mOwner->endBox();
2052                  }
2053                mOwner->endBox();
2054            } else {
2055                if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
2056                    mOwner->beginBox("mp4v");
2057                } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
2058                    mOwner->beginBox("s263");
2059                } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
2060                    mOwner->beginBox("avc1");
2061                } else {
2062                    LOGE("Unknown mime type '%s'.", mime);
2063                    CHECK(!"should not be here, unknown mime type.");
2064                }
2065
2066                  mOwner->writeInt32(0);           // reserved
2067                  mOwner->writeInt16(0);           // reserved
2068                  mOwner->writeInt16(1);           // data ref index
2069                  mOwner->writeInt16(0);           // predefined
2070                  mOwner->writeInt16(0);           // reserved
2071                  mOwner->writeInt32(0);           // predefined
2072                  mOwner->writeInt32(0);           // predefined
2073                  mOwner->writeInt32(0);           // predefined
2074
2075                  int32_t width, height;
2076                  bool success = mMeta->findInt32(kKeyWidth, &width);
2077                  success = success && mMeta->findInt32(kKeyHeight, &height);
2078                  CHECK(success);
2079
2080                  mOwner->writeInt16(width);
2081                  mOwner->writeInt16(height);
2082                  mOwner->writeInt32(0x480000);    // horiz resolution
2083                  mOwner->writeInt32(0x480000);    // vert resolution
2084                  mOwner->writeInt32(0);           // reserved
2085                  mOwner->writeInt16(1);           // frame count
2086                  mOwner->write("                                ", 32);
2087                  mOwner->writeInt16(0x18);        // depth
2088                  mOwner->writeInt16(-1);          // predefined
2089
2090                  CHECK(23 + mCodecSpecificDataSize < 128);
2091
2092                  if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
2093                      CHECK(mCodecSpecificData);
2094                      CHECK(mCodecSpecificDataSize > 0);
2095                      mOwner->beginBox("esds");
2096
2097                        mOwner->writeInt32(0);           // version=0, flags=0
2098
2099                        mOwner->writeInt8(0x03);  // ES_DescrTag
2100                        mOwner->writeInt8(23 + mCodecSpecificDataSize);
2101                        mOwner->writeInt16(0x0000);  // ES_ID
2102                        mOwner->writeInt8(0x1f);
2103
2104                        mOwner->writeInt8(0x04);  // DecoderConfigDescrTag
2105                        mOwner->writeInt8(15 + mCodecSpecificDataSize);
2106                        mOwner->writeInt8(0x20);  // objectTypeIndication ISO/IEC 14492-2
2107                        mOwner->writeInt8(0x11);  // streamType VisualStream
2108
2109                        static const uint8_t kData[] = {
2110                            0x01, 0x77, 0x00,
2111                            0x00, 0x03, 0xe8, 0x00,
2112                            0x00, 0x03, 0xe8, 0x00
2113                        };
2114                        mOwner->write(kData, sizeof(kData));
2115
2116                        mOwner->writeInt8(0x05);  // DecoderSpecificInfoTag
2117
2118                        mOwner->writeInt8(mCodecSpecificDataSize);
2119                        mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
2120
2121                        static const uint8_t kData2[] = {
2122                            0x06,  // SLConfigDescriptorTag
2123                            0x01,
2124                            0x02
2125                        };
2126                        mOwner->write(kData2, sizeof(kData2));
2127
2128                      mOwner->endBox();  // esds
2129                  } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
2130                      mOwner->beginBox("d263");
2131
2132                          mOwner->writeInt32(0);  // vendor
2133                          mOwner->writeInt8(0);   // decoder version
2134                          mOwner->writeInt8(10);  // level: 10
2135                          mOwner->writeInt8(0);   // profile: 0
2136
2137                      mOwner->endBox();  // d263
2138                  } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
2139                      CHECK(mCodecSpecificData);
2140                      CHECK(mCodecSpecificDataSize > 0);
2141                      mOwner->beginBox("avcC");
2142                        mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
2143                      mOwner->endBox();  // avcC
2144                  }
2145
2146                  mOwner->beginBox("pasp");
2147                    // This is useful if the pixel is not square
2148                    mOwner->writeInt32(1 << 16);  // hspacing
2149                    mOwner->writeInt32(1 << 16);  // vspacing
2150                  mOwner->endBox();  // pasp
2151                mOwner->endBox();  // mp4v, s263 or avc1
2152            }
2153          mOwner->endBox();  // stsd
2154
2155          mOwner->beginBox("stts");
2156            mOwner->writeInt32(0);  // version=0, flags=0
2157            mOwner->writeInt32(mSttsTableEntries.size());
2158            int64_t prevTimestampUs = 0;
2159            for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin();
2160                 it != mSttsTableEntries.end(); ++it) {
2161                mOwner->writeInt32(it->sampleCount);
2162
2163                // Make sure that we are calculating the sample duration the exactly
2164                // same way as we made decision on how to create stts entries.
2165                int64_t currTimestampUs = prevTimestampUs + it->sampleDurationUs;
2166                int32_t dur = ((currTimestampUs * mTimeScale + 500000LL) / 1000000LL -
2167                               (prevTimestampUs * mTimeScale + 500000LL) / 1000000LL);
2168                prevTimestampUs += (it->sampleCount * it->sampleDurationUs);
2169
2170                mOwner->writeInt32(dur);
2171            }
2172          mOwner->endBox();  // stts
2173
2174          if (!mIsAudio) {
2175            mOwner->beginBox("stss");
2176              mOwner->writeInt32(0);  // version=0, flags=0
2177              mOwner->writeInt32(mStssTableEntries.size());  // number of sync frames
2178              for (List<int32_t>::iterator it = mStssTableEntries.begin();
2179                   it != mStssTableEntries.end(); ++it) {
2180                  mOwner->writeInt32(*it);
2181              }
2182            mOwner->endBox();  // stss
2183          }
2184
2185          mOwner->beginBox("stsz");
2186            mOwner->writeInt32(0);  // version=0, flags=0
2187            if (mSamplesHaveSameSize) {
2188                List<size_t>::iterator it = mSampleSizes.begin();
2189                mOwner->writeInt32(*it);  // default sample size
2190            } else {
2191                mOwner->writeInt32(0);
2192            }
2193            mOwner->writeInt32(mNumSamples);
2194            if (!mSamplesHaveSameSize) {
2195                for (List<size_t>::iterator it = mSampleSizes.begin();
2196                     it != mSampleSizes.end(); ++it) {
2197                    mOwner->writeInt32(*it);
2198                }
2199            }
2200          mOwner->endBox();  // stsz
2201
2202          mOwner->beginBox("stsc");
2203            mOwner->writeInt32(0);  // version=0, flags=0
2204            mOwner->writeInt32(mStscTableEntries.size());
2205            for (List<StscTableEntry>::iterator it = mStscTableEntries.begin();
2206                 it != mStscTableEntries.end(); ++it) {
2207                mOwner->writeInt32(it->firstChunk);
2208                mOwner->writeInt32(it->samplesPerChunk);
2209                mOwner->writeInt32(it->sampleDescriptionId);
2210            }
2211          mOwner->endBox();  // stsc
2212          mOwner->beginBox(use32BitOffset? "stco": "co64");
2213            mOwner->writeInt32(0);  // version=0, flags=0
2214            mOwner->writeInt32(mChunkOffsets.size());
2215            for (List<off_t>::iterator it = mChunkOffsets.begin();
2216                 it != mChunkOffsets.end(); ++it) {
2217                if (use32BitOffset) {
2218                    mOwner->writeInt32(static_cast<int32_t>(*it));
2219                } else {
2220                    mOwner->writeInt64((*it));
2221                }
2222            }
2223          mOwner->endBox();  // stco or co64
2224
2225        mOwner->endBox();  // stbl
2226       mOwner->endBox();  // minf
2227      mOwner->endBox();  // mdia
2228    mOwner->endBox();  // trak
2229}
2230
2231}  // namespace android
2232