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