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