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