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