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