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