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