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