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