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