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