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