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