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