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