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