MPEG4Writer.cpp revision 5ff1dd576bb93c45b44088a51544a18fc43ebf58
120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber/*
220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Copyright (C) 2009 The Android Open Source Project
320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * you may not use this file except in compliance with the License.
620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * You may obtain a copy of the License at
720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
1020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Unless required by applicable law or agreed to in writing, software
1120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
1220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * See the License for the specific language governing permissions and
1420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * limitations under the License.
1520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber */
1620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
17050b28a593350047845a45a14cc5026221ac1620James Dong//#define LOG_NDEBUG 0
18050b28a593350047845a45a14cc5026221ac1620James Dong#define LOG_TAG "MPEG4Writer"
19050b28a593350047845a45a14cc5026221ac1620James Dong#include <utils/Log.h>
20050b28a593350047845a45a14cc5026221ac1620James Dong
2120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <arpa/inet.h>
2220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <pthread.h>
24a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong#include <sys/prctl.h>
2520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MPEG4Writer.h>
2720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBuffer.h>
2820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h>
290c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber#include <media/stagefright/MediaDebug.h>
3018291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h>
3103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#include <media/stagefright/MediaErrors.h>
3220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaSource.h>
3320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/Utils.h>
34d599cd4573b5a2d5914c5040e0565ef866749b77James Dong#include <media/mediarecorder.h>
3507ec01904613a0bac32caaa8444b4690998faed7James Dong#include <cutils/properties.h>
36674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong#include <sys/types.h>
37674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong#include <sys/stat.h>
38674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong#include <fcntl.h>
39674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong#include <unistd.h>
4020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber#include "include/ESDS.h"
4219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
4320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android {
4420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
451f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongstatic const int64_t kMax32BitFileSize = 0x007fffffffLL;
463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypeSeqParamSet = 0x07;
473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypePicParamSet = 0x08;
4870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongstatic const int64_t kInitialDelayTimeUs     = 700000LL;
495b6a01e65aa4129a9226667536d1bc1dad5980d8James Dong
5020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Writer::Track {
5120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic:
52bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    Track(MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId);
538f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
5420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    ~Track();
5520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t start(MetaData *params);
5737187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t stop();
5837187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t pause();
5925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool reachedEOS();
6020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
613b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber    int64_t getDurationUs() const;
62d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t getEstimatedTrackSizeBytes() const;
63b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeTrackHeader(bool use32BitOffset = true);
641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void bufferChunk(int64_t timestampUs);
651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isAvc() const { return mIsAvc; }
661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isAudio() const { return mIsAudio; }
671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isMPEG4() const { return mIsMPEG4; }
68c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    void addChunkOffset(off64_t offset);
6970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int32_t getTrackId() const { return mTrackId; }
70dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    status_t dump(int fd, const Vector<String16>& args) const;
7120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate:
7320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Writer *mOwner;
7420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MetaData> mMeta;
75693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    sp<MediaSource> mSource;
7620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    volatile bool mDone;
77a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mPaused;
78a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mResumed;
79eaae38445a340c4857c1c5569475879a728e63b7James Dong    volatile bool mStarted;
801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAvc;
811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAudio;
821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsMPEG4;
83bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    int32_t mTrackId;
84c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    int64_t mTrackDurationUs;
8543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    int64_t mMaxChunkDurationUs;
86e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
87e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    bool mIsRealTimeRecording;
88e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    int64_t mMaxTimeStampUs;
89d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t mEstimatedTrackSizeBytes;
901f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    int64_t mMdatSizeBytes;
918f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int32_t mTimeScale;
9220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_t mThread;
9420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
95ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    // mNumSamples is used to track how many samples in mSampleSizes List.
96ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    // This is to reduce the cost associated with mSampleSizes.size() call,
97ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    // since it is O(n). Ideally, the fix should be in List class.
98ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    size_t              mNumSamples;
998644c14618d30d9e57a69df40ed939986ebf02c4James Dong    List<size_t>        mSampleSizes;
100be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    bool                mSamplesHaveSameSize;
101be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
10213aec890216948b0c364f8f92792129d0335f506James Dong    List<MediaBuffer *> mChunkSamples;
1031f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1041f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    size_t              mNumStcoTableEntries;
105c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    List<off64_t>         mChunkOffsets;
10613aec890216948b0c364f8f92792129d0335f506James Dong
1071f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    size_t              mNumStscTableEntries;
10813aec890216948b0c364f8f92792129d0335f506James Dong    struct StscTableEntry {
10913aec890216948b0c364f8f92792129d0335f506James Dong
11013aec890216948b0c364f8f92792129d0335f506James Dong        StscTableEntry(uint32_t chunk, uint32_t samples, uint32_t id)
11113aec890216948b0c364f8f92792129d0335f506James Dong            : firstChunk(chunk),
11213aec890216948b0c364f8f92792129d0335f506James Dong              samplesPerChunk(samples),
11313aec890216948b0c364f8f92792129d0335f506James Dong              sampleDescriptionId(id) {}
11413aec890216948b0c364f8f92792129d0335f506James Dong
11513aec890216948b0c364f8f92792129d0335f506James Dong        uint32_t firstChunk;
11613aec890216948b0c364f8f92792129d0335f506James Dong        uint32_t samplesPerChunk;
11713aec890216948b0c364f8f92792129d0335f506James Dong        uint32_t sampleDescriptionId;
11813aec890216948b0c364f8f92792129d0335f506James Dong    };
11913aec890216948b0c364f8f92792129d0335f506James Dong    List<StscTableEntry> mStscTableEntries;
12020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1211f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    size_t        mNumStssTableEntries;
122050b28a593350047845a45a14cc5026221ac1620James Dong    List<int32_t> mStssTableEntries;
123050b28a593350047845a45a14cc5026221ac1620James Dong
124be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    struct SttsTableEntry {
125be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
12679761ab096f57c3027fad9556c2bc436672d614eJames Dong        SttsTableEntry(uint32_t count, uint32_t duration)
12779761ab096f57c3027fad9556c2bc436672d614eJames Dong            : sampleCount(count), sampleDuration(duration) {}
128be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
129be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        uint32_t sampleCount;
13079761ab096f57c3027fad9556c2bc436672d614eJames Dong        uint32_t sampleDuration;  // time scale based
131be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    };
132965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    size_t        mNumSttsTableEntries;
133be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    List<SttsTableEntry> mSttsTableEntries;
134be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
135965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    struct CttsTableEntry {
136965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        CttsTableEntry(uint32_t count, int32_t timescaledDur)
137965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            : sampleCount(count), sampleDuration(timescaledDur) {}
138965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
139965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        uint32_t sampleCount;
140965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        int32_t sampleDuration;  // time scale based
141965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    };
142965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    bool          mHasNegativeCttsDeltaDuration;
143965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    size_t        mNumCttsTableEntries;
144965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    List<CttsTableEntry> mCttsTableEntries;
145965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
1463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Sequence parameter set or picture parameter set
1473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    struct AVCParamSet {
1483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        AVCParamSet(uint16_t length, const uint8_t *data)
1493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            : mLength(length), mData(data) {}
1503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
1513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t mLength;
1523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *mData;
1533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    };
1543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    List<AVCParamSet> mSeqParamSets;
1553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    List<AVCParamSet> mPicParamSets;
1563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mProfileIdc;
1573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mProfileCompatible;
1583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mLevelIdc;
1593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
16020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *mCodecSpecificData;
16120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t mCodecSpecificDataSize;
162548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    bool mGotAllCodecSpecificData;
16393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    bool mTrackingProgressStatus;
16420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
16525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool mReachedEOS;
1663c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    int64_t mStartTimestampUs;
16770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int64_t mStartTimeRealUs;
16870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int64_t mFirstSampleTimeRealUs;
16993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mPreviousTrackTimeUs;
17093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mTrackEveryTimeDurationUs;
17125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
172872a481558350634a3fd5cb67939de288af00ecbJames Dong    // Update the audio track's drift information.
173872a481558350634a3fd5cb67939de288af00ecbJames Dong    void updateDriftTime(const sp<MetaData>& meta);
174872a481558350634a3fd5cb67939de288af00ecbJames Dong
17520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    static void *ThreadWrapper(void *me);
17637187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t threadEntry();
17720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *parseParamSet(
1793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen);
1803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
181b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t makeAVCCodecSpecificData(const uint8_t *data, size_t size);
182b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t copyAVCCodecSpecificData(const uint8_t *data, size_t size);
183b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t parseAVCCodecSpecificData(const uint8_t *data, size_t size);
184215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong
185215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    // Track authoring progress status
186faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    void trackProgressStatus(int64_t timeUs, status_t err = OK);
18793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    void initTrackingProgressStatus(MetaData *params);
18803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
18919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    void getCodecSpecificDataFromInputFormatIfPossible();
19019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
191c059860c73678a202bfa33062723e8f82fb779d9James Dong    // Determine the track time scale
192c059860c73678a202bfa33062723e8f82fb779d9James Dong    // If it is an audio track, try to use the sampling rate as
193c059860c73678a202bfa33062723e8f82fb779d9James Dong    // the time scale; however, if user chooses the overwrite
194c059860c73678a202bfa33062723e8f82fb779d9James Dong    // value, the user-supplied time scale will be used.
195c059860c73678a202bfa33062723e8f82fb779d9James Dong    void setTimeScale();
196c059860c73678a202bfa33062723e8f82fb779d9James Dong
197690f546b0ee548dbfe997df36418e5302ec2d786James Dong    // Simple validation on the codec specific data
198690f546b0ee548dbfe997df36418e5302ec2d786James Dong    status_t checkCodecSpecificData() const;
19913f6284305e4b27395a23db7882d670bdb1bcae1James Dong    int32_t mRotation;
200690f546b0ee548dbfe997df36418e5302ec2d786James Dong
2011f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void updateTrackSizeEstimate();
2021f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void addOneStscTableEntry(size_t chunkId, size_t sampleId);
2031f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void addOneStssTableEntry(size_t sampleId);
20479761ab096f57c3027fad9556c2bc436672d614eJames Dong
20579761ab096f57c3027fad9556c2bc436672d614eJames Dong    // Duration is time scale based
20679761ab096f57c3027fad9556c2bc436672d614eJames Dong    void addOneSttsTableEntry(size_t sampleCount, int32_t timescaledDur);
207965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    void addOneCttsTableEntry(size_t sampleCount, int32_t timescaledDur);
20845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
20945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    bool isTrackMalFormed() const;
21043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    void sendTrackSummary(bool hasMultipleTracks);
2111f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
212b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Write the boxes
213b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStcoBox(bool use32BitOffset);
214b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStscBox();
215b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStszBox();
216b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStssBox();
217b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeSttsBox();
218965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    void writeCttsBox();
219b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeD263Box();
220b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writePaspBox();
221b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeAvccBox();
222b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeUrlBox();
223b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDrefBox();
224b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDinfBox();
225b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDamrBox();
226b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeMdhdBox(time_t now);
227b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeSmhdBox();
228b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeVmhdBox();
229b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeHdlrBox();
230b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeTkhdBox(time_t now);
231b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeMp4aEsdsBox();
232b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeMp4vEsdsBox();
233b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeAudioFourCCBox();
234b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeVideoFourCCBox();
235b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStblBox(bool use32BitOffset);
236b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
23720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track(const Track &);
23820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track &operator=(const Track &);
23920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
24020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
24120111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::MPEG4Writer(const char *filename)
242674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    : mFd(-1),
243674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong      mInitCheck(NO_INIT),
244b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong      mUse4ByteNalLength(true),
2451acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong      mUse32BitOffset(true),
246a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong      mIsFileSizeLimitExplicitlyRequested(false),
247a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
248a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mStarted(false),
249411ba422e3635d534928ffd81abf54f4f291c739James Dong      mWriterThreadStarted(false),
25020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOffset(0),
25113aec890216948b0c364f8f92792129d0335f506James Dong      mMdatOffset(0),
2527837c17063a4c50bc856ba59418516fdab731de7James Dong      mEstimatedMoovBoxSize(0),
25307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mInterleaveDurationUs(1000000),
25407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mLatitudex10000(0),
25507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mLongitudex10000(0),
25686b7f47aa7482424cf8fd248f1315311919be3b0James Dong      mAreGeoTagsAvailable(false),
25786b7f47aa7482424cf8fd248f1315311919be3b0James Dong      mStartTimeOffsetMs(-1) {
258674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong
25903f6f4e7e2ce09357cbc05bb546cd8a6e54b5baeJames Dong    mFd = open(filename, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR);
260674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mFd >= 0) {
261674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        mInitCheck = OK;
262674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    }
26320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
26420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
26530ab66297501757d745b9ae10da61adcd891f497Andreas HuberMPEG4Writer::MPEG4Writer(int fd)
266674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    : mFd(dup(fd)),
267674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong      mInitCheck(mFd < 0? NO_INIT: OK),
268b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong      mUse4ByteNalLength(true),
2691acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong      mUse32BitOffset(true),
270a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong      mIsFileSizeLimitExplicitlyRequested(false),
271a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
272a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mStarted(false),
273411ba422e3635d534928ffd81abf54f4f291c739James Dong      mWriterThreadStarted(false),
27430ab66297501757d745b9ae10da61adcd891f497Andreas Huber      mOffset(0),
27513aec890216948b0c364f8f92792129d0335f506James Dong      mMdatOffset(0),
2767837c17063a4c50bc856ba59418516fdab731de7James Dong      mEstimatedMoovBoxSize(0),
27707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mInterleaveDurationUs(1000000),
27807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mLatitudex10000(0),
27907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mLongitudex10000(0),
28086b7f47aa7482424cf8fd248f1315311919be3b0James Dong      mAreGeoTagsAvailable(false),
28186b7f47aa7482424cf8fd248f1315311919be3b0James Dong      mStartTimeOffsetMs(-1) {
28230ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
28330ab66297501757d745b9ae10da61adcd891f497Andreas Huber
28420111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() {
28520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    stop();
28620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2871f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    while (!mTracks.empty()) {
2881f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        List<Track *>::iterator it = mTracks.begin();
28920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        delete *it;
2901f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        (*it) = NULL;
2911f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mTracks.erase(it);
29220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
29320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.clear();
29420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
29520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
296dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::dump(
297dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        int fd, const Vector<String16>& args) {
298dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    const size_t SIZE = 256;
299dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    char buffer[SIZE];
300dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    String8 result;
301dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "   MPEG4Writer %p\n", this);
302dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
303dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "     mStarted: %s\n", mStarted? "true": "false");
304dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
305dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    ::write(fd, result.string(), result.size());
306dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    for (List<Track *>::iterator it = mTracks.begin();
307dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong         it != mTracks.end(); ++it) {
308dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        (*it)->dump(fd, args);
309dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    }
310dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    return OK;
311dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong}
312dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong
313dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::Track::dump(
314dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        int fd, const Vector<String16>& args) const {
315dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    const size_t SIZE = 256;
316dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    char buffer[SIZE];
317dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    String8 result;
318dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "     %s track\n", mIsAudio? "Audio": "Video");
319dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
320dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "       reached EOS: %s\n",
321dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong            mReachedEOS? "true": "false");
322dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
323dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    ::write(fd, result.string(), result.size());
324dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    return OK;
325dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong}
326dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong
3272dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huberstatus_t MPEG4Writer::addSource(const sp<MediaSource> &source) {
328bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    Mutex::Autolock l(mLock);
329bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    if (mStarted) {
330bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        LOGE("Attempt to add source AFTER recording is started");
331bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        return UNKNOWN_ERROR;
332bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    }
333bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    Track *track = new Track(this, source, mTracks.size());
33420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.push_back(track);
3352dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
3362dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    return OK;
33720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
33820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
33993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::startTracks(MetaData *params) {
340a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
341a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
34293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        status_t err = (*it)->start(params);
343a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
344a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (err != OK) {
345a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            for (List<Track *>::iterator it2 = mTracks.begin();
346a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                 it2 != it; ++it2) {
347a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                (*it2)->stop();
348a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            }
349a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
350a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            return err;
351a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
352a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
353a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    return OK;
354a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
355a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
3562dec2b5be2056c6d9428897dc672185872d30d17James Dongint64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) {
3572dec2b5be2056c6d9428897dc672185872d30d17James Dong    // This implementation is highly experimental/heurisitic.
3582dec2b5be2056c6d9428897dc672185872d30d17James Dong    //
3592dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Statistical analysis shows that metadata usually accounts
3602dec2b5be2056c6d9428897dc672185872d30d17James Dong    // for a small portion of the total file size, usually < 0.6%.
3612dec2b5be2056c6d9428897dc672185872d30d17James Dong
36278a1a286f736888ae7af8860b2c424af0d978848James Dong    // The default MIN_MOOV_BOX_SIZE is set to 0.6% x 1MB / 2,
3632dec2b5be2056c6d9428897dc672185872d30d17James Dong    // where 1MB is the common file size limit for MMS application.
36478a1a286f736888ae7af8860b2c424af0d978848James Dong    // The default MAX _MOOV_BOX_SIZE value is based on about 3
3652dec2b5be2056c6d9428897dc672185872d30d17James Dong    // minute video recording with a bit rate about 3 Mbps, because
3662dec2b5be2056c6d9428897dc672185872d30d17James Dong    // statistics also show that most of the video captured are going
3672dec2b5be2056c6d9428897dc672185872d30d17James Dong    // to be less than 3 minutes.
3682dec2b5be2056c6d9428897dc672185872d30d17James Dong
3692dec2b5be2056c6d9428897dc672185872d30d17James Dong    // If the estimation is wrong, we will pay the price of wasting
3702dec2b5be2056c6d9428897dc672185872d30d17James Dong    // some reserved space. This should not happen so often statistically.
3712dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int32_t factor = mUse32BitOffset? 1: 2;
37278a1a286f736888ae7af8860b2c424af0d978848James Dong    static const int64_t MIN_MOOV_BOX_SIZE = 3 * 1024;  // 3 KB
3732dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000);
3742dec2b5be2056c6d9428897dc672185872d30d17James Dong    int64_t size = MIN_MOOV_BOX_SIZE;
3752dec2b5be2056c6d9428897dc672185872d30d17James Dong
37678a1a286f736888ae7af8860b2c424af0d978848James Dong    // Max file size limit is set
377a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
37878a1a286f736888ae7af8860b2c424af0d978848James Dong        size = mMaxFileSizeLimitBytes * 6 / 1000;
37978a1a286f736888ae7af8860b2c424af0d978848James Dong    }
38078a1a286f736888ae7af8860b2c424af0d978848James Dong
38178a1a286f736888ae7af8860b2c424af0d978848James Dong    // Max file duration limit is set
38278a1a286f736888ae7af8860b2c424af0d978848James Dong    if (mMaxFileDurationLimitUs != 0) {
38378a1a286f736888ae7af8860b2c424af0d978848James Dong        if (bitRate > 0) {
38478a1a286f736888ae7af8860b2c424af0d978848James Dong            int64_t size2 =
38578a1a286f736888ae7af8860b2c424af0d978848James Dong                ((mMaxFileDurationLimitUs * bitRate * 6) / 1000 / 8000000);
38678a1a286f736888ae7af8860b2c424af0d978848James Dong            if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
38778a1a286f736888ae7af8860b2c424af0d978848James Dong                // When both file size and duration limits are set,
38878a1a286f736888ae7af8860b2c424af0d978848James Dong                // we use the smaller limit of the two.
38978a1a286f736888ae7af8860b2c424af0d978848James Dong                if (size > size2) {
39078a1a286f736888ae7af8860b2c424af0d978848James Dong                    size = size2;
39178a1a286f736888ae7af8860b2c424af0d978848James Dong                }
39278a1a286f736888ae7af8860b2c424af0d978848James Dong            } else {
39378a1a286f736888ae7af8860b2c424af0d978848James Dong                // Only max file duration limit is set
39478a1a286f736888ae7af8860b2c424af0d978848James Dong                size = size2;
39578a1a286f736888ae7af8860b2c424af0d978848James Dong            }
3962dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
3972dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
39878a1a286f736888ae7af8860b2c424af0d978848James Dong
3992dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size < MIN_MOOV_BOX_SIZE) {
4002dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MIN_MOOV_BOX_SIZE;
4012dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
4022dec2b5be2056c6d9428897dc672185872d30d17James Dong
4032dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Any long duration recording will be probably end up with
4042dec2b5be2056c6d9428897dc672185872d30d17James Dong    // non-streamable mp4 file.
4052dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size > MAX_MOOV_BOX_SIZE) {
4062dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MAX_MOOV_BOX_SIZE;
4072dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
4082dec2b5be2056c6d9428897dc672185872d30d17James Dong
409df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("limits: %lld/%lld bytes/us, bit rate: %d bps and the estimated"
4102dec2b5be2056c6d9428897dc672185872d30d17James Dong         " moov size %lld bytes",
4112dec2b5be2056c6d9428897dc672185872d30d17James Dong         mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size);
4122dec2b5be2056c6d9428897dc672185872d30d17James Dong    return factor * size;
4132dec2b5be2056c6d9428897dc672185872d30d17James Dong}
4142dec2b5be2056c6d9428897dc672185872d30d17James Dong
4152dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t MPEG4Writer::start(MetaData *param) {
416674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
41725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return UNKNOWN_ERROR;
41820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
41920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
420a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    /*
421a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * Check mMaxFileSizeLimitBytes at the beginning
422a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * since mMaxFileSizeLimitBytes may be implicitly
423a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * changed later for 32-bit file offset even if
424a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * user does not ask to set it explicitly.
425a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     */
426a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    if (mMaxFileSizeLimitBytes != 0) {
427a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong        mIsFileSizeLimitExplicitlyRequested = true;
428a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    }
429a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong
4302dec2b5be2056c6d9428897dc672185872d30d17James Dong    int32_t use64BitOffset;
4312dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (param &&
4322dec2b5be2056c6d9428897dc672185872d30d17James Dong        param->findInt32(kKey64BitFileOffset, &use64BitOffset) &&
4332dec2b5be2056c6d9428897dc672185872d30d17James Dong        use64BitOffset) {
4342dec2b5be2056c6d9428897dc672185872d30d17James Dong        mUse32BitOffset = false;
4352dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
4362dec2b5be2056c6d9428897dc672185872d30d17James Dong
4371f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    if (mUse32BitOffset) {
4381f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // Implicit 32 bit file size limit
4391f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        if (mMaxFileSizeLimitBytes == 0) {
4401f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            mMaxFileSizeLimitBytes = kMax32BitFileSize;
4411f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        }
4421f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
4431f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // If file size is set to be larger than the 32 bit file
4441f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // size limit, treat it as an error.
4451f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        if (mMaxFileSizeLimitBytes > kMax32BitFileSize) {
4465ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block            ALOGW("32-bit file size limit (%lld bytes) too big. "
447d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong                 "It is changed to %lld bytes",
448d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong                mMaxFileSizeLimitBytes, kMax32BitFileSize);
449d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong            mMaxFileSizeLimitBytes = kMax32BitFileSize;
4501f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        }
4511f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    }
4521f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
453b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    int32_t use2ByteNalLength;
454b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (param &&
455b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        param->findInt32(kKey2ByteNalLength, &use2ByteNalLength) &&
456b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        use2ByteNalLength) {
457b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mUse4ByteNalLength = false;
4582dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
4592dec2b5be2056c6d9428897dc672185872d30d17James Dong
460065d1aff96818df54456053f1574aec8a234d0deJames Dong    mStartTimestampUs = -1;
46193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
462a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (mStarted) {
463a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused) {
464a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mPaused = false;
46593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            return startTracks(param);
466a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
467a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
468a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
469a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
4708f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    if (!param ||
4718f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        !param->findInt32(kKeyTimeScale, &mTimeScale)) {
4728f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        mTimeScale = 1000;
4738f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    }
4748f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    CHECK(mTimeScale > 0);
4753856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("movie time scale: %d", mTimeScale);
4768f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
4777837c17063a4c50bc856ba59418516fdab731de7James Dong    mStreamableFile = true;
4787837c17063a4c50bc856ba59418516fdab731de7James Dong    mWriteMoovBoxToMemory = false;
4797837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBuffer = NULL;
4807837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
4817837c17063a4c50bc856ba59418516fdab731de7James Dong
482b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeFtypBox(param);
48320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4847837c17063a4c50bc856ba59418516fdab731de7James Dong    mFreeBoxOffset = mOffset;
48520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4867837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mEstimatedMoovBoxSize == 0) {
4872dec2b5be2056c6d9428897dc672185872d30d17James Dong        int32_t bitRate = -1;
4882dec2b5be2056c6d9428897dc672185872d30d17James Dong        if (param) {
4892dec2b5be2056c6d9428897dc672185872d30d17James Dong            param->findInt32(kKeyBitRate, &bitRate);
4902dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
4912dec2b5be2056c6d9428897dc672185872d30d17James Dong        mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate);
4927837c17063a4c50bc856ba59418516fdab731de7James Dong    }
4937837c17063a4c50bc856ba59418516fdab731de7James Dong    CHECK(mEstimatedMoovBoxSize >= 8);
494c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    lseek64(mFd, mFreeBoxOffset, SEEK_SET);
4957837c17063a4c50bc856ba59418516fdab731de7James Dong    writeInt32(mEstimatedMoovBoxSize);
4967837c17063a4c50bc856ba59418516fdab731de7James Dong    write("free", 4);
4977837c17063a4c50bc856ba59418516fdab731de7James Dong
4987837c17063a4c50bc856ba59418516fdab731de7James Dong    mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize;
4997837c17063a4c50bc856ba59418516fdab731de7James Dong    mOffset = mMdatOffset;
500c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    lseek64(mFd, mMdatOffset, SEEK_SET);
5011acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
5021acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("????mdat", 8);
5031acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
5041acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("\x00\x00\x00\x01mdat????????", 16);
5051acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
5061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
5071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    status_t err = startWriterThread();
5081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (err != OK) {
5091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        return err;
5101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
5111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
5121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    err = startTracks(param);
513a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (err != OK) {
514a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return err;
51520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
5161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
517a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mStarted = true;
51825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
51920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
52020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5211f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongbool MPEG4Writer::use32BitFileOffset() const {
5221f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    return mUse32BitOffset;
5231f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
5241f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
52537187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::pause() {
526674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
52737187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
528a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
529a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
53037187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = OK;
531a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
532a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
53337187916a486504acaf83bea30147eb5fbf46ae5James Dong        status_t status = (*it)->pause();
53437187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (status != OK) {
53537187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
53637187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
537a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
53837187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
539a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
540a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
5411c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::stopWriterThread() {
542b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("Stopping writer thread");
543411ba422e3635d534928ffd81abf54f4f291c739James Dong    if (!mWriterThreadStarted) {
544411ba422e3635d534928ffd81abf54f4f291c739James Dong        return;
545411ba422e3635d534928ffd81abf54f4f291c739James Dong    }
5461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
5471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    {
5481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        Mutex::Autolock autolock(mLock);
5491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
5501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mDone = true;
5511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkReadyCondition.signal();
5521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
5531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
5541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void *dummy;
5551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_join(mThread, &dummy);
556411ba422e3635d534928ffd81abf54f4f291c739James Dong    mWriterThreadStarted = false;
557b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("Writer thread stopped");
5581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
5591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
56013f6284305e4b27395a23db7882d670bdb1bcae1James Dong/*
56113f6284305e4b27395a23db7882d670bdb1bcae1James Dong * MP4 file standard defines a composition matrix:
56213f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | a  b  u |
56313f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | c  d  v |
56413f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | x  y  w |
56513f6284305e4b27395a23db7882d670bdb1bcae1James Dong *
56613f6284305e4b27395a23db7882d670bdb1bcae1James Dong * the element in the matrix is stored in the following
56713f6284305e4b27395a23db7882d670bdb1bcae1James Dong * order: {a, b, u, c, d, v, x, y, w},
56813f6284305e4b27395a23db7882d670bdb1bcae1James Dong * where a, b, c, d, x, and y is in 16.16 format, while
56913f6284305e4b27395a23db7882d670bdb1bcae1James Dong * u, v and w is in 2.30 format.
57013f6284305e4b27395a23db7882d670bdb1bcae1James Dong */
57113f6284305e4b27395a23db7882d670bdb1bcae1James Dongvoid MPEG4Writer::writeCompositionMatrix(int degrees) {
5723856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("writeCompositionMatrix");
57313f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t a = 0x00010000;
57413f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t b = 0;
57513f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t c = 0;
57613f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t d = 0x00010000;
57713f6284305e4b27395a23db7882d670bdb1bcae1James Dong    switch (degrees) {
57813f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 0:
57913f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
58013f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 90:
58113f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0;
58213f6284305e4b27395a23db7882d670bdb1bcae1James Dong            b = 0x00010000;
58313f6284305e4b27395a23db7882d670bdb1bcae1James Dong            c = 0xFFFF0000;
58413f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0;
58513f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
58613f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 180:
58713f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0xFFFF0000;
58813f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0xFFFF0000;
58913f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
59013f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 270:
59113f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0;
59213f6284305e4b27395a23db7882d670bdb1bcae1James Dong            b = 0xFFFF0000;
59313f6284305e4b27395a23db7882d670bdb1bcae1James Dong            c = 0x00010000;
59413f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0;
59513f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
59613f6284305e4b27395a23db7882d670bdb1bcae1James Dong        default:
59713f6284305e4b27395a23db7882d670bdb1bcae1James Dong            CHECK(!"Should never reach this unknown rotation");
59813f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
59913f6284305e4b27395a23db7882d670bdb1bcae1James Dong    }
60013f6284305e4b27395a23db7882d670bdb1bcae1James Dong
60113f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(a);           // a
60213f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(b);           // b
60313f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // u
60413f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(c);           // c
60513f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(d);           // d
60613f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // v
60713f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // x
60813f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // y
60913f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0x40000000);  // w
61013f6284305e4b27395a23db7882d670bdb1bcae1James Dong}
61113f6284305e4b27395a23db7882d670bdb1bcae1James Dong
612411ba422e3635d534928ffd81abf54f4f291c739James Dongvoid MPEG4Writer::release() {
613411ba422e3635d534928ffd81abf54f4f291c739James Dong    close(mFd);
614411ba422e3635d534928ffd81abf54f4f291c739James Dong    mFd = -1;
615411ba422e3635d534928ffd81abf54f4f291c739James Dong    mInitCheck = NO_INIT;
616411ba422e3635d534928ffd81abf54f4f291c739James Dong    mStarted = false;
617411ba422e3635d534928ffd81abf54f4f291c739James Dong}
61813f6284305e4b27395a23db7882d670bdb1bcae1James Dong
61937187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::stop() {
620674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
62137187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
622411ba422e3635d534928ffd81abf54f4f291c739James Dong    } else {
623411ba422e3635d534928ffd81abf54f4f291c739James Dong        if (!mWriterThreadStarted ||
624411ba422e3635d534928ffd81abf54f4f291c739James Dong            !mStarted) {
625411ba422e3635d534928ffd81abf54f4f291c739James Dong            if (mWriterThreadStarted) {
626411ba422e3635d534928ffd81abf54f4f291c739James Dong                stopWriterThread();
627411ba422e3635d534928ffd81abf54f4f291c739James Dong            }
628411ba422e3635d534928ffd81abf54f4f291c739James Dong            release();
629411ba422e3635d534928ffd81abf54f4f291c739James Dong            return OK;
630411ba422e3635d534928ffd81abf54f4f291c739James Dong        }
63120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
63220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
63337187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = OK;
6348f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t maxDurationUs = 0;
63565b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    int64_t minDurationUs = 0x7fffffffffffffffLL;
63620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
63720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber         it != mTracks.end(); ++it) {
63837187916a486504acaf83bea30147eb5fbf46ae5James Dong        status_t status = (*it)->stop();
63937187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (err == OK && status != OK) {
64037187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
64137187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
64220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6438f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int64_t durationUs = (*it)->getDurationUs();
6448f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        if (durationUs > maxDurationUs) {
6458f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            maxDurationUs = durationUs;
64620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
64765b3d76025c71d755b0fb3b6ead90255f25417edJames Dong        if (durationUs < minDurationUs) {
64865b3d76025c71d755b0fb3b6ead90255f25417edJames Dong            minDurationUs = durationUs;
64965b3d76025c71d755b0fb3b6ead90255f25417edJames Dong        }
65065b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    }
65165b3d76025c71d755b0fb3b6ead90255f25417edJames Dong
65265b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    if (mTracks.size() > 1) {
653b8a805261bf0282e992d3608035e47d05a898710Steve Block        ALOGD("Duration from tracks range is [%lld, %lld] us",
65465b3d76025c71d755b0fb3b6ead90255f25417edJames Dong            minDurationUs, maxDurationUs);
65520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
65620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    stopWriterThread();
6587837c17063a4c50bc856ba59418516fdab731de7James Dong
65937187916a486504acaf83bea30147eb5fbf46ae5James Dong    // Do not write out movie header on error.
66037187916a486504acaf83bea30147eb5fbf46ae5James Dong    if (err != OK) {
661411ba422e3635d534928ffd81abf54f4f291c739James Dong        release();
66237187916a486504acaf83bea30147eb5fbf46ae5James Dong        return err;
66337187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
66437187916a486504acaf83bea30147eb5fbf46ae5James Dong
66520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // Fix up the size of the 'mdat' chunk.
6661acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
667c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mMdatOffset, SEEK_SET);
6681acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        int32_t size = htonl(static_cast<int32_t>(mOffset - mMdatOffset));
669c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &size, 4);
6701acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
671c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mMdatOffset + 8, SEEK_SET);
6721acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        int64_t size = mOffset - mMdatOffset;
6731acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        size = hton64(size);
674c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &size, 8);
6751acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
676c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    lseek64(mFd, mOffset, SEEK_SET);
67720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
678c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    const off64_t moovOffset = mOffset;
6797837c17063a4c50bc856ba59418516fdab731de7James Dong    mWriteMoovBoxToMemory = true;
6807837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize);
6817837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
6827837c17063a4c50bc856ba59418516fdab731de7James Dong    CHECK(mMoovBoxBuffer != NULL);
683b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeMoovBox(maxDurationUs);
68420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6857837c17063a4c50bc856ba59418516fdab731de7James Dong    mWriteMoovBoxToMemory = false;
6867837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mStreamableFile) {
6877837c17063a4c50bc856ba59418516fdab731de7James Dong        CHECK(mMoovBoxBufferOffset + 8 <= mEstimatedMoovBoxSize);
6887837c17063a4c50bc856ba59418516fdab731de7James Dong
6897837c17063a4c50bc856ba59418516fdab731de7James Dong        // Moov box
690c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mFreeBoxOffset, SEEK_SET);
6917837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset = mFreeBoxOffset;
692674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset);
6937837c17063a4c50bc856ba59418516fdab731de7James Dong
6947837c17063a4c50bc856ba59418516fdab731de7James Dong        // Free box
695c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mOffset, SEEK_SET);
6967837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset);
6977837c17063a4c50bc856ba59418516fdab731de7James Dong        write("free", 4);
6987837c17063a4c50bc856ba59418516fdab731de7James Dong
6997837c17063a4c50bc856ba59418516fdab731de7James Dong        // Free temp memory
7007837c17063a4c50bc856ba59418516fdab731de7James Dong        free(mMoovBoxBuffer);
7017837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBuffer = NULL;
7027837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBufferOffset = 0;
7032dec2b5be2056c6d9428897dc672185872d30d17James Dong    } else {
704df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("The mp4 file will not be streamable.");
7057837c17063a4c50bc856ba59418516fdab731de7James Dong    }
7067837c17063a4c50bc856ba59418516fdab731de7James Dong
7070c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(mBoxes.empty());
70820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
709411ba422e3635d534928ffd81abf54f4f291c739James Dong    release();
71037187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
71120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
71220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
713b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::writeMvhdBox(int64_t durationUs) {
714b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    time_t now = time(NULL);
715b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("mvhd");
716b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // version=0, flags=0
717b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(now);           // creation time
718b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(now);           // modification time
719b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(mTimeScale);    // mvhd timescale
720b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t duration = (durationUs * mTimeScale + 5E5) / 1E6;
721b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(duration);
722b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0x10000);       // rate: 1.0
723b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt16(0x100);         // volume
724b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt16(0);             // reserved
725b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // reserved
726b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // reserved
727b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeCompositionMatrix(0); // matrix
728b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
729b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
730b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
731b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
732b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
733b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
734b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(mTracks.size() + 1);  // nextTrackID
735b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();  // mvhd
736b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
737b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
738b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::writeMoovBox(int64_t durationUs) {
739b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("moov");
740b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeMvhdBox(durationUs);
74107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (mAreGeoTagsAvailable) {
74207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        writeUdtaBox();
74307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
744b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t id = 1;
745b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    for (List<Track *>::iterator it = mTracks.begin();
746b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        it != mTracks.end(); ++it, ++id) {
747b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        (*it)->writeTrackHeader(mUse32BitOffset);
748b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
749b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();  // moov
750b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
751b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
7522cf9c5073ca3342ee52673ad68763fadd2c2be79James Dongvoid MPEG4Writer::writeFtypBox(MetaData *param) {
753b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("ftyp");
754b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
755b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t fileType;
756b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (param && param->findInt32(kKeyFileType, &fileType) &&
757b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        fileType != OUTPUT_FORMAT_MPEG_4) {
758b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeFourcc("3gp4");
759b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
760b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeFourcc("isom");
761b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
762b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
763b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);
764b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeFourcc("isom");
765b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeFourcc("3gp4");
766b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();
767b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
768b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
76907ec01904613a0bac32caaa8444b4690998faed7James Dongstatic bool isTestModeEnabled() {
77007ec01904613a0bac32caaa8444b4690998faed7James Dong#if (PROPERTY_VALUE_MAX < 5)
77107ec01904613a0bac32caaa8444b4690998faed7James Dong#error "PROPERTY_VALUE_MAX must be at least 5"
77207ec01904613a0bac32caaa8444b4690998faed7James Dong#endif
77307ec01904613a0bac32caaa8444b4690998faed7James Dong
77407ec01904613a0bac32caaa8444b4690998faed7James Dong    // Test mode is enabled only if rw.media.record.test system
77507ec01904613a0bac32caaa8444b4690998faed7James Dong    // property is enabled.
77607ec01904613a0bac32caaa8444b4690998faed7James Dong    char value[PROPERTY_VALUE_MAX];
77707ec01904613a0bac32caaa8444b4690998faed7James Dong    if (property_get("rw.media.record.test", value, NULL) &&
77807ec01904613a0bac32caaa8444b4690998faed7James Dong        (!strcasecmp(value, "true") || !strcasecmp(value, "1"))) {
77907ec01904613a0bac32caaa8444b4690998faed7James Dong        return true;
78007ec01904613a0bac32caaa8444b4690998faed7James Dong    }
78107ec01904613a0bac32caaa8444b4690998faed7James Dong    return false;
78207ec01904613a0bac32caaa8444b4690998faed7James Dong}
78307ec01904613a0bac32caaa8444b4690998faed7James Dong
78470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongvoid MPEG4Writer::sendSessionSummary() {
78507ec01904613a0bac32caaa8444b4690998faed7James Dong    // Send session summary only if test mode is enabled
78607ec01904613a0bac32caaa8444b4690998faed7James Dong    if (!isTestModeEnabled()) {
78707ec01904613a0bac32caaa8444b4690998faed7James Dong        return;
78807ec01904613a0bac32caaa8444b4690998faed7James Dong    }
78907ec01904613a0bac32caaa8444b4690998faed7James Dong
79070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
79170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong         it != mChunkInfos.end(); ++it) {
79270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        int trackNum = it->mTrack->getTrackId() << 28;
79370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
79470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                trackNum | MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS,
79570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                it->mMaxInterChunkDurUs);
79670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    }
79770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong}
79870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
79913aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) {
80013aec890216948b0c364f8f92792129d0335f506James Dong    mInterleaveDurationUs = durationUs;
80113aec890216948b0c364f8f92792129d0335f506James Dong    return OK;
80213aec890216948b0c364f8f92792129d0335f506James Dong}
80313aec890216948b0c364f8f92792129d0335f506James Dong
80413aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() {
80513aec890216948b0c364f8f92792129d0335f506James Dong    mLock.lock();
80613aec890216948b0c364f8f92792129d0335f506James Dong}
80713aec890216948b0c364f8f92792129d0335f506James Dong
80813aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() {
80913aec890216948b0c364f8f92792129d0335f506James Dong    mLock.unlock();
81013aec890216948b0c364f8f92792129d0335f506James Dong}
81120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
812c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addSample_l(MediaBuffer *buffer) {
813c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t old_offset = mOffset;
81420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
815c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    ::write(mFd,
816c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong          (const uint8_t *)buffer->data() + buffer->range_offset(),
817c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong          buffer->range_length());
81820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
81920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += buffer->range_length();
82020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
82120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return old_offset;
82220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
82320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
82403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) {
82503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (buffer->range_length() < 4) {
82603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return;
82703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
82803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
82903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    const uint8_t *ptr =
83003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        (const uint8_t *)buffer->data() + buffer->range_offset();
83103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
83203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) {
83303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        buffer->set_range(
83403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                buffer->range_offset() + 4, buffer->range_length() - 4);
83503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
83603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
83703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
838c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) {
839c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t old_offset = mOffset;
84030ab66297501757d745b9ae10da61adcd891f497Andreas Huber
84130ab66297501757d745b9ae10da61adcd891f497Andreas Huber    size_t length = buffer->range_length();
84203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
843b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (mUse4ByteNalLength) {
844b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        uint8_t x = length >> 24;
845c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
846b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = (length >> 16) & 0xff;
847c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
848b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = (length >> 8) & 0xff;
849c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
850b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = length & 0xff;
851c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
852c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong
853c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd,
854c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong              (const uint8_t *)buffer->data() + buffer->range_offset(),
855c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong              length);
856b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong
857b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mOffset += length + 4;
858b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    } else {
859b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        CHECK(length < 65536);
86030ab66297501757d745b9ae10da61adcd891f497Andreas Huber
861b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        uint8_t x = length >> 8;
862c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
863b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = length & 0xff;
864c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
865c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, (const uint8_t *)buffer->data() + buffer->range_offset(), length);
866b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mOffset += length + 2;
867b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    }
86830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
86930ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return old_offset;
87030ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
87130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
8727837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write(
873674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        const void *ptr, size_t size, size_t nmemb) {
8747837c17063a4c50bc856ba59418516fdab731de7James Dong
8757837c17063a4c50bc856ba59418516fdab731de7James Dong    const size_t bytes = size * nmemb;
8767837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
877674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        // This happens only when we write the moov box at the end of
878674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        // recording, not for each output video/audio frame we receive.
879c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes;
8801acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        if (moovBoxSize > mEstimatedMoovBoxSize) {
881c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            for (List<off64_t>::iterator it = mBoxes.begin();
8827837c17063a4c50bc856ba59418516fdab731de7James Dong                 it != mBoxes.end(); ++it) {
8837837c17063a4c50bc856ba59418516fdab731de7James Dong                (*it) += mOffset;
8847837c17063a4c50bc856ba59418516fdab731de7James Dong            }
885674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong            lseek64(mFd, mOffset, SEEK_SET);
886674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong            ::write(mFd, mMoovBoxBuffer, mMoovBoxBufferOffset);
887674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong            ::write(mFd, ptr, size * nmemb);
8887837c17063a4c50bc856ba59418516fdab731de7James Dong            mOffset += (bytes + mMoovBoxBufferOffset);
8897837c17063a4c50bc856ba59418516fdab731de7James Dong            free(mMoovBoxBuffer);
8907837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBuffer = NULL;
8917837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset = 0;
8927837c17063a4c50bc856ba59418516fdab731de7James Dong            mWriteMoovBoxToMemory = false;
8937837c17063a4c50bc856ba59418516fdab731de7James Dong            mStreamableFile = false;
8947837c17063a4c50bc856ba59418516fdab731de7James Dong        } else {
8957837c17063a4c50bc856ba59418516fdab731de7James Dong            memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes);
8967837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset += bytes;
8977837c17063a4c50bc856ba59418516fdab731de7James Dong        }
8987837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
899674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        ::write(mFd, ptr, size * nmemb);
9007837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset += bytes;
9017837c17063a4c50bc856ba59418516fdab731de7James Dong    }
9027837c17063a4c50bc856ba59418516fdab731de7James Dong    return bytes;
9037837c17063a4c50bc856ba59418516fdab731de7James Dong}
9047837c17063a4c50bc856ba59418516fdab731de7James Dong
90520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) {
9060c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(fourcc), 4);
90720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9087837c17063a4c50bc856ba59418516fdab731de7James Dong    mBoxes.push_back(mWriteMoovBoxToMemory?
9097837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset: mOffset);
91020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
91120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeInt32(0);
91220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeFourcc(fourcc);
91320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
91420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
91520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() {
9160c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(!mBoxes.empty());
91720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
918c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t offset = *--mBoxes.end();
91920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mBoxes.erase(--mBoxes.end());
92020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9217837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
9227837c17063a4c50bc856ba59418516fdab731de7James Dong       int32_t x = htonl(mMoovBoxBufferOffset - offset);
9237837c17063a4c50bc856ba59418516fdab731de7James Dong       memcpy(mMoovBoxBuffer + offset, &x, 4);
9247837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
925c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, offset, SEEK_SET);
9267837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mOffset - offset);
9277837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset -= 4;
928c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mOffset, SEEK_SET);
9297837c17063a4c50bc856ba59418516fdab731de7James Dong    }
93020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
93120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
93220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) {
933674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 1);
93420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
93520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
93620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) {
93720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htons(x);
938674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 2);
93920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
94020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
94120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) {
94220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htonl(x);
943674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 4);
94420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
94520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
94620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) {
94720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = hton64(x);
948674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 8);
94920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
95020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
95120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) {
95220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t n = strlen(s);
953674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(s, 1, n + 1);
95420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
95520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
95620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) {
9570c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(s), 4);
958674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(s, 1, 4);
95920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
96020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
96107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
96207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/-DD.DDDD format
96307b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLatitude(int degreex10000) {
96407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    bool isNegative = (degreex10000 < 0);
96507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char sign = isNegative? '-': '+';
96607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
96707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the whole part
96807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char str[9];
96907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int wholePart = degreex10000 / 10000;
97007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (wholePart == 0) {
97107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 5, "%c%.2d.", sign, wholePart);
97207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    } else {
97307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 5, "%+.2d.", wholePart);
97407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
97507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
97607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the fractional part
97707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int fractionalPart = degreex10000 - (wholePart * 10000);
97807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (fractionalPart < 0) {
97907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        fractionalPart = -fractionalPart;
98007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
98107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    snprintf(&str[4], 5, "%.4d", fractionalPart);
98207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
98307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Do not write the null terminator
98407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    write(str, 1, 8);
98507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
98607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
98707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/- DDD.DDDD format
98807b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLongitude(int degreex10000) {
98907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    bool isNegative = (degreex10000 < 0);
99007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char sign = isNegative? '-': '+';
99107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
99207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the whole part
99307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char str[10];
99407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int wholePart = degreex10000 / 10000;
99507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (wholePart == 0) {
99607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 6, "%c%.3d.", sign, wholePart);
99707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    } else {
99807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 6, "%+.3d.", wholePart);
99907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
100007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
100107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the fractional part
100207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int fractionalPart = degreex10000 - (wholePart * 10000);
100307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (fractionalPart < 0) {
100407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        fractionalPart = -fractionalPart;
100507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
100607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    snprintf(&str[5], 5, "%.4d", fractionalPart);
100707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
100807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Do not write the null terminator
100907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    write(str, 1, 9);
101007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
101107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
101207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/*
101307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard.
101407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * latitudex10000 is latitude in degrees times 10000, and
101507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * longitudex10000 is longitude in degrees times 10000.
101607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the latitude is in [-90, +90], and
101707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the longitude is in [-180, +180]
101807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */
101907b1bb529a1ae76c46a71b01338c166f9490629dJames Dongstatus_t MPEG4Writer::setGeoData(int latitudex10000, int longitudex10000) {
102007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Is latitude or longitude out of range?
102107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (latitudex10000 < -900000 || latitudex10000 > 900000 ||
102207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        longitudex10000 < -1800000 || longitudex10000 > 1800000) {
102307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        return BAD_VALUE;
102407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
102507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
102607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mLatitudex10000 = latitudex10000;
102707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mLongitudex10000 = longitudex10000;
102807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mAreGeoTagsAvailable = true;
102907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    return OK;
103007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
103107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
103220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) {
1033674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(data, 1, size);
103420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
103520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
103678a1a286f736888ae7af8860b2c424af0d978848James Dongbool MPEG4Writer::isFileStreamable() const {
103778a1a286f736888ae7af8860b2c424af0d978848James Dong    return mStreamableFile;
103878a1a286f736888ae7af8860b2c424af0d978848James Dong}
103978a1a286f736888ae7af8860b2c424af0d978848James Dong
1040d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() {
1041d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
1042d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileSizeLimitBytes == 0) {
1043d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
1044d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1045d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1046956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize);
1047d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
1048d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
1049d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes();
1050d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
10511f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1052acd234bba9f048971d66890009eeff9a8db94be3James Dong    // Be conservative in the estimate: do not exceed 95% of
1053acd234bba9f048971d66890009eeff9a8db94be3James Dong    // the target file limit. For small target file size limit, though,
1054acd234bba9f048971d66890009eeff9a8db94be3James Dong    // this will not help.
1055acd234bba9f048971d66890009eeff9a8db94be3James Dong    return (nTotalBytesEstimate >= (95 * mMaxFileSizeLimitBytes) / 100);
1056d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
1057d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1058d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() {
1059d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
1060d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileDurationLimitUs == 0) {
1061d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
1062d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1063d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1064d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
1065d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
1066d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) {
1067d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            return true;
1068d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
1069d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1070d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return false;
1071d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
1072d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
107325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() {
107425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool allDone = true;
107525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
107625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber         it != mTracks.end(); ++it) {
107725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        if (!(*it)->reachedEOS()) {
107825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            allDone = false;
107925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            break;
108025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        }
108125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
108225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
108325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return allDone;
108425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
108525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
1086f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) {
1087df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("setStartTimestampUs: %lld", timeUs);
1088f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    CHECK(timeUs >= 0);
10893c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
1090065d1aff96818df54456053f1574aec8a234d0deJames Dong    if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) {
1091f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mStartTimestampUs = timeUs;
1092df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("Earliest track starting time: %lld", mStartTimestampUs);
10933c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    }
10943c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
10953c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
1096f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() {
10973c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
10983c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    return mStartTimestampUs;
10993c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
11003c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
110158ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() {
110258ae9c530247668f8af36e30d228c716c226b3d4James Dong    Mutex::Autolock autolock(mLock);
110358ae9c530247668f8af36e30d228c716c226b3d4James Dong    return mTracks.size();
110458ae9c530247668f8af36e30d228c716c226b3d4James Dong}
110558ae9c530247668f8af36e30d228c716c226b3d4James Dong
110620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
110720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
110820111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track(
1109bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId)
111020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mOwner(owner),
111125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mMeta(source->getFormat()),
111220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSource(source),
111320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDone(false),
1114a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
1115a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mResumed(false),
1116eaae38445a340c4857c1c5569475879a728e63b7James Dong      mStarted(false),
1117bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong      mTrackId(trackId),
1118c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong      mTrackDurationUs(0),
1119956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      mEstimatedTrackSizeBytes(0),
1120be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong      mSamplesHaveSameSize(true),
112120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCodecSpecificData(NULL),
112225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mCodecSpecificDataSize(0),
1123548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber      mGotAllCodecSpecificData(false),
112413f6284305e4b27395a23db7882d670bdb1bcae1James Dong      mReachedEOS(false),
112513f6284305e4b27395a23db7882d670bdb1bcae1James Dong      mRotation(0) {
112619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    getCodecSpecificDataFromInputFormatIfPossible();
11278f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
11281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    const char *mime;
11291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mMeta->findCString(kKeyMIMEType, &mime);
11301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
11311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAudio = !strncasecmp(mime, "audio/", 6);
11321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
11331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong               !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC);
11341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1135c059860c73678a202bfa33062723e8f82fb779d9James Dong    setTimeScale();
1136c059860c73678a202bfa33062723e8f82fb779d9James Dong}
1137c059860c73678a202bfa33062723e8f82fb779d9James Dong
11381f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::updateTrackSizeEstimate() {
11391f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
11401f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    int64_t stcoBoxSizeBytes = mOwner->use32BitFileOffset()
11411f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                                ? mNumStcoTableEntries * 4
11421f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                                : mNumStcoTableEntries * 8;
11431f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
11441f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mNumSamples * 4);
11451f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
114678a1a286f736888ae7af8860b2c424af0d978848James Dong    mEstimatedTrackSizeBytes = mMdatSizeBytes;  // media data size
114778a1a286f736888ae7af8860b2c424af0d978848James Dong    if (!mOwner->isFileStreamable()) {
114878a1a286f736888ae7af8860b2c424af0d978848James Dong        // Reserved free space is not large enough to hold
114978a1a286f736888ae7af8860b2c424af0d978848James Dong        // all meta data and thus wasted.
115078a1a286f736888ae7af8860b2c424af0d978848James Dong        mEstimatedTrackSizeBytes += mNumStscTableEntries * 12 +  // stsc box size
115178a1a286f736888ae7af8860b2c424af0d978848James Dong                                    mNumStssTableEntries * 4 +   // stss box size
115278a1a286f736888ae7af8860b2c424af0d978848James Dong                                    mNumSttsTableEntries * 8 +   // stts box size
1153965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong                                    mNumCttsTableEntries * 8 +   // ctts box size
115478a1a286f736888ae7af8860b2c424af0d978848James Dong                                    stcoBoxSizeBytes +           // stco box size
115578a1a286f736888ae7af8860b2c424af0d978848James Dong                                    stszBoxSizeBytes;            // stsz box size
115678a1a286f736888ae7af8860b2c424af0d978848James Dong    }
11571f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
11581f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
11591f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStscTableEntry(
11601f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        size_t chunkId, size_t sampleId) {
11611f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
11621f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        StscTableEntry stscEntry(chunkId, sampleId, 1);
11631f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mStscTableEntries.push_back(stscEntry);
11641f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        ++mNumStscTableEntries;
11651f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
11661f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
11671f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) {
11681f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mStssTableEntries.push_back(sampleId);
11691f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    ++mNumStssTableEntries;
11701f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
11711f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
11721f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneSttsTableEntry(
117379761ab096f57c3027fad9556c2bc436672d614eJames Dong        size_t sampleCount, int32_t duration) {
11741f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
11755a217fba010e801c255503602bda4b86ac5a6ac9James Dong    if (duration == 0) {
11765ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("0-duration samples found: %d", sampleCount);
11775a217fba010e801c255503602bda4b86ac5a6ac9James Dong    }
117879761ab096f57c3027fad9556c2bc436672d614eJames Dong    SttsTableEntry sttsEntry(sampleCount, duration);
11791f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mSttsTableEntries.push_back(sttsEntry);
11801f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    ++mNumSttsTableEntries;
11811f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
11821f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1183965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::addOneCttsTableEntry(
1184965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        size_t sampleCount, int32_t duration) {
1185965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
1186965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    if (mIsAudio) {
1187965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
1188965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
1189965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    if (duration < 0 && !mHasNegativeCttsDeltaDuration) {
1190965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        mHasNegativeCttsDeltaDuration = true;
1191965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
1192965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    CttsTableEntry cttsEntry(sampleCount, duration);
1193965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mCttsTableEntries.push_back(cttsEntry);
1194965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    ++mNumCttsTableEntries;
1195965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong}
1196965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
1197c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongvoid MPEG4Writer::Track::addChunkOffset(off64_t offset) {
11981f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    ++mNumStcoTableEntries;
11991f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mChunkOffsets.push_back(offset);
12001f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
12011f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1202c059860c73678a202bfa33062723e8f82fb779d9James Dongvoid MPEG4Writer::Track::setTimeScale() {
12033856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setTimeScale");
1204c059860c73678a202bfa33062723e8f82fb779d9James Dong    // Default time scale
1205c059860c73678a202bfa33062723e8f82fb779d9James Dong    mTimeScale = 90000;
1206c059860c73678a202bfa33062723e8f82fb779d9James Dong
1207c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mIsAudio) {
1208c059860c73678a202bfa33062723e8f82fb779d9James Dong        // Use the sampling rate as the default time scale for audio track.
1209c059860c73678a202bfa33062723e8f82fb779d9James Dong        int32_t sampleRate;
1210c059860c73678a202bfa33062723e8f82fb779d9James Dong        bool success = mMeta->findInt32(kKeySampleRate, &sampleRate);
1211c059860c73678a202bfa33062723e8f82fb779d9James Dong        CHECK(success);
1212c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = sampleRate;
1213c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
1214c059860c73678a202bfa33062723e8f82fb779d9James Dong
1215c059860c73678a202bfa33062723e8f82fb779d9James Dong    // If someone would like to overwrite the timescale, use user-supplied value.
1216c059860c73678a202bfa33062723e8f82fb779d9James Dong    int32_t timeScale;
1217c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mMeta->findInt32(kKeyTimeScale, &timeScale)) {
1218c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = timeScale;
1219c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
1220c059860c73678a202bfa33062723e8f82fb779d9James Dong
12218f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    CHECK(mTimeScale > 0);
122219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber}
122319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
122419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Hubervoid MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() {
122519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    const char *mime;
122619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
122719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
122819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
122919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        uint32_t type;
123019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        const void *data;
123119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        size_t size;
123219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        if (mMeta->findData(kKeyAVCC, &type, &data, &size)) {
123319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mCodecSpecificData = malloc(size);
123419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mCodecSpecificDataSize = size;
123519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            memcpy(mCodecSpecificData, data, size);
123619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mGotAllCodecSpecificData = true;
123719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        }
123819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
123919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
124019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        uint32_t type;
124119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        const void *data;
124219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        size_t size;
124319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        if (mMeta->findData(kKeyESDS, &type, &data, &size)) {
124419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            ESDS esds(data, size);
124519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            if (esds.getCodecSpecificInfo(&data, &size) == OK) {
124619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mCodecSpecificData = malloc(size);
124719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mCodecSpecificDataSize = size;
124819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                memcpy(mCodecSpecificData, data, size);
124919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mGotAllCodecSpecificData = true;
125019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            }
125119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        }
125219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
125320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
125420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
125520111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() {
125620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    stop();
125720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
125820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mCodecSpecificData != NULL) {
125920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        free(mCodecSpecificData);
126020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mCodecSpecificData = NULL;
126120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
126220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
126320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
126493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) {
12653856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("initTrackingProgressStatus");
126693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mPreviousTrackTimeUs = -1;
126793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackingProgressStatus = false;
126893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackEveryTimeDurationUs = 0;
126993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    {
127093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        int64_t timeUs;
127193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) {
12723856b090cd04ba5dd4a59a12430ed724d5995909Steve Block            ALOGV("Receive request to track progress status for every %lld us", timeUs);
127393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackEveryTimeDurationUs = timeUs;
127493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackingProgressStatus = true;
127593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
127693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
127793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
127893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
12791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong// static
12801c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid *MPEG4Writer::ThreadWrapper(void *me) {
12813856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("ThreadWrapper: %p", me);
12821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    MPEG4Writer *writer = static_cast<MPEG4Writer *>(me);
12831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    writer->threadFunc();
12841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return NULL;
12851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
12861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
12871c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::bufferChunk(const Chunk& chunk) {
12883856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("bufferChunk: %p", chunk.mTrack);
12891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Mutex::Autolock autolock(mLock);
12901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    CHECK_EQ(mDone, false);
12911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
12921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
12931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
12941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
12951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (chunk.mTrack == it->mTrack) {  // Found owner
12961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            it->mChunks.push_back(chunk);
12971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.signal();
12981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            return;
12991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
13001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
13011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
13021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    CHECK("Received a chunk for a unknown track" == 0);
13031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
13041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1305fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeChunkToFile(Chunk* chunk) {
13063856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("writeChunkToFile: %lld from %s track",
13075410afcbb0af5d29d9f710a1c2978c500f9792dcPannag Sanketi        chunk->mTimeStampUs, chunk->mTrack->isAudio()? "audio": "video");
1308fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1309fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    int32_t isFirstSample = true;
1310fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    while (!chunk->mSamples.empty()) {
1311fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        List<MediaBuffer *>::iterator it = chunk->mSamples.begin();
1312fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1313fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        off64_t offset = chunk->mTrack->isAvc()
1314fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong                                ? addLengthPrefixedSample_l(*it)
1315fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong                                : addSample_l(*it);
1316fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1317fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        if (isFirstSample) {
1318fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            chunk->mTrack->addChunkOffset(offset);
1319fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            isFirstSample = false;
13201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
13211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
13221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it)->release();
13231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it) = NULL;
1324fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        chunk->mSamples.erase(it);
13251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1326fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    chunk->mSamples.clear();
13271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
13281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1329fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeAllChunks() {
13303856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("writeAllChunks");
13311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    size_t outstandingChunks = 0;
133270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    Chunk chunk;
133370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    while (findChunkToWrite(&chunk)) {
1334e9f6d0579603372fd2547e6c5ba6e114c6f8cba7James Dong        writeChunkToFile(&chunk);
133570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        ++outstandingChunks;
13361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
133770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
133870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    sendSessionSummary();
133970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
13401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mChunkInfos.clear();
1341b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("%d chunks are written in the last batch", outstandingChunks);
13421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
13431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1344fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongbool MPEG4Writer::findChunkToWrite(Chunk *chunk) {
13453856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("findChunkToWrite");
13461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
13471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL;
13481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Track *track = NULL;
13491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
13501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
13511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (!it->mChunks.empty()) {
13521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            List<Chunk>::iterator chunkIt = it->mChunks.begin();
13531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (chunkIt->mTimeStampUs < minTimestampUs) {
13541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                minTimestampUs = chunkIt->mTimeStampUs;
13551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                track = it->mTrack;
13561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            }
13571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
13581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
13591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
13601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (track == NULL) {
13613856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("Nothing to be written after all");
1362fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        return false;
13631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
13641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
13651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (mIsFirstChunk) {
13661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsFirstChunk = false;
13671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1368fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
13691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
13701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
13711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (it->mTrack == track) {
1372fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            *chunk = *(it->mChunks.begin());
1373fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            it->mChunks.erase(it->mChunks.begin());
1374fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            CHECK_EQ(chunk->mTrack, track);
137570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
137670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            int64_t interChunkTimeUs =
137770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                chunk->mTimeStampUs - it->mPrevChunkTimestampUs;
137870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            if (interChunkTimeUs > it->mPrevChunkTimestampUs) {
137970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                it->mMaxInterChunkDurUs = interChunkTimeUs;
138070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            }
138170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
1382fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            return true;
13831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
13841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1385fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1386fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    return false;
13871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
13881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
13891c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::threadFunc() {
13903856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("threadFunc");
13911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1392a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    prctl(PR_SET_NAME, (unsigned long)"MPEG4Writer", 0, 0, 0);
1393fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1394fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    Mutex::Autolock autoLock(mLock);
13951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    while (!mDone) {
1396fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        Chunk chunk;
1397fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        bool chunkFound = false;
1398fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1399fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        while (!mDone && !(chunkFound = findChunkToWrite(&chunk))) {
14001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.wait(mLock);
14011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
14021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1403fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        // Actual write without holding the lock in order to
1404fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        // reduce the blocking time for media track threads.
1405fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        if (chunkFound) {
1406fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            mLock.unlock();
1407fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            writeChunkToFile(&chunk);
1408fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            mLock.lock();
1409fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        }
14101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1411fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1412fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    writeAllChunks();
14131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
14141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
14151c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::startWriterThread() {
14163856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("startWriterThread");
14171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
14181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mDone = false;
14191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsFirstChunk = true;
1420e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    mDriftTimeUs = 0;
14211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<Track *>::iterator it = mTracks.begin();
14221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mTracks.end(); ++it) {
14231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        ChunkInfo info;
14241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        info.mTrack = *it;
142570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        info.mPrevChunkTimestampUs = 0;
142670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        info.mMaxInterChunkDurUs = 0;
14271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkInfos.push_back(info);
14281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
14291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
14301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_t attr;
14311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_init(&attr);
14321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
14331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_create(&mThread, &attr, ThreadWrapper, this);
14341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_destroy(&attr);
1435411ba422e3635d534928ffd81abf54f4f291c739James Dong    mWriterThreadStarted = true;
14361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return OK;
14371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
14381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
14391f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
144093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) {
1441a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (!mDone && mPaused) {
1442a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mPaused = false;
1443a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mResumed = true;
1444a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
1445a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
144625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
144793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t startTimeUs;
144819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) {
144919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        startTimeUs = 0;
145019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
145170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    mStartTimeRealUs = startTimeUs;
145219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
145313f6284305e4b27395a23db7882d670bdb1bcae1James Dong    int32_t rotationDegrees;
145413f6284305e4b27395a23db7882d670bdb1bcae1James Dong    if (!mIsAudio && params && params->findInt32(kKeyRotation, &rotationDegrees)) {
145513f6284305e4b27395a23db7882d670bdb1bcae1James Dong        mRotation = rotationDegrees;
145613f6284305e4b27395a23db7882d670bdb1bcae1James Dong    }
145713f6284305e4b27395a23db7882d670bdb1bcae1James Dong
14585b6a01e65aa4129a9226667536d1bc1dad5980d8James Dong    mIsRealTimeRecording = true;
1459e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    {
1460e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        int32_t isNotRealTime;
1461e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        if (params && params->findInt32(kKeyNotRealTime, &isNotRealTime)) {
1462e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            mIsRealTimeRecording = (isNotRealTime == 0);
1463e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        }
1464e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    }
1465e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
146693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    initTrackingProgressStatus(params);
146793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
1468f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    sp<MetaData> meta = new MetaData;
1469a472613aec322e25891abf5c77bf3f7e3c244920James Dong    if (mIsRealTimeRecording && mOwner->numTracks() > 1) {
1470a472613aec322e25891abf5c77bf3f7e3c244920James Dong        /*
1471a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * This extra delay of accepting incoming audio/video signals
1472a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * helps to align a/v start time at the beginning of a recording
1473a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * session, and it also helps eliminate the "recording" sound for
1474a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * camcorder applications.
1475a472613aec322e25891abf5c77bf3f7e3c244920James Dong         *
147686b7f47aa7482424cf8fd248f1315311919be3b0James Dong         * If client does not set the start time offset, we fall back to
147786b7f47aa7482424cf8fd248f1315311919be3b0James Dong         * use the default initial delay value.
1478a472613aec322e25891abf5c77bf3f7e3c244920James Dong         */
147986b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL;
148086b7f47aa7482424cf8fd248f1315311919be3b0James Dong        if (startTimeOffsetUs < 0) {  // Start time offset was not set
148186b7f47aa7482424cf8fd248f1315311919be3b0James Dong            startTimeOffsetUs = kInitialDelayTimeUs;
148286b7f47aa7482424cf8fd248f1315311919be3b0James Dong        }
148386b7f47aa7482424cf8fd248f1315311919be3b0James Dong        startTimeUs += startTimeOffsetUs;
1484df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("Start time offset: %lld us", startTimeOffsetUs);
1485a472613aec322e25891abf5c77bf3f7e3c244920James Dong    }
1486a472613aec322e25891abf5c77bf3f7e3c244920James Dong
1487f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    meta->setInt64(kKeyTime, startTimeUs);
1488a472613aec322e25891abf5c77bf3f7e3c244920James Dong
1489f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    status_t err = mSource->start(meta.get());
149025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    if (err != OK) {
149125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        mDone = mReachedEOS = true;
149225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return err;
149325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
149420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
149520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_t attr;
149620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_init(&attr);
149720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
149820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
149920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = false;
1500eaae38445a340c4857c1c5569475879a728e63b7James Dong    mStarted = true;
1501c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs = 0;
150225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = false;
1503956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    mEstimatedTrackSizeBytes = 0;
15041f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mNumStcoTableEntries = 0;
15051f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mNumStssTableEntries = 0;
15061f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mNumStscTableEntries = 0;
15071f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mNumSttsTableEntries = 0;
1508965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mNumCttsTableEntries = 0;
15091f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mMdatSizeBytes = 0;
1510f2ab12d0dcef27fd52dcae53221e9c51a369fef6James Dong
151143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mMaxChunkDurationUs = 0;
1512965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mHasNegativeCttsDeltaDuration = false;
151320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
151425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    pthread_create(&mThread, &attr, ThreadWrapper, this);
151520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_destroy(&attr);
151625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
151725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
151820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
151920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
152037187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::pause() {
1521a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
152237187916a486504acaf83bea30147eb5fbf46ae5James Dong    return OK;
1523a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
1524a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
152537187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::stop() {
1526b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("Stopping %s track", mIsAudio? "Audio": "Video");
1527eaae38445a340c4857c1c5569475879a728e63b7James Dong    if (!mStarted) {
1528eaae38445a340c4857c1c5569475879a728e63b7James Dong        LOGE("Stop() called but track is not started");
1529eaae38445a340c4857c1c5569475879a728e63b7James Dong        return ERROR_END_OF_STREAM;
1530eaae38445a340c4857c1c5569475879a728e63b7James Dong    }
1531eaae38445a340c4857c1c5569475879a728e63b7James Dong
153220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mDone) {
153337187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
153420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
153520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = true;
153620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
153720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *dummy;
153820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_join(mThread, &dummy);
153920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
154037187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = (status_t) dummy;
154137187916a486504acaf83bea30147eb5fbf46ae5James Dong
1542b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("Stopping %s track source", mIsAudio? "Audio": "Video");
154337187916a486504acaf83bea30147eb5fbf46ae5James Dong    {
154437187916a486504acaf83bea30147eb5fbf46ae5James Dong        status_t status = mSource->stop();
154537187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (err == OK && status != OK && status != ERROR_END_OF_STREAM) {
154637187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
154737187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
154837187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
154937187916a486504acaf83bea30147eb5fbf46ae5James Dong
1550b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("%s track stopped", mIsAudio? "Audio": "Video");
155137187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
155220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
155320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
155425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() {
155525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return mReachedEOS;
155625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
155725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
155820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static
155920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) {
156020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = static_cast<Track *>(me);
156120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
156237187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = track->threadEntry();
156337187916a486504acaf83bea30147eb5fbf46ae5James Dong    return (void *) err;
156420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
156520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
15663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic void getNalUnitType(uint8_t byte, uint8_t* type) {
15673856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("getNalUnitType: %d", byte);
15683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
15693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // nal_unit_type: 5-bit unsigned integer
15703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *type = (byte & 0x1F);
15713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
15723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
15733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t *findNextStartCode(
15743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length) {
15753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
15763856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("findNextStartCode: %p %d", data, length);
15773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
15783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t bytesLeft = length;
15793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    while (bytesLeft > 4  &&
15803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            memcmp("\x00\x00\x00\x01", &data[length - bytesLeft], 4)) {
15813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        --bytesLeft;
15823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
15833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (bytesLeft <= 4) {
15843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        bytesLeft = 0; // Last parameter set
15853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
15863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return &data[length - bytesLeft];
15873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
15883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
15893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongconst uint8_t *MPEG4Writer::Track::parseParamSet(
15903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen) {
15913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
15923856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("parseParamSet");
15933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    CHECK(type == kNalUnitTypeSeqParamSet ||
15943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong          type == kNalUnitTypePicParamSet);
15953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
15963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *nextStartCode = findNextStartCode(data, length);
15973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *paramSetLen = nextStartCode - data;
15983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (*paramSetLen == 0) {
15993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        LOGE("Param set is malformed, since its length is 0");
16003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return NULL;
16013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
16023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
16033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    AVCParamSet paramSet(*paramSetLen, data);
16043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (type == kNalUnitTypeSeqParamSet) {
16053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (*paramSetLen < 4) {
16063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Seq parameter set malformed");
16073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return NULL;
16083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
16093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mSeqParamSets.empty()) {
16103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc = data[1];
16113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileCompatible = data[2];
16123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mLevelIdc = data[3];
16133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
16143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (mProfileIdc != data[1] ||
16153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mProfileCompatible != data[2] ||
16163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mLevelIdc != data[3]) {
16173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                LOGE("Inconsistent profile/level found in seq parameter sets");
16183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return NULL;
16193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
16203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
16213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mSeqParamSets.push_back(paramSet);
16223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    } else {
16233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mPicParamSets.push_back(paramSet);
16243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
16253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return nextStartCode;
16263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
16273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
16283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::copyAVCCodecSpecificData(
16293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
16303856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("copyAVCCodecSpecificData");
16313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
16323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 2 bytes for each of the parameter set length field
16333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // plus the 7 bytes for the header
16343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (size < 4 + 7) {
16353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        LOGE("Codec specific data length too short: %d", size);
16363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return ERROR_MALFORMED;
16373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
16383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
16393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize = size;
16403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificData = malloc(size);
16413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    memcpy(mCodecSpecificData, data, size);
16423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
16433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
16443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
16453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::parseAVCCodecSpecificData(
16463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
16473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
16483856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("parseAVCCodecSpecificData");
16493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data starts with a start code.
16503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // SPS and PPS are separated with start codes.
16513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Also, SPS must come before PPS
16523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t type = kNalUnitTypeSeqParamSet;
16533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotSps = false;
16543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotPps = false;
16553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *tmp = data;
16563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *nextStartCode = data;
16573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t bytesLeft = size;
16583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t paramSetLen = 0;
16593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize = 0;
16603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) {
16613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        getNalUnitType(*(tmp + 4), &type);
16623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (type == kNalUnitTypeSeqParamSet) {
16633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (gotPps) {
16643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                LOGE("SPS must come before PPS");
16653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
16663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
16673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
16683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotSps = true;
16693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
16703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
16713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else if (type == kNalUnitTypePicParamSet) {
16723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
16733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                LOGE("SPS must come before PPS");
16743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
16753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
16763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotPps) {
16773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotPps = true;
16783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
16793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
16803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
16813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Only SPS and PPS Nal units are expected");
16823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
16833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
16843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
16853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nextStartCode == NULL) {
16863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
16873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
16883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
16893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Move on to find the next parameter set
16903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        bytesLeft -= nextStartCode - tmp;
16913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        tmp = nextStartCode;
16923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mCodecSpecificDataSize += (2 + paramSetLen);
16933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
16943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
16953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
16963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of seq parameter sets
16973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nSeqParamSets = mSeqParamSets.size();
16983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets == 0) {
16993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Cound not find sequence parameter set");
17003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
17013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
17023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
17033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets > 0x1F) {
17043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Too many seq parameter sets (%d) found", nSeqParamSets);
17053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
17063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
17073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
17083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
17093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
17103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of pic parameter sets
17113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nPicParamSets = mPicParamSets.size();
17123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets == 0) {
17133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Cound not find picture parameter set");
17143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
17153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
17163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets > 0xFF) {
17173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Too many pic parameter sets (%d) found", nPicParamSets);
17183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
17193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
17203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
17211374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// FIXME:
17221374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// Add chromat_format_idc, bit depth values, etc for AVC/h264 high profile and above
17231374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// and remove #if 0
17241374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#if 0
17253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
17263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the profiles
17273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // These profiles requires additional parameter set extensions
17283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mProfileIdc == 100 || mProfileIdc == 110 ||
17293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc == 122 || mProfileIdc == 144) {
17303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Sorry, no support for profile_idc: %d!", mProfileIdc);
17313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return BAD_VALUE;
17323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
17333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
17341374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#endif
17353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
17363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
1737548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
173803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData(
173903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        const uint8_t *data, size_t size) {
1740548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
174103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (mCodecSpecificData != NULL) {
1742548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        LOGE("Already have codec specific data");
174303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
174403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
174503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
17463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (size < 4) {
17473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        LOGE("Codec specific data length too short: %d", size);
174803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
174903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
175003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
17513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data is in the form of AVCCodecSpecificData
17523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (memcmp("\x00\x00\x00\x01", data, 4)) {
17533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return copyAVCCodecSpecificData(data, size);
175403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
175503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
17563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (parseAVCCodecSpecificData(data, size) != OK) {
175703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
175803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
175903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
17603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // ISO 14496-15: AVC file format
17613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize += 7;  // 7 more bytes in the header
176203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    mCodecSpecificData = malloc(mCodecSpecificDataSize);
176303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    uint8_t *header = (uint8_t *)mCodecSpecificData;
17643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = 1;                     // version
17653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[1] = mProfileIdc;           // profile indication
17663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[2] = mProfileCompatible;    // profile compatibility
17673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[3] = mLevelIdc;
176803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
17693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne
1770b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (mOwner->useNalLengthFour()) {
1771b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        header[4] = 0xfc | 3;  // length size == 4 bytes
1772b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    } else {
1773b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        header[4] = 0xfc | 1;  // length size == 2 bytes
1774b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    }
177503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
17763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 3-bit '111' followed by 5-bit numSequenceParameterSets
17773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nSequenceParamSets = mSeqParamSets.size();
17783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[5] = 0xe0 | nSequenceParamSets;
17793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 6;
17803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mSeqParamSets.begin();
17813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mSeqParamSets.end(); ++it) {
17823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit sequence parameter set length
17833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t seqParamSetLength = it->mLength;
17843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = seqParamSetLength >> 8;
17853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = seqParamSetLength & 0xff;
17863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
17873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // SPS NAL unit (sequence parameter length bytes)
17883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, seqParamSetLength);
17893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + seqParamSetLength);
17903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
17913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
17923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 8-bit nPictureParameterSets
17933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nPictureParamSets = mPicParamSets.size();
17943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = nPictureParamSets;
17953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 1;
17963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mPicParamSets.begin();
17973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mPicParamSets.end(); ++it) {
17983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit picture parameter set length
17993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t picParamSetLength = it->mLength;
18003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = picParamSetLength >> 8;
18013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = picParamSetLength & 0xff;
18023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
18033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // PPS Nal unit (picture parameter set length bytes)
18043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, picParamSetLength);
18053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + picParamSetLength);
18063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
180703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
180803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    return OK;
180903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
181003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
1811872a481558350634a3fd5cb67939de288af00ecbJames Dong/*
1812872a481558350634a3fd5cb67939de288af00ecbJames Dong * Updates the drift time from the audio track so that
1813872a481558350634a3fd5cb67939de288af00ecbJames Dong * the video track can get the updated drift time information
1814872a481558350634a3fd5cb67939de288af00ecbJames Dong * from the file writer. The fluctuation of the drift time of the audio
1815872a481558350634a3fd5cb67939de288af00ecbJames Dong * encoding path is smoothed out with a simple filter by giving a larger
1816872a481558350634a3fd5cb67939de288af00ecbJames Dong * weight to more recently drift time. The filter coefficients, 0.5 and 0.5,
1817872a481558350634a3fd5cb67939de288af00ecbJames Dong * are heuristically determined.
1818872a481558350634a3fd5cb67939de288af00ecbJames Dong */
1819872a481558350634a3fd5cb67939de288af00ecbJames Dongvoid MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) {
1820872a481558350634a3fd5cb67939de288af00ecbJames Dong    int64_t driftTimeUs = 0;
1821872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) {
1822872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t prevDriftTimeUs = mOwner->getDriftTimeUs();
1823872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1;
1824872a481558350634a3fd5cb67939de288af00ecbJames Dong        mOwner->setDriftTimeUs(timeUs);
1825872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
1826872a481558350634a3fd5cb67939de288af00ecbJames Dong}
1827872a481558350634a3fd5cb67939de288af00ecbJames Dong
182837187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::threadEntry() {
182930ab66297501757d745b9ae10da61adcd891f497Andreas Huber    int32_t count = 0;
183013aec890216948b0c364f8f92792129d0335f506James Dong    const int64_t interleaveDurationUs = mOwner->interleaveDuration();
183143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    const bool hasMultipleTracks = (mOwner->numTracks() > 1);
183213aec890216948b0c364f8f92792129d0335f506James Dong    int64_t chunkTimestampUs = 0;
183313aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nChunks = 0;
183413aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nZeroLengthFrames = 0;
1835965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastTimestampUs = 0;      // Previous sample time stamp
1836965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastCttsTimeUs = 0;       // Previous sample time stamp
1837965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastDurationUs = 0;       // Between the previous two samples
1838965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t currDurationTicks = 0;    // Timescale based ticks
1839965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastDurationTicks = 0;    // Timescale based ticks
1840965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int32_t sampleCount = 1;          // Sample count in the current stts table entry
1841965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t currCttsDurTicks = 0;     // Timescale based ticks
1842965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastCttsDurTicks = 0;     // Timescale based ticks
1843965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int32_t cttsSampleCount = 1;      // Sample count in the current ctts table entry
1844965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    uint32_t previousSampleSize = 0;      // Size of the previous sample
1845a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    int64_t previousPausedDurationUs = 0;
1846965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t timestampUs = 0;
1847965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t cttsDeltaTimeUs = 0;
184805e65807d48c2c7b954af82eda0532a48948e96aJames Dong    bool hasBFrames = false;
1849e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
185005e65807d48c2c7b954af82eda0532a48948e96aJames Dong#if 1
185105e65807d48c2c7b954af82eda0532a48948e96aJames Dong    // XXX: Samsung's video encoder's output buffer timestamp
185205e65807d48c2c7b954af82eda0532a48948e96aJames Dong    // is not correct. see bug 4724339
185305e65807d48c2c7b954af82eda0532a48948e96aJames Dong    char value[PROPERTY_VALUE_MAX];
185405e65807d48c2c7b954af82eda0532a48948e96aJames Dong    if (property_get("rw.media.record.hasb", value, NULL) &&
185505e65807d48c2c7b954af82eda0532a48948e96aJames Dong        (!strcasecmp(value, "true") || !strcasecmp(value, "1"))) {
185605e65807d48c2c7b954af82eda0532a48948e96aJames Dong        hasBFrames = true;
185705e65807d48c2c7b954af82eda0532a48948e96aJames Dong    }
185805e65807d48c2c7b954af82eda0532a48948e96aJames Dong#endif
1859a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    if (mIsAudio) {
1860a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong        prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0);
1861a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    } else {
1862a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong        prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0);
1863a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    }
186486106f8b0641444c97a39e9788eeef55ab2a2ac6Glenn Kasten    androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
1865985f838934510983d8a887461e98dca60a6e858fJames Dong
1866d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong    sp<MetaData> meta_data;
186720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1868ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    mNumSamples = 0;
186993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t err = OK;
187020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBuffer *buffer;
187193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    while (!mDone && (err = mSource->read(&buffer)) == OK) {
187220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (buffer->range_length() == 0) {
187320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer->release();
187420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer = NULL;
187513aec890216948b0c364f8f92792129d0335f506James Dong            ++nZeroLengthFrames;
187620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            continue;
187720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
187820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1879a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // If the codec specific data has not been received yet, delay pause.
1880a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // After the codec specific data is received, discard what we received
1881a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // when the track is to be paused.
1882a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused && !mResumed) {
1883a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer->release();
1884a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer = NULL;
1885a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            continue;
1886a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
1887a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
188830ab66297501757d745b9ae10da61adcd891f497Andreas Huber        ++count;
188930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
189003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        int32_t isCodecConfig;
189103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig)
189203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                && isCodecConfig) {
1893548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            CHECK(!mGotAllCodecSpecificData);
1894548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
18951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (mIsAvc) {
189603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                status_t err = makeAVCCodecSpecificData(
189703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        (const uint8_t *)buffer->data()
189803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                            + buffer->range_offset(),
189903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        buffer->range_length());
1900be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                CHECK_EQ(OK, err);
19011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            } else if (mIsMPEG4) {
190203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificDataSize = buffer->range_length();
190303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificData = malloc(mCodecSpecificDataSize);
190403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                memcpy(mCodecSpecificData,
190503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        (const uint8_t *)buffer->data()
190603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                            + buffer->range_offset(),
190703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                       buffer->range_length());
190830ab66297501757d745b9ae10da61adcd891f497Andreas Huber            }
190930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
191030ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer->release();
191130ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer = NULL;
191230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
1913548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            mGotAllCodecSpecificData = true;
191430ab66297501757d745b9ae10da61adcd891f497Andreas Huber            continue;
1915a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
1916a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
1917d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // Make a deep copy of the MediaBuffer and Metadata and release
1918d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // the original as soon as we can
1919d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        MediaBuffer *copy = new MediaBuffer(buffer->range_length());
1920d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(),
1921d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong                buffer->range_length());
1922d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        copy->set_range(0, buffer->range_length());
1923d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data = new MetaData(*buffer->meta_data().get());
1924d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer->release();
1925d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer = NULL;
1926d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
19271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (mIsAvc) StripStartcode(copy);
1928e136c3bb38e88315bf8797a464ebf2c788296b22James Dong
1929b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        size_t sampleSize = copy->range_length();
1930b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        if (mIsAvc) {
1931b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            if (mOwner->useNalLengthFour()) {
1932b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                sampleSize += 4;
1933b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            } else {
1934b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                sampleSize += 2;
1935b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            }
1936b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        }
1937050b28a593350047845a45a14cc5026221ac1620James Dong
1938d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        // Max file size or duration handling
19391f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mMdatSizeBytes += sampleSize;
19401f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        updateTrackSizeEstimate();
19411f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1942d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileSizeLimit()) {
1943d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
1944d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
1945d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
1946d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileDurationLimit()) {
1947d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
1948d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
1949d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
1950d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1951050b28a593350047845a45a14cc5026221ac1620James Dong
1952d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        int32_t isSync = false;
1953d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data->findInt32(kKeyIsSyncFrame, &isSync);
1954d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        CHECK(meta_data->findInt64(kKeyTime, &timestampUs));
1955d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
1956d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong////////////////////////////////////////////////////////////////////////////////
195770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        if (mNumSamples == 0) {
195870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            mFirstSampleTimeRealUs = systemTime() / 1000;
1959f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mStartTimestampUs = timestampUs;
1960f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mOwner->setStartTimestampUs(mStartTimestampUs);
19618428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            previousPausedDurationUs = mStartTimestampUs;
19623c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        }
196348c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber
1964a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mResumed) {
19658428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs;
19668428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            CHECK(durExcludingEarlierPausesUs >= 0);
19678428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs;
19688428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            CHECK(pausedDurationUs >= lastDurationUs);
19698428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            previousPausedDurationUs += pausedDurationUs - lastDurationUs;
1970a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mResumed = false;
1971a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
1972a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
1973a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        timestampUs -= previousPausedDurationUs;
19748428af5381e835cc783b7ecb0d71cb60961c99c2James Dong        CHECK(timestampUs >= 0);
197505e65807d48c2c7b954af82eda0532a48948e96aJames Dong        if (!mIsAudio && hasBFrames) {
1976965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            /*
1977965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             * Composition time: timestampUs
1978965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             * Decoding time: decodingTimeUs
1979965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             * Composition time delta = composition time - decoding time
1980965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             *
1981965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             * We save picture decoding time stamp delta in stts table entries,
1982965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             * and composition time delta duration in ctts table entries.
1983965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             */
1984965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            int64_t decodingTimeUs;
1985965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs));
1986965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            decodingTimeUs -= previousPausedDurationUs;
1987965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            int64_t timeUs = decodingTimeUs;
1988965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            cttsDeltaTimeUs = timestampUs - decodingTimeUs;
1989965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            timestampUs = decodingTimeUs;
19903856b090cd04ba5dd4a59a12430ed724d5995909Steve Block            ALOGV("decoding time: %lld and ctts delta time: %lld",
1991965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong                timestampUs, cttsDeltaTimeUs);
1992965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        }
1993872a481558350634a3fd5cb67939de288af00ecbJames Dong
1994872a481558350634a3fd5cb67939de288af00ecbJames Dong        if (mIsRealTimeRecording) {
1995872a481558350634a3fd5cb67939de288af00ecbJames Dong            if (mIsAudio) {
1996872a481558350634a3fd5cb67939de288af00ecbJames Dong                updateDriftTime(meta_data);
1997e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            }
1998e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        }
1999872a481558350634a3fd5cb67939de288af00ecbJames Dong
2000e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        CHECK(timestampUs >= 0);
20013856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("%s media time stamp: %lld and previous paused duration %lld",
20028428af5381e835cc783b7ecb0d71cb60961c99c2James Dong                mIsAudio? "Audio": "Video", timestampUs, previousPausedDurationUs);
2003c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong        if (timestampUs > mTrackDurationUs) {
2004c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong            mTrackDurationUs = timestampUs;
20053b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber        }
20063b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber
20075a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // We need to use the time scale based ticks, rather than the
20085a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // timestamp itself to determine whether we have to use a new
20095a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // stts entry, since we may have rounding errors.
20105a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // The calculation is intended to reduce the accumulated
20115a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // rounding errors.
20125a217fba010e801c255503602bda4b86ac5a6ac9James Dong        currDurationTicks =
20135a217fba010e801c255503602bda4b86ac5a6ac9James Dong            ((timestampUs * mTimeScale + 500000LL) / 1000000LL -
20145a217fba010e801c255503602bda4b86ac5a6ac9James Dong                (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL);
20155a217fba010e801c255503602bda4b86ac5a6ac9James Dong
20168644c14618d30d9e57a69df40ed939986ebf02c4James Dong        mSampleSizes.push_back(sampleSize);
2017ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong        ++mNumSamples;
2018ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong        if (mNumSamples > 2) {
2019c059860c73678a202bfa33062723e8f82fb779d9James Dong
2020a472613aec322e25891abf5c77bf3f7e3c244920James Dong            // Force the first sample to have its own stts entry so that
2021a472613aec322e25891abf5c77bf3f7e3c244920James Dong            // we can adjust its value later to maintain the A/V sync.
2022a472613aec322e25891abf5c77bf3f7e3c244920James Dong            if (mNumSamples == 3 || currDurationTicks != lastDurationTicks) {
20233856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("%s lastDurationUs: %lld us, currDurationTicks: %lld us",
2024a472613aec322e25891abf5c77bf3f7e3c244920James Dong                        mIsAudio? "Audio": "Video", lastDurationUs, currDurationTicks);
202579761ab096f57c3027fad9556c2bc436672d614eJames Dong                addOneSttsTableEntry(sampleCount, lastDurationTicks);
2026be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                sampleCount = 1;
2027be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            } else {
2028be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                ++sampleCount;
2029be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
2030965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2031965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            if (!mIsAudio) {
2032965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong                currCttsDurTicks =
2033965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong                     ((cttsDeltaTimeUs * mTimeScale + 500000LL) / 1000000LL -
2034965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong                     (lastCttsTimeUs * mTimeScale + 500000LL) / 1000000LL);
2035965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong                if (currCttsDurTicks != lastCttsDurTicks) {
2036965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong                    addOneCttsTableEntry(cttsSampleCount, lastCttsDurTicks);
2037965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong                    cttsSampleCount = 1;
2038965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong                } else {
2039965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong                    ++cttsSampleCount;
2040965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong                }
2041965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            }
2042be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
2043be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        if (mSamplesHaveSameSize) {
2044ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong            if (mNumSamples >= 2 && previousSampleSize != sampleSize) {
2045be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mSamplesHaveSameSize = false;
2046be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
20478644c14618d30d9e57a69df40ed939986ebf02c4James Dong            previousSampleSize = sampleSize;
2048be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
20493856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("%s timestampUs/lastTimestampUs: %lld/%lld",
2050a472613aec322e25891abf5c77bf3f7e3c244920James Dong                mIsAudio? "Audio": "Video", timestampUs, lastTimestampUs);
20518644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastDurationUs = timestampUs - lastTimestampUs;
2052c059860c73678a202bfa33062723e8f82fb779d9James Dong        lastDurationTicks = currDurationTicks;
20538644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastTimestampUs = timestampUs;
205420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2055965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        if (!mIsAudio) {
2056965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            lastCttsDurTicks = currCttsDurTicks;
2057965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            lastCttsTimeUs = cttsDeltaTimeUs;
2058965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        }
2059965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2060d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        if (isSync != 0) {
20611f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            addOneStssTableEntry(mNumSamples);
2062d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        }
2063d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
206493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (mTrackingProgressStatus) {
206593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            if (mPreviousTrackTimeUs <= 0) {
206693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong                mPreviousTrackTimeUs = mStartTimestampUs;
206793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            }
2068faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong            trackProgressStatus(timestampUs);
206993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
207043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong        if (!hasMultipleTracks) {
2071c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t offset = mIsAvc? mOwner->addLengthPrefixedSample_l(copy)
207258ae9c530247668f8af36e30d228c716c226b3d4James Dong                                 : mOwner->addSample_l(copy);
207358ae9c530247668f8af36e30d228c716c226b3d4James Dong            if (mChunkOffsets.empty()) {
20741f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                addChunkOffset(offset);
207558ae9c530247668f8af36e30d228c716c226b3d4James Dong            }
207658ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy->release();
207758ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy = NULL;
207858ae9c530247668f8af36e30d228c716c226b3d4James Dong            continue;
207958ae9c530247668f8af36e30d228c716c226b3d4James Dong        }
208013aec890216948b0c364f8f92792129d0335f506James Dong
208113aec890216948b0c364f8f92792129d0335f506James Dong        mChunkSamples.push_back(copy);
208213aec890216948b0c364f8f92792129d0335f506James Dong        if (interleaveDurationUs == 0) {
20831f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            addOneStscTableEntry(++nChunks, 1);
20841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            bufferChunk(timestampUs);
208513aec890216948b0c364f8f92792129d0335f506James Dong        } else {
208613aec890216948b0c364f8f92792129d0335f506James Dong            if (chunkTimestampUs == 0) {
208713aec890216948b0c364f8f92792129d0335f506James Dong                chunkTimestampUs = timestampUs;
208813aec890216948b0c364f8f92792129d0335f506James Dong            } else {
208943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                int64_t chunkDurationUs = timestampUs - chunkTimestampUs;
209043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                if (chunkDurationUs > interleaveDurationUs) {
209143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    if (chunkDurationUs > mMaxChunkDurationUs) {
209243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                        mMaxChunkDurationUs = chunkDurationUs;
209343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    }
209413aec890216948b0c364f8f92792129d0335f506James Dong                    ++nChunks;
209513aec890216948b0c364f8f92792129d0335f506James Dong                    if (nChunks == 1 ||  // First chunk
209613aec890216948b0c364f8f92792129d0335f506James Dong                        (--(mStscTableEntries.end()))->samplesPerChunk !=
209713aec890216948b0c364f8f92792129d0335f506James Dong                         mChunkSamples.size()) {
20981f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                        addOneStscTableEntry(nChunks, mChunkSamples.size());
209913aec890216948b0c364f8f92792129d0335f506James Dong                    }
21001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                    bufferChunk(timestampUs);
210113aec890216948b0c364f8f92792129d0335f506James Dong                    chunkTimestampUs = timestampUs;
210213aec890216948b0c364f8f92792129d0335f506James Dong                }
210313aec890216948b0c364f8f92792129d0335f506James Dong            }
210413aec890216948b0c364f8f92792129d0335f506James Dong        }
210513aec890216948b0c364f8f92792129d0335f506James Dong
210620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
210725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
210845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    if (isTrackMalFormed()) {
2109690f546b0ee548dbfe997df36418e5302ec2d786James Dong        err = ERROR_MALFORMED;
2110f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong    }
211145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
2112bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    mOwner->trackProgressStatus(mTrackId, -1, err);
2113be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
211413aec890216948b0c364f8f92792129d0335f506James Dong    // Last chunk
211543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    if (!hasMultipleTracks) {
21161f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        addOneStscTableEntry(1, mNumSamples);
211758ae9c530247668f8af36e30d228c716c226b3d4James Dong    } else if (!mChunkSamples.empty()) {
21181f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        addOneStscTableEntry(++nChunks, mChunkSamples.size());
21191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        bufferChunk(timestampUs);
212013aec890216948b0c364f8f92792129d0335f506James Dong    }
212113aec890216948b0c364f8f92792129d0335f506James Dong
2122be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // We don't really know how long the last frame lasts, since
2123be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // there is no frame time after it, just repeat the previous
2124be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // frame's duration.
2125ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    if (mNumSamples == 1) {
21268f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        lastDurationUs = 0;  // A single sample's duration
212779761ab096f57c3027fad9556c2bc436672d614eJames Dong        lastDurationTicks = 0;
2128965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        lastCttsDurTicks = 0;
2129be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    } else {
2130be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        ++sampleCount;  // Count for the last sample
2131965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        ++cttsSampleCount;
2132be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    }
2133a472613aec322e25891abf5c77bf3f7e3c244920James Dong
2134a472613aec322e25891abf5c77bf3f7e3c244920James Dong    if (mNumSamples <= 2) {
213579761ab096f57c3027fad9556c2bc436672d614eJames Dong        addOneSttsTableEntry(1, lastDurationTicks);
2136a472613aec322e25891abf5c77bf3f7e3c244920James Dong        if (sampleCount - 1 > 0) {
213779761ab096f57c3027fad9556c2bc436672d614eJames Dong            addOneSttsTableEntry(sampleCount - 1, lastDurationTicks);
2138a472613aec322e25891abf5c77bf3f7e3c244920James Dong        }
2139a472613aec322e25891abf5c77bf3f7e3c244920James Dong    } else {
214079761ab096f57c3027fad9556c2bc436672d614eJames Dong        addOneSttsTableEntry(sampleCount, lastDurationTicks);
2141a472613aec322e25891abf5c77bf3f7e3c244920James Dong    }
2142a472613aec322e25891abf5c77bf3f7e3c244920James Dong
2143965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    addOneCttsTableEntry(cttsSampleCount, lastCttsDurTicks);
2144c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs += lastDurationUs;
214525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = true;
214643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
214743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    sendTrackSummary(hasMultipleTracks);
214843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
2149df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s",
21501f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            count, nZeroLengthFrames, mNumSamples, mIsAudio? "audio": "video");
2151872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (mIsAudio) {
2152df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("Audio track drift time: %lld us", mOwner->getDriftTimeUs());
2153872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
2154365a963142093a1cd8efdcea76b5f65096a5b115James Dong
215537187916a486504acaf83bea30147eb5fbf46ae5James Dong    if (err == ERROR_END_OF_STREAM) {
215637187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
215737187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
215837187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
2159365a963142093a1cd8efdcea76b5f65096a5b115James Dong}
2160365a963142093a1cd8efdcea76b5f65096a5b115James Dong
216145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dongbool MPEG4Writer::Track::isTrackMalFormed() const {
216245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    if (mSampleSizes.empty()) {                      // no samples written
216345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        LOGE("The number of recorded samples is 0");
216445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
216545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
216645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
216745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    if (!mIsAudio && mNumStssTableEntries == 0) {  // no sync frames for video
216845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        LOGE("There are no sync frames for video track");
216945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
217045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
217145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
217245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    if (OK != checkCodecSpecificData()) {         // no codec specific data
217345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
217445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
217545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
217645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    return false;
217745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong}
217845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
217943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dongvoid MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) {
218007ec01904613a0bac32caaa8444b4690998faed7James Dong
218107ec01904613a0bac32caaa8444b4690998faed7James Dong    // Send track summary only if test mode is enabled.
218207ec01904613a0bac32caaa8444b4690998faed7James Dong    if (!isTestModeEnabled()) {
218307ec01904613a0bac32caaa8444b4690998faed7James Dong        return;
218407ec01904613a0bac32caaa8444b4690998faed7James Dong    }
218507ec01904613a0bac32caaa8444b4690998faed7James Dong
218643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    int trackNum = (mTrackId << 28);
218743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
218843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
218943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_TYPE,
219043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mIsAudio? 0: 1);
219143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
219243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
219343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_DURATION_MS,
219443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mTrackDurationUs / 1000);
219543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
219643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
219743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES,
219843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mNumSamples);
219943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
220086b7f47aa7482424cf8fd248f1315311919be3b0James Dong    {
220186b7f47aa7482424cf8fd248f1315311919be3b0James Dong        // The system delay time excluding the requested initial delay that
220286b7f47aa7482424cf8fd248f1315311919be3b0James Dong        // is used to eliminate the recording sound.
220386b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL;
220486b7f47aa7482424cf8fd248f1315311919be3b0James Dong        if (startTimeOffsetUs < 0) {  // Start time offset was not set
220586b7f47aa7482424cf8fd248f1315311919be3b0James Dong            startTimeOffsetUs = kInitialDelayTimeUs;
220686b7f47aa7482424cf8fd248f1315311919be3b0James Dong        }
220786b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t initialDelayUs =
220886b7f47aa7482424cf8fd248f1315311919be3b0James Dong            mFirstSampleTimeRealUs - mStartTimeRealUs - startTimeOffsetUs;
220986b7f47aa7482424cf8fd248f1315311919be3b0James Dong
221086b7f47aa7482424cf8fd248f1315311919be3b0James Dong        mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
221170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS,
221270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    (initialDelayUs) / 1000);
221386b7f47aa7482424cf8fd248f1315311919be3b0James Dong    }
221470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
221507ec01904613a0bac32caaa8444b4690998faed7James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
221607ec01904613a0bac32caaa8444b4690998faed7James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES,
221707ec01904613a0bac32caaa8444b4690998faed7James Dong                    mMdatSizeBytes / 1024);
221807ec01904613a0bac32caaa8444b4690998faed7James Dong
221943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    if (hasMultipleTracks) {
222043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong        mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
222143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS,
222243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mMaxChunkDurationUs / 1000);
222370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
222470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
222570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        if (mStartTimestampUs != moovStartTimeUs) {
222670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            int64_t startTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
222770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
222870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS,
222970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    startTimeOffsetUs / 1000);
223070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        }
223143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    }
223243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong}
223343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
2234faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) {
22353856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("trackProgressStatus: %lld us", timeUs);
2236215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    if (mTrackEveryTimeDurationUs > 0 &&
2237215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) {
22383856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("Fire time tracking progress status at %lld us", timeUs);
2239bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err);
224093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        mPreviousTrackTimeUs = timeUs;
224193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
224293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
224393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
2244faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::trackProgressStatus(
2245bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        size_t trackId, int64_t timeUs, status_t err) {
2246faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    Mutex::Autolock lock(mLock);
2247bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    int32_t trackNum = (trackId << 28);
2248faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
2249faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Error notification
2250faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Do not consider ERROR_END_OF_STREAM an error
2251faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (err != OK && err != ERROR_END_OF_STREAM) {
2252bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_ERROR,
2253bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL,
2254faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
2255faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        return;
2256faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
2257faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
2258faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (timeUs == -1) {
2259faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send completion notification
2260bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
2261bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS,
2262faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
2263faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    } else {
2264faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send progress status
2265bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
2266bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME,
2267faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               timeUs / 1000);
2268faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
2269faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong}
2270faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
2271d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dongvoid MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) {
22723856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setDriftTimeUs: %lld us", driftTimeUs);
2273e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
2274d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong    mDriftTimeUs = driftTimeUs;
2275e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
2276e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
2277e259531ce59ab1f31de5a23124b22536f6a5a767James Dongint64_t MPEG4Writer::getDriftTimeUs() {
22783856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("getDriftTimeUs: %lld us", mDriftTimeUs);
2279e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
2280e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    return mDriftTimeUs;
2281e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
2282e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
2283b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dongbool MPEG4Writer::useNalLengthFour() {
2284b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    return mUse4ByteNalLength;
2285b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong}
2286b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong
22871c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::Track::bufferChunk(int64_t timestampUs) {
22883856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("bufferChunk");
22891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
22901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Chunk chunk(this, timestampUs, mChunkSamples);
22911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mOwner->bufferChunk(chunk);
229213aec890216948b0c364f8f92792129d0335f506James Dong    mChunkSamples.clear();
229320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
229420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
22953b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const {
2296c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    return mTrackDurationUs;
229720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
229820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2299d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const {
2300d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return mEstimatedTrackSizeBytes;
2301d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
2302d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
2303690f546b0ee548dbfe997df36418e5302ec2d786James Dongstatus_t MPEG4Writer::Track::checkCodecSpecificData() const {
2304690f546b0ee548dbfe997df36418e5302ec2d786James Dong    const char *mime;
2305690f546b0ee548dbfe997df36418e5302ec2d786James Dong    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
2306690f546b0ee548dbfe997df36418e5302ec2d786James Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) ||
2307690f546b0ee548dbfe997df36418e5302ec2d786James Dong        !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) ||
2308690f546b0ee548dbfe997df36418e5302ec2d786James Dong        !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
2309690f546b0ee548dbfe997df36418e5302ec2d786James Dong        if (!mCodecSpecificData ||
2310690f546b0ee548dbfe997df36418e5302ec2d786James Dong            mCodecSpecificDataSize <= 0) {
2311a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong            LOGE("Missing codec specific data");
2312690f546b0ee548dbfe997df36418e5302ec2d786James Dong            return ERROR_MALFORMED;
2313690f546b0ee548dbfe997df36418e5302ec2d786James Dong        }
2314690f546b0ee548dbfe997df36418e5302ec2d786James Dong    } else {
2315690f546b0ee548dbfe997df36418e5302ec2d786James Dong        if (mCodecSpecificData ||
2316690f546b0ee548dbfe997df36418e5302ec2d786James Dong            mCodecSpecificDataSize > 0) {
2317a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong            LOGE("Unexepected codec specific data found");
2318690f546b0ee548dbfe997df36418e5302ec2d786James Dong            return ERROR_MALFORMED;
2319690f546b0ee548dbfe997df36418e5302ec2d786James Dong        }
2320690f546b0ee548dbfe997df36418e5302ec2d786James Dong    }
2321690f546b0ee548dbfe997df36418e5302ec2d786James Dong    return OK;
2322690f546b0ee548dbfe997df36418e5302ec2d786James Dong}
2323690f546b0ee548dbfe997df36418e5302ec2d786James Dong
2324b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeTrackHeader(bool use32BitOffset) {
232520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
23263856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("%s track time scale: %d",
23271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsAudio? "Audio": "Video", mTimeScale);
23288f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
232920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    time_t now = time(NULL);
2330b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("trak");
2331b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeTkhdBox(now);
2332b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->beginBox("mdia");
2333b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            writeMdhdBox(now);
2334b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            writeHdlrBox();
2335b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            mOwner->beginBox("minf");
2336b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                if (mIsAudio) {
2337b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                    writeSmhdBox();
2338b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                } else {
2339b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                    writeVmhdBox();
2340b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                }
2341b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                writeDinfBox();
2342b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                writeStblBox(use32BitOffset);
2343b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            mOwner->endBox();  // minf
2344b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->endBox();  // mdia
2345b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // trak
2346b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2347b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2348b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStblBox(bool use32BitOffset) {
2349b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stbl");
2350b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsd");
2351b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);               // version=0, flags=0
2352b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);               // entry count
2353b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mIsAudio) {
2354b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeAudioFourCCBox();
2355b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
2356b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeVideoFourCCBox();
2357b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2358b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsd
2359b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeSttsBox();
2360965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    writeCttsBox();
2361b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!mIsAudio) {
2362b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeStssBox();
2363b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2364b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStszBox();
2365b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStscBox();
2366b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStcoBox(use32BitOffset);
2367b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stbl
2368b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2369b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2370b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVideoFourCCBox() {
2371b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    const char *mime;
2372b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    bool success = mMeta->findCString(kKeyMIMEType, &mime);
2373b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
2374b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
2375b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->beginBox("mp4v");
2376b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
2377b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->beginBox("s263");
2378b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
2379b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->beginBox("avc1");
2380b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
2381b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        LOGE("Unknown mime type '%s'.", mime);
2382b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        CHECK(!"should not be here, unknown mime type.");
2383b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2384b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2385b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2386b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2387b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(1);           // data ref index
2388b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // predefined
2389b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2390b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
2391b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
2392b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
2393b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2394b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t width, height;
2395b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = mMeta->findInt32(kKeyWidth, &width);
2396b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = success && mMeta->findInt32(kKeyHeight, &height);
2397b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
2398b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2399b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(width);
2400b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(height);
2401b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x480000);    // horiz resolution
2402b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x480000);    // vert resolution
2403b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2404b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(1);           // frame count
2405b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write("                                ", 32);
2406b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x18);        // depth
2407b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(-1);          // predefined
2408b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2409b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(23 + mCodecSpecificDataSize < 128);
2410b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2411b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
2412b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeMp4vEsdsBox();
2413b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
2414b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeD263Box();
2415b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
2416b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeAvccBox();
2417b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2418b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2419b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writePaspBox();
2420b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // mp4v, s263 or avc1
2421b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2422b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2423b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAudioFourCCBox() {
2424b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    const char *mime;
2425b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    bool success = mMeta->findCString(kKeyMIMEType, &mime);
2426b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
2427b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    const char *fourcc = NULL;
2428b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) {
2429b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        fourcc = "samr";
2430b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
2431b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        fourcc = "sawb";
2432b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
2433b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        fourcc = "mp4a";
2434b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
2435b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        LOGE("Unknown mime type '%s'.", mime);
2436b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        CHECK(!"should not be here, unknown mime type.");
2437b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2438b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2439b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox(fourcc);        // audio format
2440b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2441b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2442b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x1);         // data ref index
2443b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2444b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2445b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t nChannels;
2446b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels));
2447b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(nChannels);   // channel count
2448b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(16);          // sample size
2449b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // predefined
2450b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2451b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2452b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t samplerate;
2453b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = mMeta->findInt32(kKeySampleRate, &samplerate);
2454b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
2455b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(samplerate << 16);
2456b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
2457b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeMp4aEsdsBox();
2458b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) ||
2459b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong               !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
2460b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeDamrBox();
2461b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2462b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2463b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2464b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2465b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4aEsdsBox() {
2466b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("esds");
2467b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
2468b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificDataSize > 0);
2469b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2470b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Make sure all sizes encode to a single byte.
2471b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificDataSize + 23 < 128);
2472b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2473b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);     // version=0, flags=0
2474b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x03);   // ES_DescrTag
2475b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(23 + mCodecSpecificDataSize);
2476b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x0000);// ES_ID
2477b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x00);
2478b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2479b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x04);   // DecoderConfigDescrTag
2480b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(15 + mCodecSpecificDataSize);
2481b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x40);   // objectTypeIndication ISO/IEC 14492-2
2482b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x15);   // streamType AudioStream
2483b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2484b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x03);  // XXX
2485b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x00);   // buffer size 24-bit
2486b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(96000); // max bit rate
2487b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(96000); // avg bit rate
2488b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2489b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x05);   // DecoderSpecificInfoTag
2490b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(mCodecSpecificDataSize);
2491b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
2492b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2493b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData2[] = {
2494b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x06,  // SLConfigDescriptorTag
2495b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x01,
2496b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x02
2497b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
2498b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData2, sizeof(kData2));
2499b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2500b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // esds
2501b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2502b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2503b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4vEsdsBox() {
2504b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
2505b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificDataSize > 0);
2506b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("esds");
2507b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2508b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);    // version=0, flags=0
2509b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2510b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x03);  // ES_DescrTag
2511b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(23 + mCodecSpecificDataSize);
2512b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x0000);  // ES_ID
2513b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x1f);
2514b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2515b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x04);  // DecoderConfigDescrTag
2516b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(15 + mCodecSpecificDataSize);
2517b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x20);  // objectTypeIndication ISO/IEC 14492-2
2518b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x11);  // streamType VisualStream
2519b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2520b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData[] = {
2521b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x01, 0x77, 0x00,
2522b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x00, 0x03, 0xe8, 0x00,
2523b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x00, 0x03, 0xe8, 0x00
2524b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
2525b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData, sizeof(kData));
2526b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2527b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x05);  // DecoderSpecificInfoTag
2528b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2529b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(mCodecSpecificDataSize);
2530b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
2531b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2532b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData2[] = {
2533b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x06,  // SLConfigDescriptorTag
2534b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x01,
2535b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x02
2536b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
2537b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData2, sizeof(kData2));
2538b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2539b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // esds
2540b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2541b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2542b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeTkhdBox(time_t now) {
2543b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("tkhd");
2544b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Flags = 7 to indicate that the track is enabled, and
2545b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // part of the presentation
2546b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x07);          // version=0, flags=7
2547b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // creation time
2548b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // modification time
2549b5212db69734962f55e1493d3e696794172ced51James Dong    mOwner->writeInt32(mTrackId + 1);  // track id starts with 1
2550b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
25518f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t trakDurationUs = getDurationUs();
2552b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t mvhdTimeScale = mOwner->getTimeScale();
2553b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t tkhdDuration =
2554b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
2555b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(tkhdDuration);  // in mvhd timescale
2556b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
2557b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
2558b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // layer
2559b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // alternate group
2560b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(mIsAudio ? 0x100 : 0);  // volume
2561b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // reserved
2562b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2563b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCompositionMatrix(mRotation);       // matrix
256420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2565b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mIsAudio) {
2566b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(0);
2567b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(0);
2568b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
2569b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        int32_t width, height;
2570b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        bool success = mMeta->findInt32(kKeyWidth, &width);
2571b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        success = success && mMeta->findInt32(kKeyHeight, &height);
2572b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        CHECK(success);
2573b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2574b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(width << 16);   // 32-bit fixed-point value
2575b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(height << 16);  // 32-bit fixed-point value
2576b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2577b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // tkhd
2578b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2579b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2580b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVmhdBox() {
2581b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("vmhd");
2582b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x01);        // version=0, flags=1
2583b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // graphics mode
2584b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // opcolor
2585b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);
2586b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);
2587b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2588b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2589b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2590b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeSmhdBox() {
2591b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("smhd");
2592b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // version=0, flags=0
2593b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // balance
2594b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2595b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2596b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2597b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2598b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeHdlrBox() {
2599b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("hdlr");
2600b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // version=0, flags=0
2601b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // component type: should be mhlr
2602b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeFourcc(mIsAudio ? "soun" : "vide");  // component subtype
2603b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
2604b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
2605b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
2606b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Removing "r" for the name string just makes the string 4 byte aligned
2607b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle");  // name
2608b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2609b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2610b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2611b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMdhdBox(time_t now) {
2612b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int64_t trakDurationUs = getDurationUs();
2613b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("mdhd");
2614b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // version=0, flags=0
2615b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // creation time
2616b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // modification time
2617b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(mTimeScale);    // media timescale
2618b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6;
2619b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(mdhdDuration);  // use media timescale
2620b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Language follows the three letter standard ISO-639-2/T
2621b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // 'e', 'n', 'g' for "English", for instance.
2622b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Each character is packed as the difference between its ASCII value and 0x60.
2623b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // For "English", these are 00101, 01110, 00111.
2624b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // XXX: Where is the padding bit located: 0x15C7?
2625b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // language code
2626b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // predefined
2627b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2628b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2629b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2630b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDamrBox() {
2631b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // 3gpp2 Spec AMRSampleEntry fields
2632b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("damr");
2633b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCString("   ");  // vendor: 4 bytes
2634b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);         // decoder version
2635b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x83FF);   // mode set: all enabled
2636b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);         // mode change period
2637b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(1);         // frames per sample
2638b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2639b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2640b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2641b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeUrlBox() {
2642b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // The table index here refers to the sample description index
2643b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // in the sample table entries.
2644b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("url ");
2645b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);  // version=0, flags=1 (self-contained)
2646b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // url
2647b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2648b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2649b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDrefBox() {
2650b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("dref");
2651b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
2652b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);  // entry count (either url or urn)
2653b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeUrlBox();
2654b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // dref
2655b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2656b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2657b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDinfBox() {
2658b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("dinf");
2659b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeDrefBox();
2660b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // dinf
2661b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2662b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2663b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAvccBox() {
2664b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
2665b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificDataSize >= 5);
2666b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2667b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Patch avcc's lengthSize field to match the number
2668b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // of bytes we use to indicate the size of a nal unit.
2669b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    uint8_t *ptr = (uint8_t *)mCodecSpecificData;
2670b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    ptr[4] = (ptr[4] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1);
2671b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("avcC");
2672b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
2673b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // avcC
2674b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2675b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2676b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeD263Box() {
2677b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("d263");
2678b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // vendor
2679b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);   // decoder version
2680b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(10);  // level: 10
2681b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);   // profile: 0
2682b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // d263
2683b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2684b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2685b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong// This is useful if the pixel is not square
2686b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writePaspBox() {
2687b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("pasp");
2688b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1 << 16);  // hspacing
2689b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1 << 16);  // vspacing
2690b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // pasp
2691b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2692b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2693b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeSttsBox() {
2694b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stts");
2695b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
2696b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(mNumSttsTableEntries);
269770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
2698a472613aec322e25891abf5c77bf3f7e3c244920James Dong    // Compensate for small start time difference from different media tracks
2699a472613aec322e25891abf5c77bf3f7e3c244920James Dong    int64_t trackStartTimeOffsetUs = 0;
2700b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
2701b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mStartTimestampUs != moovStartTimeUs) {
2702b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        CHECK(mStartTimestampUs > moovStartTimeUs);
2703b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        trackStartTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
2704b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
270579761ab096f57c3027fad9556c2bc436672d614eJames Dong    List<SttsTableEntry>::iterator it = mSttsTableEntries.begin();
270679761ab096f57c3027fad9556c2bc436672d614eJames Dong    CHECK(it != mSttsTableEntries.end() && it->sampleCount == 1);
270779761ab096f57c3027fad9556c2bc436672d614eJames Dong    mOwner->writeInt32(it->sampleCount);
270879761ab096f57c3027fad9556c2bc436672d614eJames Dong    int32_t dur = (trackStartTimeOffsetUs * mTimeScale + 500000LL) / 1000000LL;
270979761ab096f57c3027fad9556c2bc436672d614eJames Dong    mOwner->writeInt32(dur + it->sampleDuration);
2710a472613aec322e25891abf5c77bf3f7e3c244920James Dong
2711965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t totalCount = 1;
271279761ab096f57c3027fad9556c2bc436672d614eJames Dong    while (++it != mSttsTableEntries.end()) {
271379761ab096f57c3027fad9556c2bc436672d614eJames Dong        mOwner->writeInt32(it->sampleCount);
271479761ab096f57c3027fad9556c2bc436672d614eJames Dong        mOwner->writeInt32(it->sampleDuration);
2715965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        totalCount += it->sampleCount;
2716b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2717965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    CHECK(totalCount == mNumSamples);
2718b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stts
2719b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
272020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2721965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::writeCttsBox() {
2722965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    if (mIsAudio) {  // ctts is not for audio
2723965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
2724965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
2725965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2726965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    // Do not write ctts box when there is no need to have it.
2727965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    if ((mNumCttsTableEntries == 1 &&
2728965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        mCttsTableEntries.begin()->sampleDuration == 0) ||
2729965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        mNumCttsTableEntries == 0) {
2730965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
2731965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
2732965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
27333856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("ctts box has %d entries", mNumCttsTableEntries);
2734965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2735965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mOwner->beginBox("ctts");
2736965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    if (mHasNegativeCttsDeltaDuration) {
2737965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        mOwner->writeInt32(0x00010000);  // version=1, flags=0
2738965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    } else {
2739965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        mOwner->writeInt32(0);  // version=0, flags=0
2740965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
2741965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mOwner->writeInt32(mNumCttsTableEntries);
2742965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2743965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t totalCount = 0;
2744965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    for (List<CttsTableEntry>::iterator it = mCttsTableEntries.begin();
2745965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong         it != mCttsTableEntries.end(); ++it) {
2746965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        mOwner->writeInt32(it->sampleCount);
2747965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        mOwner->writeInt32(it->sampleDuration);
2748965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        totalCount += it->sampleCount;
2749965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
2750965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    CHECK(totalCount == mNumSamples);
2751965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mOwner->endBox();  // ctts
2752965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong}
2753965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2754b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStssBox() {
2755b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stss");
2756b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
2757b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(mNumStssTableEntries);  // number of sync frames
2758b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    for (List<int32_t>::iterator it = mStssTableEntries.begin();
2759b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        it != mStssTableEntries.end(); ++it) {
2760b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(*it);
2761b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2762b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stss
2763b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
276425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
2765b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStszBox() {
2766b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsz");
2767b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
2768b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mSamplesHaveSameSize) {
2769b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        List<size_t>::iterator it = mSampleSizes.begin();
2770b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(*it);  // default sample size
2771b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
2772b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(0);
2773b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2774b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(mNumSamples);
2775b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!mSamplesHaveSameSize) {
2776b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        for (List<size_t>::iterator it = mSampleSizes.begin();
2777b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            it != mSampleSizes.end(); ++it) {
2778b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            mOwner->writeInt32(*it);
2779b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        }
2780b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2781b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsz
2782b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
278320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2784b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStscBox() {
2785b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsc");
2786b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
2787b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(mNumStscTableEntries);
2788b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    for (List<StscTableEntry>::iterator it = mStscTableEntries.begin();
2789b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        it != mStscTableEntries.end(); ++it) {
2790b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(it->firstChunk);
2791b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(it->samplesPerChunk);
2792b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(it->sampleDescriptionId);
2793b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2794b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsc
2795b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
279620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2797b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) {
2798b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox(use32BitOffset? "stco": "co64");
2799b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
2800b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(mNumStcoTableEntries);
2801b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    for (List<off64_t>::iterator it = mChunkOffsets.begin();
2802b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        it != mChunkOffsets.end(); ++it) {
2803b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        if (use32BitOffset) {
2804b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            mOwner->writeInt32(static_cast<int32_t>(*it));
2805b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        } else {
2806b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            mOwner->writeInt64((*it));
2807b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        }
2808b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2809b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stco or co64
281020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
281120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
281207b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeUdtaBox() {
281307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    beginBox("udta");
281407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeGeoDataBox();
281507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    endBox();
281607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
281707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
281807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/*
281907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard.
282007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */
282107b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeGeoDataBox() {
282207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    beginBox("\xA9xyz");
282307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    /*
282407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * For historical reasons, any user data start
282507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * with "\0xA9", must be followed by its assoicated
282607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * language code.
2827432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong     * 0x0012: text string length
2828432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong     * 0x15c7: lang (locale) code: en
282907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     */
283007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeInt32(0x001215c7);
283107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeLatitude(mLatitudex10000);
283207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeLongitude(mLongitudex10000);
283307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeInt8(0x2F);
283407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    endBox();
283507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
283607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
283720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
2838