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