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