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