MPEG4Writer.cpp revision 4c845fde3d60ad93984879f69b164e35536e080d
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 <inttypes.h>
20#include <utils/Log.h>
21
22#include <arpa/inet.h>
23
24#include <pthread.h>
25#include <sys/prctl.h>
26
27#include <media/stagefright/foundation/ADebug.h>
28#include <media/stagefright/MPEG4Writer.h>
29#include <media/stagefright/MediaBuffer.h>
30#include <media/stagefright/MetaData.h>
31#include <media/stagefright/MediaDefs.h>
32#include <media/stagefright/MediaErrors.h>
33#include <media/stagefright/MediaSource.h>
34#include <media/stagefright/Utils.h>
35#include <media/mediarecorder.h>
36#include <cutils/properties.h>
37#include <sys/types.h>
38#include <sys/stat.h>
39#include <fcntl.h>
40#include <unistd.h>
41
42#include "include/ESDS.h"
43
44namespace android {
45
46static const int64_t kMinStreamableFileSizeInBytes = 5 * 1024 * 1024;
47static const int64_t kMax32BitFileSize = 0x007fffffffLL;
48static const uint8_t kNalUnitTypeSeqParamSet = 0x07;
49static const uint8_t kNalUnitTypePicParamSet = 0x08;
50static const int64_t kInitialDelayTimeUs     = 700000LL;
51
52class MPEG4Writer::Track {
53public:
54    Track(MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId);
55
56    ~Track();
57
58    status_t start(MetaData *params);
59    status_t stop();
60    status_t pause();
61    bool reachedEOS();
62
63    int64_t getDurationUs() const;
64    int64_t getEstimatedTrackSizeBytes() const;
65    void writeTrackHeader(bool use32BitOffset = true);
66    void bufferChunk(int64_t timestampUs);
67    bool isAvc() const { return mIsAvc; }
68    bool isAudio() const { return mIsAudio; }
69    bool isMPEG4() const { return mIsMPEG4; }
70    void addChunkOffset(off64_t offset);
71    int32_t getTrackId() const { return mTrackId; }
72    status_t dump(int fd, const Vector<String16>& args) const;
73
74private:
75    enum {
76        kMaxCttsOffsetTimeUs = 1000000LL,  // 1 second
77        kSampleArraySize = 1000,
78    };
79
80    // A helper class to handle faster write box with table entries
81    template<class TYPE>
82    struct ListTableEntries {
83        ListTableEntries(uint32_t elementCapacity, uint32_t entryCapacity)
84            : mElementCapacity(elementCapacity),
85            mEntryCapacity(entryCapacity),
86            mTotalNumTableEntries(0),
87            mNumValuesInCurrEntry(0),
88            mCurrTableEntriesElement(NULL) {
89            CHECK_GT(mElementCapacity, 0);
90            CHECK_GT(mEntryCapacity, 0);
91        }
92
93        // Free the allocated memory.
94        ~ListTableEntries() {
95            while (!mTableEntryList.empty()) {
96                typename List<TYPE *>::iterator it = mTableEntryList.begin();
97                delete[] (*it);
98                mTableEntryList.erase(it);
99            }
100        }
101
102        // Replace the value at the given position by the given value.
103        // There must be an existing value at the given position.
104        // @arg value must be in network byte order
105        // @arg pos location the value must be in.
106        void set(const TYPE& value, uint32_t pos) {
107            CHECK_LT(pos, mTotalNumTableEntries * mEntryCapacity);
108
109            typename List<TYPE *>::iterator it = mTableEntryList.begin();
110            uint32_t iterations = (pos / (mElementCapacity * mEntryCapacity));
111            while (it != mTableEntryList.end() && iterations > 0) {
112                ++it;
113                --iterations;
114            }
115            CHECK(it != mTableEntryList.end());
116            CHECK_EQ(iterations, 0);
117
118            (*it)[(pos % (mElementCapacity * mEntryCapacity))] = value;
119        }
120
121        // Get the value at the given position by the given value.
122        // @arg value the retrieved value at the position in network byte order.
123        // @arg pos location the value must be in.
124        // @return true if a value is found.
125        bool get(TYPE& value, uint32_t pos) const {
126            if (pos >= mTotalNumTableEntries * mEntryCapacity) {
127                return false;
128            }
129
130            typename List<TYPE *>::iterator it = mTableEntryList.begin();
131            uint32_t iterations = (pos / (mElementCapacity * mEntryCapacity));
132            while (it != mTableEntryList.end() && iterations > 0) {
133                ++it;
134                --iterations;
135            }
136            CHECK(it != mTableEntryList.end());
137            CHECK_EQ(iterations, 0);
138
139            value = (*it)[(pos % (mElementCapacity * mEntryCapacity))];
140            return true;
141        }
142
143        // Store a single value.
144        // @arg value must be in network byte order.
145        void add(const TYPE& value) {
146            CHECK_LT(mNumValuesInCurrEntry, mElementCapacity);
147            uint32_t nEntries = mTotalNumTableEntries % mElementCapacity;
148            uint32_t nValues  = mNumValuesInCurrEntry % mEntryCapacity;
149            if (nEntries == 0 && nValues == 0) {
150                mCurrTableEntriesElement = new TYPE[mEntryCapacity * mElementCapacity];
151                CHECK(mCurrTableEntriesElement != NULL);
152                mTableEntryList.push_back(mCurrTableEntriesElement);
153            }
154
155            uint32_t pos = nEntries * mEntryCapacity + nValues;
156            mCurrTableEntriesElement[pos] = value;
157
158            ++mNumValuesInCurrEntry;
159            if ((mNumValuesInCurrEntry % mEntryCapacity) == 0) {
160                ++mTotalNumTableEntries;
161                mNumValuesInCurrEntry = 0;
162            }
163        }
164
165        // Write out the table entries:
166        // 1. the number of entries goes first
167        // 2. followed by the values in the table enties in order
168        // @arg writer the writer to actual write to the storage
169        void write(MPEG4Writer *writer) const {
170            CHECK_EQ(mNumValuesInCurrEntry % mEntryCapacity, 0);
171            uint32_t nEntries = mTotalNumTableEntries;
172            writer->writeInt32(nEntries);
173            for (typename List<TYPE *>::iterator it = mTableEntryList.begin();
174                it != mTableEntryList.end(); ++it) {
175                CHECK_GT(nEntries, 0);
176                if (nEntries >= mElementCapacity) {
177                    writer->write(*it, sizeof(TYPE) * mEntryCapacity, mElementCapacity);
178                    nEntries -= mElementCapacity;
179                } else {
180                    writer->write(*it, sizeof(TYPE) * mEntryCapacity, nEntries);
181                    break;
182                }
183            }
184        }
185
186        // Return the number of entries in the table.
187        uint32_t count() const { return mTotalNumTableEntries; }
188
189    private:
190        uint32_t         mElementCapacity;  // # entries in an element
191        uint32_t         mEntryCapacity;    // # of values in each entry
192        uint32_t         mTotalNumTableEntries;
193        uint32_t         mNumValuesInCurrEntry;  // up to mEntryCapacity
194        TYPE             *mCurrTableEntriesElement;
195        mutable List<TYPE *>     mTableEntryList;
196
197        DISALLOW_EVIL_CONSTRUCTORS(ListTableEntries);
198    };
199
200
201
202    MPEG4Writer *mOwner;
203    sp<MetaData> mMeta;
204    sp<MediaSource> mSource;
205    volatile bool mDone;
206    volatile bool mPaused;
207    volatile bool mResumed;
208    volatile bool mStarted;
209    bool mIsAvc;
210    bool mIsAudio;
211    bool mIsMPEG4;
212    int32_t mTrackId;
213    int64_t mTrackDurationUs;
214    int64_t mMaxChunkDurationUs;
215
216    int64_t mEstimatedTrackSizeBytes;
217    int64_t mMdatSizeBytes;
218    int32_t mTimeScale;
219
220    pthread_t mThread;
221
222
223    List<MediaBuffer *> mChunkSamples;
224
225    bool                mSamplesHaveSameSize;
226    ListTableEntries<uint32_t> *mStszTableEntries;
227
228    ListTableEntries<uint32_t> *mStcoTableEntries;
229    ListTableEntries<off64_t> *mCo64TableEntries;
230    ListTableEntries<uint32_t> *mStscTableEntries;
231    ListTableEntries<uint32_t> *mStssTableEntries;
232    ListTableEntries<uint32_t> *mSttsTableEntries;
233    ListTableEntries<uint32_t> *mCttsTableEntries;
234
235    int64_t mMinCttsOffsetTimeUs;
236    int64_t mMaxCttsOffsetTimeUs;
237
238    // Sequence parameter set or picture parameter set
239    struct AVCParamSet {
240        AVCParamSet(uint16_t length, const uint8_t *data)
241            : mLength(length), mData(data) {}
242
243        uint16_t mLength;
244        const uint8_t *mData;
245    };
246    List<AVCParamSet> mSeqParamSets;
247    List<AVCParamSet> mPicParamSets;
248    uint8_t mProfileIdc;
249    uint8_t mProfileCompatible;
250    uint8_t mLevelIdc;
251
252    void *mCodecSpecificData;
253    size_t mCodecSpecificDataSize;
254    bool mGotAllCodecSpecificData;
255    bool mTrackingProgressStatus;
256
257    bool mReachedEOS;
258    int64_t mStartTimestampUs;
259    int64_t mStartTimeRealUs;
260    int64_t mFirstSampleTimeRealUs;
261    int64_t mPreviousTrackTimeUs;
262    int64_t mTrackEveryTimeDurationUs;
263
264    // Update the audio track's drift information.
265    void updateDriftTime(const sp<MetaData>& meta);
266
267    int32_t getStartTimeOffsetScaledTime() const;
268
269    static void *ThreadWrapper(void *me);
270    status_t threadEntry();
271
272    const uint8_t *parseParamSet(
273        const uint8_t *data, size_t length, int type, size_t *paramSetLen);
274
275    status_t makeAVCCodecSpecificData(const uint8_t *data, size_t size);
276    status_t copyAVCCodecSpecificData(const uint8_t *data, size_t size);
277    status_t parseAVCCodecSpecificData(const uint8_t *data, size_t size);
278
279    // Track authoring progress status
280    void trackProgressStatus(int64_t timeUs, status_t err = OK);
281    void initTrackingProgressStatus(MetaData *params);
282
283    void getCodecSpecificDataFromInputFormatIfPossible();
284
285    // Determine the track time scale
286    // If it is an audio track, try to use the sampling rate as
287    // the time scale; however, if user chooses the overwrite
288    // value, the user-supplied time scale will be used.
289    void setTimeScale();
290
291    // Simple validation on the codec specific data
292    status_t checkCodecSpecificData() const;
293    int32_t mRotation;
294
295    void updateTrackSizeEstimate();
296    void addOneStscTableEntry(size_t chunkId, size_t sampleId);
297    void addOneStssTableEntry(size_t sampleId);
298
299    // Duration is time scale based
300    void addOneSttsTableEntry(size_t sampleCount, int32_t timescaledDur);
301    void addOneCttsTableEntry(size_t sampleCount, int32_t timescaledDur);
302
303    bool isTrackMalFormed() const;
304    void sendTrackSummary(bool hasMultipleTracks);
305
306    // Write the boxes
307    void writeStcoBox(bool use32BitOffset);
308    void writeStscBox();
309    void writeStszBox();
310    void writeStssBox();
311    void writeSttsBox();
312    void writeCttsBox();
313    void writeD263Box();
314    void writePaspBox();
315    void writeAvccBox();
316    void writeUrlBox();
317    void writeDrefBox();
318    void writeDinfBox();
319    void writeDamrBox();
320    void writeMdhdBox(uint32_t now);
321    void writeSmhdBox();
322    void writeVmhdBox();
323    void writeHdlrBox();
324    void writeTkhdBox(uint32_t now);
325    void writeMp4aEsdsBox();
326    void writeMp4vEsdsBox();
327    void writeAudioFourCCBox();
328    void writeVideoFourCCBox();
329    void writeStblBox(bool use32BitOffset);
330
331    Track(const Track &);
332    Track &operator=(const Track &);
333};
334
335MPEG4Writer::MPEG4Writer(const char *filename)
336    : mFd(-1),
337      mInitCheck(NO_INIT),
338      mIsRealTimeRecording(true),
339      mUse4ByteNalLength(true),
340      mUse32BitOffset(true),
341      mIsFileSizeLimitExplicitlyRequested(false),
342      mPaused(false),
343      mStarted(false),
344      mWriterThreadStarted(false),
345      mOffset(0),
346      mMdatOffset(0),
347      mEstimatedMoovBoxSize(0),
348      mInterleaveDurationUs(1000000),
349      mLatitudex10000(0),
350      mLongitudex10000(0),
351      mAreGeoTagsAvailable(false),
352      mStartTimeOffsetMs(-1) {
353
354    mFd = open(filename, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
355    if (mFd >= 0) {
356        mInitCheck = OK;
357    }
358}
359
360MPEG4Writer::MPEG4Writer(int fd)
361    : mFd(dup(fd)),
362      mInitCheck(mFd < 0? NO_INIT: OK),
363      mIsRealTimeRecording(true),
364      mUse4ByteNalLength(true),
365      mUse32BitOffset(true),
366      mIsFileSizeLimitExplicitlyRequested(false),
367      mPaused(false),
368      mStarted(false),
369      mWriterThreadStarted(false),
370      mOffset(0),
371      mMdatOffset(0),
372      mEstimatedMoovBoxSize(0),
373      mInterleaveDurationUs(1000000),
374      mLatitudex10000(0),
375      mLongitudex10000(0),
376      mAreGeoTagsAvailable(false),
377      mStartTimeOffsetMs(-1) {
378}
379
380MPEG4Writer::~MPEG4Writer() {
381    reset();
382
383    while (!mTracks.empty()) {
384        List<Track *>::iterator it = mTracks.begin();
385        delete *it;
386        (*it) = NULL;
387        mTracks.erase(it);
388    }
389    mTracks.clear();
390}
391
392status_t MPEG4Writer::dump(
393        int fd, const Vector<String16>& args) {
394    const size_t SIZE = 256;
395    char buffer[SIZE];
396    String8 result;
397    snprintf(buffer, SIZE, "   MPEG4Writer %p\n", this);
398    result.append(buffer);
399    snprintf(buffer, SIZE, "     mStarted: %s\n", mStarted? "true": "false");
400    result.append(buffer);
401    ::write(fd, result.string(), result.size());
402    for (List<Track *>::iterator it = mTracks.begin();
403         it != mTracks.end(); ++it) {
404        (*it)->dump(fd, args);
405    }
406    return OK;
407}
408
409status_t MPEG4Writer::Track::dump(
410        int fd, const Vector<String16>& args) const {
411    const size_t SIZE = 256;
412    char buffer[SIZE];
413    String8 result;
414    snprintf(buffer, SIZE, "     %s track\n", mIsAudio? "Audio": "Video");
415    result.append(buffer);
416    snprintf(buffer, SIZE, "       reached EOS: %s\n",
417            mReachedEOS? "true": "false");
418    result.append(buffer);
419    snprintf(buffer, SIZE, "       frames encoded : %d\n", mStszTableEntries->count());
420    result.append(buffer);
421    snprintf(buffer, SIZE, "       duration encoded : %" PRId64 " us\n", mTrackDurationUs);
422    result.append(buffer);
423    ::write(fd, result.string(), result.size());
424    return OK;
425}
426
427status_t MPEG4Writer::addSource(const sp<MediaSource> &source) {
428    Mutex::Autolock l(mLock);
429    if (mStarted) {
430        ALOGE("Attempt to add source AFTER recording is started");
431        return UNKNOWN_ERROR;
432    }
433
434    // At most 2 tracks can be supported.
435    if (mTracks.size() >= 2) {
436        ALOGE("Too many tracks (%d) to add", mTracks.size());
437        return ERROR_UNSUPPORTED;
438    }
439
440    CHECK(source.get() != NULL);
441
442    // A track of type other than video or audio is not supported.
443    const char *mime;
444    source->getFormat()->findCString(kKeyMIMEType, &mime);
445    bool isAudio = !strncasecmp(mime, "audio/", 6);
446    bool isVideo = !strncasecmp(mime, "video/", 6);
447    if (!isAudio && !isVideo) {
448        ALOGE("Track (%s) other than video or audio is not supported",
449            mime);
450        return ERROR_UNSUPPORTED;
451    }
452
453    // At this point, we know the track to be added is either
454    // video or audio. Thus, we only need to check whether it
455    // is an audio track or not (if it is not, then it must be
456    // a video track).
457
458    // No more than one video or one audio track is supported.
459    for (List<Track*>::iterator it = mTracks.begin();
460         it != mTracks.end(); ++it) {
461        if ((*it)->isAudio() == isAudio) {
462            ALOGE("%s track already exists", isAudio? "Audio": "Video");
463            return ERROR_UNSUPPORTED;
464        }
465    }
466
467    // This is the first track of either audio or video.
468    // Go ahead to add the track.
469    Track *track = new Track(this, source, 1 + mTracks.size());
470    mTracks.push_back(track);
471
472    return OK;
473}
474
475status_t MPEG4Writer::startTracks(MetaData *params) {
476    if (mTracks.empty()) {
477        ALOGE("No source added");
478        return INVALID_OPERATION;
479    }
480
481    for (List<Track *>::iterator it = mTracks.begin();
482         it != mTracks.end(); ++it) {
483        status_t err = (*it)->start(params);
484
485        if (err != OK) {
486            for (List<Track *>::iterator it2 = mTracks.begin();
487                 it2 != it; ++it2) {
488                (*it2)->stop();
489            }
490
491            return err;
492        }
493    }
494    return OK;
495}
496
497int64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) {
498    // This implementation is highly experimental/heurisitic.
499    //
500    // Statistical analysis shows that metadata usually accounts
501    // for a small portion of the total file size, usually < 0.6%.
502
503    // The default MIN_MOOV_BOX_SIZE is set to 0.6% x 1MB / 2,
504    // where 1MB is the common file size limit for MMS application.
505    // The default MAX _MOOV_BOX_SIZE value is based on about 3
506    // minute video recording with a bit rate about 3 Mbps, because
507    // statistics also show that most of the video captured are going
508    // to be less than 3 minutes.
509
510    // If the estimation is wrong, we will pay the price of wasting
511    // some reserved space. This should not happen so often statistically.
512    static const int32_t factor = mUse32BitOffset? 1: 2;
513    static const int64_t MIN_MOOV_BOX_SIZE = 3 * 1024;  // 3 KB
514    static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000);
515    int64_t size = MIN_MOOV_BOX_SIZE;
516
517    // Max file size limit is set
518    if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
519        size = mMaxFileSizeLimitBytes * 6 / 1000;
520    }
521
522    // Max file duration limit is set
523    if (mMaxFileDurationLimitUs != 0) {
524        if (bitRate > 0) {
525            int64_t size2 =
526                ((mMaxFileDurationLimitUs * bitRate * 6) / 1000 / 8000000);
527            if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
528                // When both file size and duration limits are set,
529                // we use the smaller limit of the two.
530                if (size > size2) {
531                    size = size2;
532                }
533            } else {
534                // Only max file duration limit is set
535                size = size2;
536            }
537        }
538    }
539
540    if (size < MIN_MOOV_BOX_SIZE) {
541        size = MIN_MOOV_BOX_SIZE;
542    }
543
544    // Any long duration recording will be probably end up with
545    // non-streamable mp4 file.
546    if (size > MAX_MOOV_BOX_SIZE) {
547        size = MAX_MOOV_BOX_SIZE;
548    }
549
550    ALOGI("limits: %lld/%lld bytes/us, bit rate: %d bps and the estimated"
551         " moov size %lld bytes",
552         mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size);
553    return factor * size;
554}
555
556status_t MPEG4Writer::start(MetaData *param) {
557    if (mInitCheck != OK) {
558        return UNKNOWN_ERROR;
559    }
560
561    /*
562     * Check mMaxFileSizeLimitBytes at the beginning
563     * since mMaxFileSizeLimitBytes may be implicitly
564     * changed later for 32-bit file offset even if
565     * user does not ask to set it explicitly.
566     */
567    if (mMaxFileSizeLimitBytes != 0) {
568        mIsFileSizeLimitExplicitlyRequested = true;
569    }
570
571    int32_t use64BitOffset;
572    if (param &&
573        param->findInt32(kKey64BitFileOffset, &use64BitOffset) &&
574        use64BitOffset) {
575        mUse32BitOffset = false;
576    }
577
578    if (mUse32BitOffset) {
579        // Implicit 32 bit file size limit
580        if (mMaxFileSizeLimitBytes == 0) {
581            mMaxFileSizeLimitBytes = kMax32BitFileSize;
582        }
583
584        // If file size is set to be larger than the 32 bit file
585        // size limit, treat it as an error.
586        if (mMaxFileSizeLimitBytes > kMax32BitFileSize) {
587            ALOGW("32-bit file size limit (%lld bytes) too big. "
588                 "It is changed to %lld bytes",
589                mMaxFileSizeLimitBytes, kMax32BitFileSize);
590            mMaxFileSizeLimitBytes = kMax32BitFileSize;
591        }
592    }
593
594    int32_t use2ByteNalLength;
595    if (param &&
596        param->findInt32(kKey2ByteNalLength, &use2ByteNalLength) &&
597        use2ByteNalLength) {
598        mUse4ByteNalLength = false;
599    }
600
601    int32_t isRealTimeRecording;
602    if (param && param->findInt32(kKeyRealTimeRecording, &isRealTimeRecording)) {
603        mIsRealTimeRecording = isRealTimeRecording;
604    }
605
606    mStartTimestampUs = -1;
607
608    if (mStarted) {
609        if (mPaused) {
610            mPaused = false;
611            return startTracks(param);
612        }
613        return OK;
614    }
615
616    if (!param ||
617        !param->findInt32(kKeyTimeScale, &mTimeScale)) {
618        mTimeScale = 1000;
619    }
620    CHECK_GT(mTimeScale, 0);
621    ALOGV("movie time scale: %d", mTimeScale);
622
623    /*
624     * When the requested file size limit is small, the priority
625     * is to meet the file size limit requirement, rather than
626     * to make the file streamable. mStreamableFile does not tell
627     * whether the actual recorded file is streamable or not.
628     */
629    mStreamableFile =
630        (mMaxFileSizeLimitBytes != 0 &&
631         mMaxFileSizeLimitBytes >= kMinStreamableFileSizeInBytes);
632
633    /*
634     * mWriteMoovBoxToMemory is true if the amount of data in moov box is
635     * smaller than the reserved free space at the beginning of a file, AND
636     * when the content of moov box is constructed. Note that video/audio
637     * frame data is always written to the file but not in the memory.
638     *
639     * Before stop()/reset() is called, mWriteMoovBoxToMemory is always
640     * false. When reset() is called at the end of a recording session,
641     * Moov box needs to be constructed.
642     *
643     * 1) Right before a moov box is constructed, mWriteMoovBoxToMemory
644     * to set to mStreamableFile so that if
645     * the file is intended to be streamable, it is set to true;
646     * otherwise, it is set to false. When the value is set to false,
647     * all the content of the moov box is written immediately to
648     * the end of the file. When the value is set to true, all the
649     * content of the moov box is written to an in-memory cache,
650     * mMoovBoxBuffer, util the following condition happens. Note
651     * that the size of the in-memory cache is the same as the
652     * reserved free space at the beginning of the file.
653     *
654     * 2) While the data of the moov box is written to an in-memory
655     * cache, the data size is checked against the reserved space.
656     * If the data size surpasses the reserved space, subsequent moov
657     * data could no longer be hold in the in-memory cache. This also
658     * indicates that the reserved space was too small. At this point,
659     * _all_ moov data must be written to the end of the file.
660     * mWriteMoovBoxToMemory must be set to false to direct the write
661     * to the file.
662     *
663     * 3) If the data size in moov box is smaller than the reserved
664     * space after moov box is completely constructed, the in-memory
665     * cache copy of the moov box is written to the reserved free
666     * space. Thus, immediately after the moov is completedly
667     * constructed, mWriteMoovBoxToMemory is always set to false.
668     */
669    mWriteMoovBoxToMemory = false;
670    mMoovBoxBuffer = NULL;
671    mMoovBoxBufferOffset = 0;
672
673    writeFtypBox(param);
674
675    mFreeBoxOffset = mOffset;
676
677    if (mEstimatedMoovBoxSize == 0) {
678        int32_t bitRate = -1;
679        if (param) {
680            param->findInt32(kKeyBitRate, &bitRate);
681        }
682        mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate);
683    }
684    CHECK_GE(mEstimatedMoovBoxSize, 8);
685    if (mStreamableFile) {
686        // Reserve a 'free' box only for streamable file
687        lseek64(mFd, mFreeBoxOffset, SEEK_SET);
688        writeInt32(mEstimatedMoovBoxSize);
689        write("free", 4);
690        mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize;
691    } else {
692        mMdatOffset = mOffset;
693    }
694
695    mOffset = mMdatOffset;
696    lseek64(mFd, mMdatOffset, SEEK_SET);
697    if (mUse32BitOffset) {
698        write("????mdat", 8);
699    } else {
700        write("\x00\x00\x00\x01mdat????????", 16);
701    }
702
703    status_t err = startWriterThread();
704    if (err != OK) {
705        return err;
706    }
707
708    err = startTracks(param);
709    if (err != OK) {
710        return err;
711    }
712
713    mStarted = true;
714    return OK;
715}
716
717bool MPEG4Writer::use32BitFileOffset() const {
718    return mUse32BitOffset;
719}
720
721status_t MPEG4Writer::pause() {
722    if (mInitCheck != OK) {
723        return OK;
724    }
725    mPaused = true;
726    status_t err = OK;
727    for (List<Track *>::iterator it = mTracks.begin();
728         it != mTracks.end(); ++it) {
729        status_t status = (*it)->pause();
730        if (status != OK) {
731            err = status;
732        }
733    }
734    return err;
735}
736
737void MPEG4Writer::stopWriterThread() {
738    ALOGD("Stopping writer thread");
739    if (!mWriterThreadStarted) {
740        return;
741    }
742
743    {
744        Mutex::Autolock autolock(mLock);
745
746        mDone = true;
747        mChunkReadyCondition.signal();
748    }
749
750    void *dummy;
751    pthread_join(mThread, &dummy);
752    mWriterThreadStarted = false;
753    ALOGD("Writer thread stopped");
754}
755
756/*
757 * MP4 file standard defines a composition matrix:
758 * | a  b  u |
759 * | c  d  v |
760 * | x  y  w |
761 *
762 * the element in the matrix is stored in the following
763 * order: {a, b, u, c, d, v, x, y, w},
764 * where a, b, c, d, x, and y is in 16.16 format, while
765 * u, v and w is in 2.30 format.
766 */
767void MPEG4Writer::writeCompositionMatrix(int degrees) {
768    ALOGV("writeCompositionMatrix");
769    uint32_t a = 0x00010000;
770    uint32_t b = 0;
771    uint32_t c = 0;
772    uint32_t d = 0x00010000;
773    switch (degrees) {
774        case 0:
775            break;
776        case 90:
777            a = 0;
778            b = 0x00010000;
779            c = 0xFFFF0000;
780            d = 0;
781            break;
782        case 180:
783            a = 0xFFFF0000;
784            d = 0xFFFF0000;
785            break;
786        case 270:
787            a = 0;
788            b = 0xFFFF0000;
789            c = 0x00010000;
790            d = 0;
791            break;
792        default:
793            CHECK(!"Should never reach this unknown rotation");
794            break;
795    }
796
797    writeInt32(a);           // a
798    writeInt32(b);           // b
799    writeInt32(0);           // u
800    writeInt32(c);           // c
801    writeInt32(d);           // d
802    writeInt32(0);           // v
803    writeInt32(0);           // x
804    writeInt32(0);           // y
805    writeInt32(0x40000000);  // w
806}
807
808void MPEG4Writer::release() {
809    close(mFd);
810    mFd = -1;
811    mInitCheck = NO_INIT;
812    mStarted = false;
813    free(mMoovBoxBuffer);
814    mMoovBoxBuffer = NULL;
815}
816
817status_t MPEG4Writer::reset() {
818    if (mInitCheck != OK) {
819        return OK;
820    } else {
821        if (!mWriterThreadStarted ||
822            !mStarted) {
823            if (mWriterThreadStarted) {
824                stopWriterThread();
825            }
826            release();
827            return OK;
828        }
829    }
830
831    status_t err = OK;
832    int64_t maxDurationUs = 0;
833    int64_t minDurationUs = 0x7fffffffffffffffLL;
834    for (List<Track *>::iterator it = mTracks.begin();
835         it != mTracks.end(); ++it) {
836        status_t status = (*it)->stop();
837        if (err == OK && status != OK) {
838            err = status;
839        }
840
841        int64_t durationUs = (*it)->getDurationUs();
842        if (durationUs > maxDurationUs) {
843            maxDurationUs = durationUs;
844        }
845        if (durationUs < minDurationUs) {
846            minDurationUs = durationUs;
847        }
848    }
849
850    if (mTracks.size() > 1) {
851        ALOGD("Duration from tracks range is [%lld, %lld] us",
852            minDurationUs, maxDurationUs);
853    }
854
855    stopWriterThread();
856
857    // Do not write out movie header on error.
858    if (err != OK) {
859        release();
860        return err;
861    }
862
863    // Fix up the size of the 'mdat' chunk.
864    if (mUse32BitOffset) {
865        lseek64(mFd, mMdatOffset, SEEK_SET);
866        int32_t size = htonl(static_cast<int32_t>(mOffset - mMdatOffset));
867        ::write(mFd, &size, 4);
868    } else {
869        lseek64(mFd, mMdatOffset + 8, SEEK_SET);
870        int64_t size = mOffset - mMdatOffset;
871        size = hton64(size);
872        ::write(mFd, &size, 8);
873    }
874    lseek64(mFd, mOffset, SEEK_SET);
875
876    // Construct moov box now
877    mMoovBoxBufferOffset = 0;
878    mWriteMoovBoxToMemory = mStreamableFile;
879    if (mWriteMoovBoxToMemory) {
880        // There is no need to allocate in-memory cache
881        // for moov box if the file is not streamable.
882
883        mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize);
884        CHECK(mMoovBoxBuffer != NULL);
885    }
886    writeMoovBox(maxDurationUs);
887
888    // mWriteMoovBoxToMemory could be set to false in
889    // MPEG4Writer::write() method
890    if (mWriteMoovBoxToMemory) {
891        mWriteMoovBoxToMemory = false;
892        // Content of the moov box is saved in the cache, and the in-memory
893        // moov box needs to be written to the file in a single shot.
894
895        CHECK_LE(mMoovBoxBufferOffset + 8, mEstimatedMoovBoxSize);
896
897        // Moov box
898        lseek64(mFd, mFreeBoxOffset, SEEK_SET);
899        mOffset = mFreeBoxOffset;
900        write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset);
901
902        // Free box
903        lseek64(mFd, mOffset, SEEK_SET);
904        writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset);
905        write("free", 4);
906    } else {
907        ALOGI("The mp4 file will not be streamable.");
908    }
909
910    // Free in-memory cache for moov box
911    if (mMoovBoxBuffer != NULL) {
912        free(mMoovBoxBuffer);
913        mMoovBoxBuffer = NULL;
914        mMoovBoxBufferOffset = 0;
915    }
916
917    CHECK(mBoxes.empty());
918
919    release();
920    return err;
921}
922
923uint32_t MPEG4Writer::getMpeg4Time() {
924    time_t now = time(NULL);
925    // MP4 file uses time counting seconds since midnight, Jan. 1, 1904
926    // while time function returns Unix epoch values which starts
927    // at 1970-01-01. Lets add the number of seconds between them
928    uint32_t mpeg4Time = now + (66 * 365 + 17) * (24 * 60 * 60);
929    return mpeg4Time;
930}
931
932void MPEG4Writer::writeMvhdBox(int64_t durationUs) {
933    uint32_t now = getMpeg4Time();
934    beginBox("mvhd");
935    writeInt32(0);             // version=0, flags=0
936    writeInt32(now);           // creation time
937    writeInt32(now);           // modification time
938    writeInt32(mTimeScale);    // mvhd timescale
939    int32_t duration = (durationUs * mTimeScale + 5E5) / 1E6;
940    writeInt32(duration);
941    writeInt32(0x10000);       // rate: 1.0
942    writeInt16(0x100);         // volume
943    writeInt16(0);             // reserved
944    writeInt32(0);             // reserved
945    writeInt32(0);             // reserved
946    writeCompositionMatrix(0); // matrix
947    writeInt32(0);             // predefined
948    writeInt32(0);             // predefined
949    writeInt32(0);             // predefined
950    writeInt32(0);             // predefined
951    writeInt32(0);             // predefined
952    writeInt32(0);             // predefined
953    writeInt32(mTracks.size() + 1);  // nextTrackID
954    endBox();  // mvhd
955}
956
957void MPEG4Writer::writeMoovBox(int64_t durationUs) {
958    beginBox("moov");
959    writeMvhdBox(durationUs);
960    if (mAreGeoTagsAvailable) {
961        writeUdtaBox();
962    }
963    int32_t id = 1;
964    for (List<Track *>::iterator it = mTracks.begin();
965        it != mTracks.end(); ++it, ++id) {
966        (*it)->writeTrackHeader(mUse32BitOffset);
967    }
968    endBox();  // moov
969}
970
971void MPEG4Writer::writeFtypBox(MetaData *param) {
972    beginBox("ftyp");
973
974    int32_t fileType;
975    if (param && param->findInt32(kKeyFileType, &fileType) &&
976        fileType != OUTPUT_FORMAT_MPEG_4) {
977        writeFourcc("3gp4");
978    } else {
979        writeFourcc("isom");
980    }
981
982    writeInt32(0);
983    writeFourcc("isom");
984    writeFourcc("3gp4");
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: %zu", 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("%zu 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 = static_cast<status_t>(reinterpret_cast<uintptr_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 *)(uintptr_t)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: %zu", 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 (%zu) 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 (%zd) 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: %zu", 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