MPEG4Writer.cpp revision 43089daaf82bd2b8e5f9a29b80af5abaae4657b3
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
2643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong#include <media/stagefright/foundation/ADebug.h>
2720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MPEG4Writer.h>
2820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBuffer.h>
2920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.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:
73000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    enum {
74000e18370baae60ffd9f25b509501dd8c26deabfJames Dong        kMaxCttsOffsetTimeUs = 1000000LL,  // 1 second
75000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    };
76000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
7720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Writer *mOwner;
7820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MetaData> mMeta;
79693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    sp<MediaSource> mSource;
8020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    volatile bool mDone;
81a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mPaused;
82a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mResumed;
83eaae38445a340c4857c1c5569475879a728e63b7James Dong    volatile bool mStarted;
841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAvc;
851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAudio;
861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsMPEG4;
87bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    int32_t mTrackId;
88c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    int64_t mTrackDurationUs;
8943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    int64_t mMaxChunkDurationUs;
90e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
91e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    bool mIsRealTimeRecording;
92e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    int64_t mMaxTimeStampUs;
93d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t mEstimatedTrackSizeBytes;
941f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    int64_t mMdatSizeBytes;
958f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int32_t mTimeScale;
9620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_t mThread;
9820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
99ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    // mNumSamples is used to track how many samples in mSampleSizes List.
100ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    // This is to reduce the cost associated with mSampleSizes.size() call,
101ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    // since it is O(n). Ideally, the fix should be in List class.
102ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    size_t              mNumSamples;
1038644c14618d30d9e57a69df40ed939986ebf02c4James Dong    List<size_t>        mSampleSizes;
104be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    bool                mSamplesHaveSameSize;
105be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
10613aec890216948b0c364f8f92792129d0335f506James Dong    List<MediaBuffer *> mChunkSamples;
1071f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1081f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    size_t              mNumStcoTableEntries;
109c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    List<off64_t>         mChunkOffsets;
11013aec890216948b0c364f8f92792129d0335f506James Dong
1111f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    size_t              mNumStscTableEntries;
11213aec890216948b0c364f8f92792129d0335f506James Dong    struct StscTableEntry {
11313aec890216948b0c364f8f92792129d0335f506James Dong
11413aec890216948b0c364f8f92792129d0335f506James Dong        StscTableEntry(uint32_t chunk, uint32_t samples, uint32_t id)
11513aec890216948b0c364f8f92792129d0335f506James Dong            : firstChunk(chunk),
11613aec890216948b0c364f8f92792129d0335f506James Dong              samplesPerChunk(samples),
11713aec890216948b0c364f8f92792129d0335f506James Dong              sampleDescriptionId(id) {}
11813aec890216948b0c364f8f92792129d0335f506James Dong
11913aec890216948b0c364f8f92792129d0335f506James Dong        uint32_t firstChunk;
12013aec890216948b0c364f8f92792129d0335f506James Dong        uint32_t samplesPerChunk;
12113aec890216948b0c364f8f92792129d0335f506James Dong        uint32_t sampleDescriptionId;
12213aec890216948b0c364f8f92792129d0335f506James Dong    };
12313aec890216948b0c364f8f92792129d0335f506James Dong    List<StscTableEntry> mStscTableEntries;
12420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1251f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    size_t        mNumStssTableEntries;
126050b28a593350047845a45a14cc5026221ac1620James Dong    List<int32_t> mStssTableEntries;
127050b28a593350047845a45a14cc5026221ac1620James Dong
128be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    struct SttsTableEntry {
129be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
13079761ab096f57c3027fad9556c2bc436672d614eJames Dong        SttsTableEntry(uint32_t count, uint32_t duration)
13179761ab096f57c3027fad9556c2bc436672d614eJames Dong            : sampleCount(count), sampleDuration(duration) {}
132be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
133be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        uint32_t sampleCount;
13479761ab096f57c3027fad9556c2bc436672d614eJames Dong        uint32_t sampleDuration;  // time scale based
135be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    };
136965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    size_t        mNumSttsTableEntries;
137be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    List<SttsTableEntry> mSttsTableEntries;
138be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
139965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    struct CttsTableEntry {
140965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        CttsTableEntry(uint32_t count, int32_t timescaledDur)
141965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            : sampleCount(count), sampleDuration(timescaledDur) {}
142965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
143965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        uint32_t sampleCount;
14443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        uint32_t sampleDuration;  // time scale based
145965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    };
146965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    size_t        mNumCttsTableEntries;
147965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    List<CttsTableEntry> mCttsTableEntries;
148000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t mMinCttsOffsetTimeUs;
149000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t mMaxCttsOffsetTimeUs;
150965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
1513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Sequence parameter set or picture parameter set
1523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    struct AVCParamSet {
1533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        AVCParamSet(uint16_t length, const uint8_t *data)
1543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            : mLength(length), mData(data) {}
1553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
1563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t mLength;
1573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *mData;
1583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    };
1593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    List<AVCParamSet> mSeqParamSets;
1603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    List<AVCParamSet> mPicParamSets;
1613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mProfileIdc;
1623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mProfileCompatible;
1633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mLevelIdc;
1643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
16520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *mCodecSpecificData;
16620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t mCodecSpecificDataSize;
167548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    bool mGotAllCodecSpecificData;
16893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    bool mTrackingProgressStatus;
16920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
17025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool mReachedEOS;
1713c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    int64_t mStartTimestampUs;
17270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int64_t mStartTimeRealUs;
17370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int64_t mFirstSampleTimeRealUs;
17493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mPreviousTrackTimeUs;
17593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mTrackEveryTimeDurationUs;
17625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
177872a481558350634a3fd5cb67939de288af00ecbJames Dong    // Update the audio track's drift information.
178872a481558350634a3fd5cb67939de288af00ecbJames Dong    void updateDriftTime(const sp<MetaData>& meta);
179872a481558350634a3fd5cb67939de288af00ecbJames Dong
180000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int32_t getStartTimeOffsetScaledTime() const;
181000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
18220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    static void *ThreadWrapper(void *me);
18337187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t threadEntry();
18420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *parseParamSet(
1863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen);
1873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
188b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t makeAVCCodecSpecificData(const uint8_t *data, size_t size);
189b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t copyAVCCodecSpecificData(const uint8_t *data, size_t size);
190b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t parseAVCCodecSpecificData(const uint8_t *data, size_t size);
191215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong
192215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    // Track authoring progress status
193faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    void trackProgressStatus(int64_t timeUs, status_t err = OK);
19493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    void initTrackingProgressStatus(MetaData *params);
19503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
19619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    void getCodecSpecificDataFromInputFormatIfPossible();
19719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
198c059860c73678a202bfa33062723e8f82fb779d9James Dong    // Determine the track time scale
199c059860c73678a202bfa33062723e8f82fb779d9James Dong    // If it is an audio track, try to use the sampling rate as
200c059860c73678a202bfa33062723e8f82fb779d9James Dong    // the time scale; however, if user chooses the overwrite
201c059860c73678a202bfa33062723e8f82fb779d9James Dong    // value, the user-supplied time scale will be used.
202c059860c73678a202bfa33062723e8f82fb779d9James Dong    void setTimeScale();
203c059860c73678a202bfa33062723e8f82fb779d9James Dong
204690f546b0ee548dbfe997df36418e5302ec2d786James Dong    // Simple validation on the codec specific data
205690f546b0ee548dbfe997df36418e5302ec2d786James Dong    status_t checkCodecSpecificData() const;
20613f6284305e4b27395a23db7882d670bdb1bcae1James Dong    int32_t mRotation;
207690f546b0ee548dbfe997df36418e5302ec2d786James Dong
2081f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void updateTrackSizeEstimate();
2091f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void addOneStscTableEntry(size_t chunkId, size_t sampleId);
2101f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void addOneStssTableEntry(size_t sampleId);
21179761ab096f57c3027fad9556c2bc436672d614eJames Dong
21279761ab096f57c3027fad9556c2bc436672d614eJames Dong    // Duration is time scale based
21379761ab096f57c3027fad9556c2bc436672d614eJames Dong    void addOneSttsTableEntry(size_t sampleCount, int32_t timescaledDur);
214965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    void addOneCttsTableEntry(size_t sampleCount, int32_t timescaledDur);
21545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
21645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    bool isTrackMalFormed() const;
21743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    void sendTrackSummary(bool hasMultipleTracks);
2181f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
219b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Write the boxes
220b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStcoBox(bool use32BitOffset);
221b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStscBox();
222b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStszBox();
223b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStssBox();
224b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeSttsBox();
225965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    void writeCttsBox();
226b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeD263Box();
227b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writePaspBox();
228b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeAvccBox();
229b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeUrlBox();
230b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDrefBox();
231b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDinfBox();
232b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDamrBox();
233b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeMdhdBox(time_t now);
234b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeSmhdBox();
235b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeVmhdBox();
236b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeHdlrBox();
237b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeTkhdBox(time_t now);
238b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeMp4aEsdsBox();
239b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeMp4vEsdsBox();
240b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeAudioFourCCBox();
241b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeVideoFourCCBox();
242b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStblBox(bool use32BitOffset);
243b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
24420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track(const Track &);
24520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track &operator=(const Track &);
24620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
24720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
24820111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::MPEG4Writer(const char *filename)
249674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    : mFd(-1),
250674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong      mInitCheck(NO_INIT),
251b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong      mUse4ByteNalLength(true),
2521acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong      mUse32BitOffset(true),
253a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong      mIsFileSizeLimitExplicitlyRequested(false),
254a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
255a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mStarted(false),
256411ba422e3635d534928ffd81abf54f4f291c739James Dong      mWriterThreadStarted(false),
25720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOffset(0),
25813aec890216948b0c364f8f92792129d0335f506James Dong      mMdatOffset(0),
2597837c17063a4c50bc856ba59418516fdab731de7James Dong      mEstimatedMoovBoxSize(0),
26007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mInterleaveDurationUs(1000000),
26107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mLatitudex10000(0),
26207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mLongitudex10000(0),
26386b7f47aa7482424cf8fd248f1315311919be3b0James Dong      mAreGeoTagsAvailable(false),
26486b7f47aa7482424cf8fd248f1315311919be3b0James Dong      mStartTimeOffsetMs(-1) {
265674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong
26603f6f4e7e2ce09357cbc05bb546cd8a6e54b5baeJames Dong    mFd = open(filename, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR);
267674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mFd >= 0) {
268674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        mInitCheck = OK;
269674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    }
27020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
27120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
27230ab66297501757d745b9ae10da61adcd891f497Andreas HuberMPEG4Writer::MPEG4Writer(int fd)
273674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    : mFd(dup(fd)),
274674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong      mInitCheck(mFd < 0? NO_INIT: OK),
275b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong      mUse4ByteNalLength(true),
2761acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong      mUse32BitOffset(true),
277a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong      mIsFileSizeLimitExplicitlyRequested(false),
278a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
279a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mStarted(false),
280411ba422e3635d534928ffd81abf54f4f291c739James Dong      mWriterThreadStarted(false),
28130ab66297501757d745b9ae10da61adcd891f497Andreas Huber      mOffset(0),
28213aec890216948b0c364f8f92792129d0335f506James Dong      mMdatOffset(0),
2837837c17063a4c50bc856ba59418516fdab731de7James Dong      mEstimatedMoovBoxSize(0),
28407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mInterleaveDurationUs(1000000),
28507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mLatitudex10000(0),
28607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mLongitudex10000(0),
28786b7f47aa7482424cf8fd248f1315311919be3b0James Dong      mAreGeoTagsAvailable(false),
28886b7f47aa7482424cf8fd248f1315311919be3b0James Dong      mStartTimeOffsetMs(-1) {
28930ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
29030ab66297501757d745b9ae10da61adcd891f497Andreas Huber
29120111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() {
2928bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dong    reset();
29320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2941f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    while (!mTracks.empty()) {
2951f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        List<Track *>::iterator it = mTracks.begin();
29620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        delete *it;
2971f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        (*it) = NULL;
2981f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mTracks.erase(it);
29920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
30020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.clear();
30120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
30220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
303dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::dump(
304dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        int fd, const Vector<String16>& args) {
305dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    const size_t SIZE = 256;
306dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    char buffer[SIZE];
307dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    String8 result;
308dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "   MPEG4Writer %p\n", this);
309dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
310dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "     mStarted: %s\n", mStarted? "true": "false");
311dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
312dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    ::write(fd, result.string(), result.size());
313dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    for (List<Track *>::iterator it = mTracks.begin();
314dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong         it != mTracks.end(); ++it) {
315dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        (*it)->dump(fd, args);
316dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    }
317dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    return OK;
318dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong}
319dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong
320dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::Track::dump(
321dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        int fd, const Vector<String16>& args) const {
322dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    const size_t SIZE = 256;
323dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    char buffer[SIZE];
324dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    String8 result;
325dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "     %s track\n", mIsAudio? "Audio": "Video");
326dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
327dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "       reached EOS: %s\n",
328dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong            mReachedEOS? "true": "false");
329dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
330dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    ::write(fd, result.string(), result.size());
331dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    return OK;
332dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong}
333dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong
3342dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huberstatus_t MPEG4Writer::addSource(const sp<MediaSource> &source) {
335bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    Mutex::Autolock l(mLock);
336bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    if (mStarted) {
33729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Attempt to add source AFTER recording is started");
338bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        return UNKNOWN_ERROR;
339bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    }
340bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    Track *track = new Track(this, source, mTracks.size());
34120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.push_back(track);
3422dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
3432dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    return OK;
34420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
34520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
34693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::startTracks(MetaData *params) {
347a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
348a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
34993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        status_t err = (*it)->start(params);
350a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
351a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (err != OK) {
352a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            for (List<Track *>::iterator it2 = mTracks.begin();
353a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                 it2 != it; ++it2) {
354a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                (*it2)->stop();
355a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            }
356a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
357a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            return err;
358a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
359a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
360a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    return OK;
361a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
362a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
3632dec2b5be2056c6d9428897dc672185872d30d17James Dongint64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) {
3642dec2b5be2056c6d9428897dc672185872d30d17James Dong    // This implementation is highly experimental/heurisitic.
3652dec2b5be2056c6d9428897dc672185872d30d17James Dong    //
3662dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Statistical analysis shows that metadata usually accounts
3672dec2b5be2056c6d9428897dc672185872d30d17James Dong    // for a small portion of the total file size, usually < 0.6%.
3682dec2b5be2056c6d9428897dc672185872d30d17James Dong
36978a1a286f736888ae7af8860b2c424af0d978848James Dong    // The default MIN_MOOV_BOX_SIZE is set to 0.6% x 1MB / 2,
3702dec2b5be2056c6d9428897dc672185872d30d17James Dong    // where 1MB is the common file size limit for MMS application.
37178a1a286f736888ae7af8860b2c424af0d978848James Dong    // The default MAX _MOOV_BOX_SIZE value is based on about 3
3722dec2b5be2056c6d9428897dc672185872d30d17James Dong    // minute video recording with a bit rate about 3 Mbps, because
3732dec2b5be2056c6d9428897dc672185872d30d17James Dong    // statistics also show that most of the video captured are going
3742dec2b5be2056c6d9428897dc672185872d30d17James Dong    // to be less than 3 minutes.
3752dec2b5be2056c6d9428897dc672185872d30d17James Dong
3762dec2b5be2056c6d9428897dc672185872d30d17James Dong    // If the estimation is wrong, we will pay the price of wasting
3772dec2b5be2056c6d9428897dc672185872d30d17James Dong    // some reserved space. This should not happen so often statistically.
3782dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int32_t factor = mUse32BitOffset? 1: 2;
37978a1a286f736888ae7af8860b2c424af0d978848James Dong    static const int64_t MIN_MOOV_BOX_SIZE = 3 * 1024;  // 3 KB
3802dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000);
3812dec2b5be2056c6d9428897dc672185872d30d17James Dong    int64_t size = MIN_MOOV_BOX_SIZE;
3822dec2b5be2056c6d9428897dc672185872d30d17James Dong
38378a1a286f736888ae7af8860b2c424af0d978848James Dong    // Max file size limit is set
384a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
38578a1a286f736888ae7af8860b2c424af0d978848James Dong        size = mMaxFileSizeLimitBytes * 6 / 1000;
38678a1a286f736888ae7af8860b2c424af0d978848James Dong    }
38778a1a286f736888ae7af8860b2c424af0d978848James Dong
38878a1a286f736888ae7af8860b2c424af0d978848James Dong    // Max file duration limit is set
38978a1a286f736888ae7af8860b2c424af0d978848James Dong    if (mMaxFileDurationLimitUs != 0) {
39078a1a286f736888ae7af8860b2c424af0d978848James Dong        if (bitRate > 0) {
39178a1a286f736888ae7af8860b2c424af0d978848James Dong            int64_t size2 =
39278a1a286f736888ae7af8860b2c424af0d978848James Dong                ((mMaxFileDurationLimitUs * bitRate * 6) / 1000 / 8000000);
39378a1a286f736888ae7af8860b2c424af0d978848James Dong            if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
39478a1a286f736888ae7af8860b2c424af0d978848James Dong                // When both file size and duration limits are set,
39578a1a286f736888ae7af8860b2c424af0d978848James Dong                // we use the smaller limit of the two.
39678a1a286f736888ae7af8860b2c424af0d978848James Dong                if (size > size2) {
39778a1a286f736888ae7af8860b2c424af0d978848James Dong                    size = size2;
39878a1a286f736888ae7af8860b2c424af0d978848James Dong                }
39978a1a286f736888ae7af8860b2c424af0d978848James Dong            } else {
40078a1a286f736888ae7af8860b2c424af0d978848James Dong                // Only max file duration limit is set
40178a1a286f736888ae7af8860b2c424af0d978848James Dong                size = size2;
40278a1a286f736888ae7af8860b2c424af0d978848James Dong            }
4032dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
4042dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
40578a1a286f736888ae7af8860b2c424af0d978848James Dong
4062dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size < MIN_MOOV_BOX_SIZE) {
4072dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MIN_MOOV_BOX_SIZE;
4082dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
4092dec2b5be2056c6d9428897dc672185872d30d17James Dong
4102dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Any long duration recording will be probably end up with
4112dec2b5be2056c6d9428897dc672185872d30d17James Dong    // non-streamable mp4 file.
4122dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size > MAX_MOOV_BOX_SIZE) {
4132dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MAX_MOOV_BOX_SIZE;
4142dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
4152dec2b5be2056c6d9428897dc672185872d30d17James Dong
416df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("limits: %lld/%lld bytes/us, bit rate: %d bps and the estimated"
4172dec2b5be2056c6d9428897dc672185872d30d17James Dong         " moov size %lld bytes",
4182dec2b5be2056c6d9428897dc672185872d30d17James Dong         mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size);
4192dec2b5be2056c6d9428897dc672185872d30d17James Dong    return factor * size;
4202dec2b5be2056c6d9428897dc672185872d30d17James Dong}
4212dec2b5be2056c6d9428897dc672185872d30d17James Dong
4222dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t MPEG4Writer::start(MetaData *param) {
423674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
42425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return UNKNOWN_ERROR;
42520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
42620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
427a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    /*
428a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * Check mMaxFileSizeLimitBytes at the beginning
429a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * since mMaxFileSizeLimitBytes may be implicitly
430a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * changed later for 32-bit file offset even if
431a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * user does not ask to set it explicitly.
432a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     */
433a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    if (mMaxFileSizeLimitBytes != 0) {
434a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong        mIsFileSizeLimitExplicitlyRequested = true;
435a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    }
436a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong
4372dec2b5be2056c6d9428897dc672185872d30d17James Dong    int32_t use64BitOffset;
4382dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (param &&
4392dec2b5be2056c6d9428897dc672185872d30d17James Dong        param->findInt32(kKey64BitFileOffset, &use64BitOffset) &&
4402dec2b5be2056c6d9428897dc672185872d30d17James Dong        use64BitOffset) {
4412dec2b5be2056c6d9428897dc672185872d30d17James Dong        mUse32BitOffset = false;
4422dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
4432dec2b5be2056c6d9428897dc672185872d30d17James Dong
4441f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    if (mUse32BitOffset) {
4451f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // Implicit 32 bit file size limit
4461f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        if (mMaxFileSizeLimitBytes == 0) {
4471f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            mMaxFileSizeLimitBytes = kMax32BitFileSize;
4481f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        }
4491f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
4501f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // If file size is set to be larger than the 32 bit file
4511f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // size limit, treat it as an error.
4521f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        if (mMaxFileSizeLimitBytes > kMax32BitFileSize) {
4535ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block            ALOGW("32-bit file size limit (%lld bytes) too big. "
454d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong                 "It is changed to %lld bytes",
455d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong                mMaxFileSizeLimitBytes, kMax32BitFileSize);
456d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong            mMaxFileSizeLimitBytes = kMax32BitFileSize;
4571f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        }
4581f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    }
4591f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
460b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    int32_t use2ByteNalLength;
461b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (param &&
462b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        param->findInt32(kKey2ByteNalLength, &use2ByteNalLength) &&
463b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        use2ByteNalLength) {
464b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mUse4ByteNalLength = false;
4652dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
4662dec2b5be2056c6d9428897dc672185872d30d17James Dong
467065d1aff96818df54456053f1574aec8a234d0deJames Dong    mStartTimestampUs = -1;
46893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
469a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (mStarted) {
470a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused) {
471a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mPaused = false;
47293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            return startTracks(param);
473a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
474a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
475a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
476a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
4778f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    if (!param ||
4788f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        !param->findInt32(kKeyTimeScale, &mTimeScale)) {
4798f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        mTimeScale = 1000;
4808f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    }
48143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mTimeScale, 0);
4823856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("movie time scale: %d", mTimeScale);
4838f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
4847837c17063a4c50bc856ba59418516fdab731de7James Dong    mStreamableFile = true;
4857837c17063a4c50bc856ba59418516fdab731de7James Dong    mWriteMoovBoxToMemory = false;
4867837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBuffer = NULL;
4877837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
4887837c17063a4c50bc856ba59418516fdab731de7James Dong
489b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeFtypBox(param);
49020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4917837c17063a4c50bc856ba59418516fdab731de7James Dong    mFreeBoxOffset = mOffset;
49220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4937837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mEstimatedMoovBoxSize == 0) {
4942dec2b5be2056c6d9428897dc672185872d30d17James Dong        int32_t bitRate = -1;
4952dec2b5be2056c6d9428897dc672185872d30d17James Dong        if (param) {
4962dec2b5be2056c6d9428897dc672185872d30d17James Dong            param->findInt32(kKeyBitRate, &bitRate);
4972dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
4982dec2b5be2056c6d9428897dc672185872d30d17James Dong        mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate);
4997837c17063a4c50bc856ba59418516fdab731de7James Dong    }
50043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GE(mEstimatedMoovBoxSize, 8);
501c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    lseek64(mFd, mFreeBoxOffset, SEEK_SET);
5027837c17063a4c50bc856ba59418516fdab731de7James Dong    writeInt32(mEstimatedMoovBoxSize);
5037837c17063a4c50bc856ba59418516fdab731de7James Dong    write("free", 4);
5047837c17063a4c50bc856ba59418516fdab731de7James Dong
5057837c17063a4c50bc856ba59418516fdab731de7James Dong    mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize;
5067837c17063a4c50bc856ba59418516fdab731de7James Dong    mOffset = mMdatOffset;
507c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    lseek64(mFd, mMdatOffset, SEEK_SET);
5081acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
5091acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("????mdat", 8);
5101acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
5111acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("\x00\x00\x00\x01mdat????????", 16);
5121acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
5131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
5141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    status_t err = startWriterThread();
5151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (err != OK) {
5161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        return err;
5171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
5181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
5191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    err = startTracks(param);
520a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (err != OK) {
521a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return err;
52220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
5231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
524a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mStarted = true;
52525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
52620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
52720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5281f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongbool MPEG4Writer::use32BitFileOffset() const {
5291f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    return mUse32BitOffset;
5301f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
5311f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
53237187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::pause() {
533674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
53437187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
535a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
536a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
53737187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = OK;
538a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
539a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
54037187916a486504acaf83bea30147eb5fbf46ae5James Dong        status_t status = (*it)->pause();
54137187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (status != OK) {
54237187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
54337187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
544a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
54537187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
546a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
547a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
5481c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::stopWriterThread() {
549b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("Stopping writer thread");
550411ba422e3635d534928ffd81abf54f4f291c739James Dong    if (!mWriterThreadStarted) {
551411ba422e3635d534928ffd81abf54f4f291c739James Dong        return;
552411ba422e3635d534928ffd81abf54f4f291c739James Dong    }
5531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
5541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    {
5551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        Mutex::Autolock autolock(mLock);
5561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
5571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mDone = true;
5581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkReadyCondition.signal();
5591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
5601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
5611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void *dummy;
5621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_join(mThread, &dummy);
563411ba422e3635d534928ffd81abf54f4f291c739James Dong    mWriterThreadStarted = false;
564b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("Writer thread stopped");
5651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
5661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
56713f6284305e4b27395a23db7882d670bdb1bcae1James Dong/*
56813f6284305e4b27395a23db7882d670bdb1bcae1James Dong * MP4 file standard defines a composition matrix:
56913f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | a  b  u |
57013f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | c  d  v |
57113f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | x  y  w |
57213f6284305e4b27395a23db7882d670bdb1bcae1James Dong *
57313f6284305e4b27395a23db7882d670bdb1bcae1James Dong * the element in the matrix is stored in the following
57413f6284305e4b27395a23db7882d670bdb1bcae1James Dong * order: {a, b, u, c, d, v, x, y, w},
57513f6284305e4b27395a23db7882d670bdb1bcae1James Dong * where a, b, c, d, x, and y is in 16.16 format, while
57613f6284305e4b27395a23db7882d670bdb1bcae1James Dong * u, v and w is in 2.30 format.
57713f6284305e4b27395a23db7882d670bdb1bcae1James Dong */
57813f6284305e4b27395a23db7882d670bdb1bcae1James Dongvoid MPEG4Writer::writeCompositionMatrix(int degrees) {
5793856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("writeCompositionMatrix");
58013f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t a = 0x00010000;
58113f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t b = 0;
58213f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t c = 0;
58313f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t d = 0x00010000;
58413f6284305e4b27395a23db7882d670bdb1bcae1James Dong    switch (degrees) {
58513f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 0:
58613f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
58713f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 90:
58813f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0;
58913f6284305e4b27395a23db7882d670bdb1bcae1James Dong            b = 0x00010000;
59013f6284305e4b27395a23db7882d670bdb1bcae1James Dong            c = 0xFFFF0000;
59113f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0;
59213f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
59313f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 180:
59413f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0xFFFF0000;
59513f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0xFFFF0000;
59613f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
59713f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 270:
59813f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0;
59913f6284305e4b27395a23db7882d670bdb1bcae1James Dong            b = 0xFFFF0000;
60013f6284305e4b27395a23db7882d670bdb1bcae1James Dong            c = 0x00010000;
60113f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0;
60213f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
60313f6284305e4b27395a23db7882d670bdb1bcae1James Dong        default:
60413f6284305e4b27395a23db7882d670bdb1bcae1James Dong            CHECK(!"Should never reach this unknown rotation");
60513f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
60613f6284305e4b27395a23db7882d670bdb1bcae1James Dong    }
60713f6284305e4b27395a23db7882d670bdb1bcae1James Dong
60813f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(a);           // a
60913f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(b);           // b
61013f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // u
61113f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(c);           // c
61213f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(d);           // d
61313f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // v
61413f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // x
61513f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // y
61613f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0x40000000);  // w
61713f6284305e4b27395a23db7882d670bdb1bcae1James Dong}
61813f6284305e4b27395a23db7882d670bdb1bcae1James Dong
619411ba422e3635d534928ffd81abf54f4f291c739James Dongvoid MPEG4Writer::release() {
620411ba422e3635d534928ffd81abf54f4f291c739James Dong    close(mFd);
621411ba422e3635d534928ffd81abf54f4f291c739James Dong    mFd = -1;
622411ba422e3635d534928ffd81abf54f4f291c739James Dong    mInitCheck = NO_INIT;
623411ba422e3635d534928ffd81abf54f4f291c739James Dong    mStarted = false;
624411ba422e3635d534928ffd81abf54f4f291c739James Dong}
62513f6284305e4b27395a23db7882d670bdb1bcae1James Dong
6268bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dongstatus_t MPEG4Writer::reset() {
627674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
62837187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
629411ba422e3635d534928ffd81abf54f4f291c739James Dong    } else {
630411ba422e3635d534928ffd81abf54f4f291c739James Dong        if (!mWriterThreadStarted ||
631411ba422e3635d534928ffd81abf54f4f291c739James Dong            !mStarted) {
632411ba422e3635d534928ffd81abf54f4f291c739James Dong            if (mWriterThreadStarted) {
633411ba422e3635d534928ffd81abf54f4f291c739James Dong                stopWriterThread();
634411ba422e3635d534928ffd81abf54f4f291c739James Dong            }
635411ba422e3635d534928ffd81abf54f4f291c739James Dong            release();
636411ba422e3635d534928ffd81abf54f4f291c739James Dong            return OK;
637411ba422e3635d534928ffd81abf54f4f291c739James Dong        }
63820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
63920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
64037187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = OK;
6418f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t maxDurationUs = 0;
64265b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    int64_t minDurationUs = 0x7fffffffffffffffLL;
64320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
64420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber         it != mTracks.end(); ++it) {
64537187916a486504acaf83bea30147eb5fbf46ae5James Dong        status_t status = (*it)->stop();
64637187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (err == OK && status != OK) {
64737187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
64837187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
64920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6508f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int64_t durationUs = (*it)->getDurationUs();
6518f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        if (durationUs > maxDurationUs) {
6528f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            maxDurationUs = durationUs;
65320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
65465b3d76025c71d755b0fb3b6ead90255f25417edJames Dong        if (durationUs < minDurationUs) {
65565b3d76025c71d755b0fb3b6ead90255f25417edJames Dong            minDurationUs = durationUs;
65665b3d76025c71d755b0fb3b6ead90255f25417edJames Dong        }
65765b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    }
65865b3d76025c71d755b0fb3b6ead90255f25417edJames Dong
65965b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    if (mTracks.size() > 1) {
660b8a805261bf0282e992d3608035e47d05a898710Steve Block        ALOGD("Duration from tracks range is [%lld, %lld] us",
66165b3d76025c71d755b0fb3b6ead90255f25417edJames Dong            minDurationUs, maxDurationUs);
66220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
66320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    stopWriterThread();
6657837c17063a4c50bc856ba59418516fdab731de7James Dong
66637187916a486504acaf83bea30147eb5fbf46ae5James Dong    // Do not write out movie header on error.
66737187916a486504acaf83bea30147eb5fbf46ae5James Dong    if (err != OK) {
668411ba422e3635d534928ffd81abf54f4f291c739James Dong        release();
66937187916a486504acaf83bea30147eb5fbf46ae5James Dong        return err;
67037187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
67137187916a486504acaf83bea30147eb5fbf46ae5James Dong
67220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // Fix up the size of the 'mdat' chunk.
6731acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
674c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mMdatOffset, SEEK_SET);
6751acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        int32_t size = htonl(static_cast<int32_t>(mOffset - mMdatOffset));
676c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &size, 4);
6771acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
678c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mMdatOffset + 8, SEEK_SET);
6791acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        int64_t size = mOffset - mMdatOffset;
6801acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        size = hton64(size);
681c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &size, 8);
6821acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
683c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    lseek64(mFd, mOffset, SEEK_SET);
68420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
685c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    const off64_t moovOffset = mOffset;
6867837c17063a4c50bc856ba59418516fdab731de7James Dong    mWriteMoovBoxToMemory = true;
6877837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize);
6887837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
6897837c17063a4c50bc856ba59418516fdab731de7James Dong    CHECK(mMoovBoxBuffer != NULL);
690b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeMoovBox(maxDurationUs);
69120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6927837c17063a4c50bc856ba59418516fdab731de7James Dong    mWriteMoovBoxToMemory = false;
6937837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mStreamableFile) {
69443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_LE(mMoovBoxBufferOffset + 8, mEstimatedMoovBoxSize);
6957837c17063a4c50bc856ba59418516fdab731de7James Dong
6967837c17063a4c50bc856ba59418516fdab731de7James Dong        // Moov box
697c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mFreeBoxOffset, SEEK_SET);
6987837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset = mFreeBoxOffset;
699674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset);
7007837c17063a4c50bc856ba59418516fdab731de7James Dong
7017837c17063a4c50bc856ba59418516fdab731de7James Dong        // Free box
702c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mOffset, SEEK_SET);
7037837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset);
7047837c17063a4c50bc856ba59418516fdab731de7James Dong        write("free", 4);
7057837c17063a4c50bc856ba59418516fdab731de7James Dong
7067837c17063a4c50bc856ba59418516fdab731de7James Dong        // Free temp memory
7077837c17063a4c50bc856ba59418516fdab731de7James Dong        free(mMoovBoxBuffer);
7087837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBuffer = NULL;
7097837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBufferOffset = 0;
7102dec2b5be2056c6d9428897dc672185872d30d17James Dong    } else {
711df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("The mp4 file will not be streamable.");
7127837c17063a4c50bc856ba59418516fdab731de7James Dong    }
7137837c17063a4c50bc856ba59418516fdab731de7James Dong
7140c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(mBoxes.empty());
71520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
716411ba422e3635d534928ffd81abf54f4f291c739James Dong    release();
71737187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
71820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
71920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
720b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::writeMvhdBox(int64_t durationUs) {
721b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    time_t now = time(NULL);
722b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("mvhd");
723b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // version=0, flags=0
724b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(now);           // creation time
725b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(now);           // modification time
726b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(mTimeScale);    // mvhd timescale
727b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t duration = (durationUs * mTimeScale + 5E5) / 1E6;
728b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(duration);
729b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0x10000);       // rate: 1.0
730b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt16(0x100);         // volume
731b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt16(0);             // reserved
732b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // reserved
733b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // reserved
734b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeCompositionMatrix(0); // matrix
735b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
736b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
737b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
738b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
739b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
740b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
741b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(mTracks.size() + 1);  // nextTrackID
742b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();  // mvhd
743b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
744b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
745b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::writeMoovBox(int64_t durationUs) {
746b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("moov");
747b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeMvhdBox(durationUs);
74807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (mAreGeoTagsAvailable) {
74907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        writeUdtaBox();
75007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
751b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t id = 1;
752b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    for (List<Track *>::iterator it = mTracks.begin();
753b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        it != mTracks.end(); ++it, ++id) {
754b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        (*it)->writeTrackHeader(mUse32BitOffset);
755b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
756b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();  // moov
757b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
758b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
7592cf9c5073ca3342ee52673ad68763fadd2c2be79James Dongvoid MPEG4Writer::writeFtypBox(MetaData *param) {
760b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("ftyp");
761b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
762b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t fileType;
763b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (param && param->findInt32(kKeyFileType, &fileType) &&
764b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        fileType != OUTPUT_FORMAT_MPEG_4) {
765b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeFourcc("3gp4");
766b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
767b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeFourcc("isom");
768b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
769b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
770b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);
771b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeFourcc("isom");
772b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeFourcc("3gp4");
773b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();
774b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
775b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
77607ec01904613a0bac32caaa8444b4690998faed7James Dongstatic bool isTestModeEnabled() {
77707ec01904613a0bac32caaa8444b4690998faed7James Dong#if (PROPERTY_VALUE_MAX < 5)
77807ec01904613a0bac32caaa8444b4690998faed7James Dong#error "PROPERTY_VALUE_MAX must be at least 5"
77907ec01904613a0bac32caaa8444b4690998faed7James Dong#endif
78007ec01904613a0bac32caaa8444b4690998faed7James Dong
78107ec01904613a0bac32caaa8444b4690998faed7James Dong    // Test mode is enabled only if rw.media.record.test system
78207ec01904613a0bac32caaa8444b4690998faed7James Dong    // property is enabled.
78307ec01904613a0bac32caaa8444b4690998faed7James Dong    char value[PROPERTY_VALUE_MAX];
78407ec01904613a0bac32caaa8444b4690998faed7James Dong    if (property_get("rw.media.record.test", value, NULL) &&
78507ec01904613a0bac32caaa8444b4690998faed7James Dong        (!strcasecmp(value, "true") || !strcasecmp(value, "1"))) {
78607ec01904613a0bac32caaa8444b4690998faed7James Dong        return true;
78707ec01904613a0bac32caaa8444b4690998faed7James Dong    }
78807ec01904613a0bac32caaa8444b4690998faed7James Dong    return false;
78907ec01904613a0bac32caaa8444b4690998faed7James Dong}
79007ec01904613a0bac32caaa8444b4690998faed7James Dong
79170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongvoid MPEG4Writer::sendSessionSummary() {
79207ec01904613a0bac32caaa8444b4690998faed7James Dong    // Send session summary only if test mode is enabled
79307ec01904613a0bac32caaa8444b4690998faed7James Dong    if (!isTestModeEnabled()) {
79407ec01904613a0bac32caaa8444b4690998faed7James Dong        return;
79507ec01904613a0bac32caaa8444b4690998faed7James Dong    }
79607ec01904613a0bac32caaa8444b4690998faed7James Dong
79770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
79870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong         it != mChunkInfos.end(); ++it) {
79970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        int trackNum = it->mTrack->getTrackId() << 28;
80070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
80170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                trackNum | MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS,
80270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                it->mMaxInterChunkDurUs);
80370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    }
80470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong}
80570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
80613aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) {
80713aec890216948b0c364f8f92792129d0335f506James Dong    mInterleaveDurationUs = durationUs;
80813aec890216948b0c364f8f92792129d0335f506James Dong    return OK;
80913aec890216948b0c364f8f92792129d0335f506James Dong}
81013aec890216948b0c364f8f92792129d0335f506James Dong
81113aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() {
81213aec890216948b0c364f8f92792129d0335f506James Dong    mLock.lock();
81313aec890216948b0c364f8f92792129d0335f506James Dong}
81413aec890216948b0c364f8f92792129d0335f506James Dong
81513aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() {
81613aec890216948b0c364f8f92792129d0335f506James Dong    mLock.unlock();
81713aec890216948b0c364f8f92792129d0335f506James Dong}
81820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
819c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addSample_l(MediaBuffer *buffer) {
820c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t old_offset = mOffset;
82120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
822c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    ::write(mFd,
823c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong          (const uint8_t *)buffer->data() + buffer->range_offset(),
824c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong          buffer->range_length());
82520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
82620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += buffer->range_length();
82720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
82820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return old_offset;
82920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
83020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
83103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) {
83203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (buffer->range_length() < 4) {
83303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return;
83403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
83503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
83603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    const uint8_t *ptr =
83703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        (const uint8_t *)buffer->data() + buffer->range_offset();
83803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
83903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) {
84003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        buffer->set_range(
84103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                buffer->range_offset() + 4, buffer->range_length() - 4);
84203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
84303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
84403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
845c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) {
846c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t old_offset = mOffset;
84730ab66297501757d745b9ae10da61adcd891f497Andreas Huber
84830ab66297501757d745b9ae10da61adcd891f497Andreas Huber    size_t length = buffer->range_length();
84903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
850b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (mUse4ByteNalLength) {
851b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        uint8_t x = length >> 24;
852c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
853b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = (length >> 16) & 0xff;
854c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
855b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = (length >> 8) & 0xff;
856c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
857b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = length & 0xff;
858c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
859c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong
860c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd,
861c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong              (const uint8_t *)buffer->data() + buffer->range_offset(),
862c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong              length);
863b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong
864b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mOffset += length + 4;
865b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    } else {
86643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_LT(length, 65536);
86730ab66297501757d745b9ae10da61adcd891f497Andreas Huber
868b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        uint8_t x = length >> 8;
869c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
870b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = length & 0xff;
871c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
872c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, (const uint8_t *)buffer->data() + buffer->range_offset(), length);
873b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mOffset += length + 2;
874b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    }
87530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
87630ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return old_offset;
87730ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
87830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
8797837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write(
880674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        const void *ptr, size_t size, size_t nmemb) {
8817837c17063a4c50bc856ba59418516fdab731de7James Dong
8827837c17063a4c50bc856ba59418516fdab731de7James Dong    const size_t bytes = size * nmemb;
8837837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
884674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        // This happens only when we write the moov box at the end of
885674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        // recording, not for each output video/audio frame we receive.
886c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes;
8871acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        if (moovBoxSize > mEstimatedMoovBoxSize) {
888c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            for (List<off64_t>::iterator it = mBoxes.begin();
8897837c17063a4c50bc856ba59418516fdab731de7James Dong                 it != mBoxes.end(); ++it) {
8907837c17063a4c50bc856ba59418516fdab731de7James Dong                (*it) += mOffset;
8917837c17063a4c50bc856ba59418516fdab731de7James Dong            }
892674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong            lseek64(mFd, mOffset, SEEK_SET);
893674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong            ::write(mFd, mMoovBoxBuffer, mMoovBoxBufferOffset);
894674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong            ::write(mFd, ptr, size * nmemb);
8957837c17063a4c50bc856ba59418516fdab731de7James Dong            mOffset += (bytes + mMoovBoxBufferOffset);
8967837c17063a4c50bc856ba59418516fdab731de7James Dong            free(mMoovBoxBuffer);
8977837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBuffer = NULL;
8987837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset = 0;
8997837c17063a4c50bc856ba59418516fdab731de7James Dong            mWriteMoovBoxToMemory = false;
9007837c17063a4c50bc856ba59418516fdab731de7James Dong            mStreamableFile = false;
9017837c17063a4c50bc856ba59418516fdab731de7James Dong        } else {
9027837c17063a4c50bc856ba59418516fdab731de7James Dong            memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes);
9037837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset += bytes;
9047837c17063a4c50bc856ba59418516fdab731de7James Dong        }
9057837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
906674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        ::write(mFd, ptr, size * nmemb);
9077837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset += bytes;
9087837c17063a4c50bc856ba59418516fdab731de7James Dong    }
9097837c17063a4c50bc856ba59418516fdab731de7James Dong    return bytes;
9107837c17063a4c50bc856ba59418516fdab731de7James Dong}
9117837c17063a4c50bc856ba59418516fdab731de7James Dong
91220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) {
9130c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(fourcc), 4);
91420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9157837c17063a4c50bc856ba59418516fdab731de7James Dong    mBoxes.push_back(mWriteMoovBoxToMemory?
9167837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset: mOffset);
91720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
91820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeInt32(0);
91920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeFourcc(fourcc);
92020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
92120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
92220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() {
9230c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(!mBoxes.empty());
92420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
925c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t offset = *--mBoxes.end();
92620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mBoxes.erase(--mBoxes.end());
92720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9287837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
9297837c17063a4c50bc856ba59418516fdab731de7James Dong       int32_t x = htonl(mMoovBoxBufferOffset - offset);
9307837c17063a4c50bc856ba59418516fdab731de7James Dong       memcpy(mMoovBoxBuffer + offset, &x, 4);
9317837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
932c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, offset, SEEK_SET);
9337837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mOffset - offset);
9347837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset -= 4;
935c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mOffset, SEEK_SET);
9367837c17063a4c50bc856ba59418516fdab731de7James Dong    }
93720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
93820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
93920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) {
940674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 1);
94120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
94220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
94320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) {
94420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htons(x);
945674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 2);
94620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
94720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
94820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) {
94920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htonl(x);
950674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 4);
95120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
95220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
95320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) {
95420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = hton64(x);
955674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 8);
95620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
95720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
95820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) {
95920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t n = strlen(s);
960674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(s, 1, n + 1);
96120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
96220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
96320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) {
9640c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(s), 4);
965674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(s, 1, 4);
96620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
96720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
96807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
96907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/-DD.DDDD format
97007b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLatitude(int degreex10000) {
97107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    bool isNegative = (degreex10000 < 0);
97207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char sign = isNegative? '-': '+';
97307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
97407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the whole part
97507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char str[9];
97607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int wholePart = degreex10000 / 10000;
97707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (wholePart == 0) {
97807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 5, "%c%.2d.", sign, wholePart);
97907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    } else {
98007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 5, "%+.2d.", wholePart);
98107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
98207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
98307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the fractional part
98407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int fractionalPart = degreex10000 - (wholePart * 10000);
98507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (fractionalPart < 0) {
98607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        fractionalPart = -fractionalPart;
98707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
98807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    snprintf(&str[4], 5, "%.4d", fractionalPart);
98907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
99007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Do not write the null terminator
99107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    write(str, 1, 8);
99207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
99307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
99407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/- DDD.DDDD format
99507b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLongitude(int degreex10000) {
99607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    bool isNegative = (degreex10000 < 0);
99707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char sign = isNegative? '-': '+';
99807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
99907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the whole part
100007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char str[10];
100107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int wholePart = degreex10000 / 10000;
100207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (wholePart == 0) {
100307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 6, "%c%.3d.", sign, wholePart);
100407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    } else {
100507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 6, "%+.3d.", wholePart);
100607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
100707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
100807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the fractional part
100907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int fractionalPart = degreex10000 - (wholePart * 10000);
101007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (fractionalPart < 0) {
101107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        fractionalPart = -fractionalPart;
101207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
101307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    snprintf(&str[5], 5, "%.4d", fractionalPart);
101407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
101507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Do not write the null terminator
101607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    write(str, 1, 9);
101707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
101807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
101907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/*
102007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard.
102107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * latitudex10000 is latitude in degrees times 10000, and
102207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * longitudex10000 is longitude in degrees times 10000.
102307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the latitude is in [-90, +90], and
102407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the longitude is in [-180, +180]
102507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */
102607b1bb529a1ae76c46a71b01338c166f9490629dJames Dongstatus_t MPEG4Writer::setGeoData(int latitudex10000, int longitudex10000) {
102707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Is latitude or longitude out of range?
102807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (latitudex10000 < -900000 || latitudex10000 > 900000 ||
102907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        longitudex10000 < -1800000 || longitudex10000 > 1800000) {
103007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        return BAD_VALUE;
103107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
103207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
103307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mLatitudex10000 = latitudex10000;
103407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mLongitudex10000 = longitudex10000;
103507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mAreGeoTagsAvailable = true;
103607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    return OK;
103707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
103807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
103920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) {
1040674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(data, 1, size);
104120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
104220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
104378a1a286f736888ae7af8860b2c424af0d978848James Dongbool MPEG4Writer::isFileStreamable() const {
104478a1a286f736888ae7af8860b2c424af0d978848James Dong    return mStreamableFile;
104578a1a286f736888ae7af8860b2c424af0d978848James Dong}
104678a1a286f736888ae7af8860b2c424af0d978848James Dong
1047d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() {
1048d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
1049d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileSizeLimitBytes == 0) {
1050d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
1051d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1052d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1053956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize);
1054d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
1055d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
1056d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes();
1057d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
10581f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1059acd234bba9f048971d66890009eeff9a8db94be3James Dong    // Be conservative in the estimate: do not exceed 95% of
1060acd234bba9f048971d66890009eeff9a8db94be3James Dong    // the target file limit. For small target file size limit, though,
1061acd234bba9f048971d66890009eeff9a8db94be3James Dong    // this will not help.
1062acd234bba9f048971d66890009eeff9a8db94be3James Dong    return (nTotalBytesEstimate >= (95 * mMaxFileSizeLimitBytes) / 100);
1063d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
1064d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1065d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() {
1066d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
1067d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileDurationLimitUs == 0) {
1068d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
1069d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1070d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1071d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
1072d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
1073d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) {
1074d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            return true;
1075d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
1076d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1077d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return false;
1078d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
1079d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
108025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() {
108125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool allDone = true;
108225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
108325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber         it != mTracks.end(); ++it) {
108425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        if (!(*it)->reachedEOS()) {
108525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            allDone = false;
108625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            break;
108725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        }
108825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
108925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
109025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return allDone;
109125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
109225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
1093f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) {
1094df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("setStartTimestampUs: %lld", timeUs);
109543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GE(timeUs, 0ll);
10963c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
1097065d1aff96818df54456053f1574aec8a234d0deJames Dong    if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) {
1098f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mStartTimestampUs = timeUs;
1099df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("Earliest track starting time: %lld", mStartTimestampUs);
11003c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    }
11013c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
11023c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
1103f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() {
11043c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
11053c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    return mStartTimestampUs;
11063c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
11073c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
110858ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() {
110958ae9c530247668f8af36e30d228c716c226b3d4James Dong    Mutex::Autolock autolock(mLock);
111058ae9c530247668f8af36e30d228c716c226b3d4James Dong    return mTracks.size();
111158ae9c530247668f8af36e30d228c716c226b3d4James Dong}
111258ae9c530247668f8af36e30d228c716c226b3d4James Dong
111320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
111420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
111520111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track(
1116bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId)
111720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mOwner(owner),
111825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mMeta(source->getFormat()),
111920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSource(source),
112020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDone(false),
1121a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
1122a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mResumed(false),
1123eaae38445a340c4857c1c5569475879a728e63b7James Dong      mStarted(false),
1124bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong      mTrackId(trackId),
1125c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong      mTrackDurationUs(0),
1126956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      mEstimatedTrackSizeBytes(0),
1127be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong      mSamplesHaveSameSize(true),
112820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCodecSpecificData(NULL),
112925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mCodecSpecificDataSize(0),
1130548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber      mGotAllCodecSpecificData(false),
113113f6284305e4b27395a23db7882d670bdb1bcae1James Dong      mReachedEOS(false),
113213f6284305e4b27395a23db7882d670bdb1bcae1James Dong      mRotation(0) {
113319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    getCodecSpecificDataFromInputFormatIfPossible();
11348f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
11351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    const char *mime;
11361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mMeta->findCString(kKeyMIMEType, &mime);
11371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
11381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAudio = !strncasecmp(mime, "audio/", 6);
11391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
11401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong               !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC);
11411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1142c059860c73678a202bfa33062723e8f82fb779d9James Dong    setTimeScale();
1143c059860c73678a202bfa33062723e8f82fb779d9James Dong}
1144c059860c73678a202bfa33062723e8f82fb779d9James Dong
11451f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::updateTrackSizeEstimate() {
11461f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
11471f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    int64_t stcoBoxSizeBytes = mOwner->use32BitFileOffset()
11481f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                                ? mNumStcoTableEntries * 4
11491f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                                : mNumStcoTableEntries * 8;
11501f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
11511f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mNumSamples * 4);
11521f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
115378a1a286f736888ae7af8860b2c424af0d978848James Dong    mEstimatedTrackSizeBytes = mMdatSizeBytes;  // media data size
115478a1a286f736888ae7af8860b2c424af0d978848James Dong    if (!mOwner->isFileStreamable()) {
115578a1a286f736888ae7af8860b2c424af0d978848James Dong        // Reserved free space is not large enough to hold
115678a1a286f736888ae7af8860b2c424af0d978848James Dong        // all meta data and thus wasted.
115778a1a286f736888ae7af8860b2c424af0d978848James Dong        mEstimatedTrackSizeBytes += mNumStscTableEntries * 12 +  // stsc box size
115878a1a286f736888ae7af8860b2c424af0d978848James Dong                                    mNumStssTableEntries * 4 +   // stss box size
115978a1a286f736888ae7af8860b2c424af0d978848James Dong                                    mNumSttsTableEntries * 8 +   // stts box size
1160965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong                                    mNumCttsTableEntries * 8 +   // ctts box size
116178a1a286f736888ae7af8860b2c424af0d978848James Dong                                    stcoBoxSizeBytes +           // stco box size
116278a1a286f736888ae7af8860b2c424af0d978848James Dong                                    stszBoxSizeBytes;            // stsz box size
116378a1a286f736888ae7af8860b2c424af0d978848James Dong    }
11641f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
11651f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
11661f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStscTableEntry(
11671f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        size_t chunkId, size_t sampleId) {
11681f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
11691f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        StscTableEntry stscEntry(chunkId, sampleId, 1);
11701f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mStscTableEntries.push_back(stscEntry);
11711f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        ++mNumStscTableEntries;
11721f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
11731f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
11741f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) {
11751f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mStssTableEntries.push_back(sampleId);
11761f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    ++mNumStssTableEntries;
11771f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
11781f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
11791f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneSttsTableEntry(
118079761ab096f57c3027fad9556c2bc436672d614eJames Dong        size_t sampleCount, int32_t duration) {
11811f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
11825a217fba010e801c255503602bda4b86ac5a6ac9James Dong    if (duration == 0) {
11835ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("0-duration samples found: %d", sampleCount);
11845a217fba010e801c255503602bda4b86ac5a6ac9James Dong    }
118579761ab096f57c3027fad9556c2bc436672d614eJames Dong    SttsTableEntry sttsEntry(sampleCount, duration);
11861f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mSttsTableEntries.push_back(sttsEntry);
11871f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    ++mNumSttsTableEntries;
11881f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
11891f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1190965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::addOneCttsTableEntry(
1191965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        size_t sampleCount, int32_t duration) {
1192965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
1193965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    if (mIsAudio) {
1194965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
1195965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
1196965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    CttsTableEntry cttsEntry(sampleCount, duration);
1197965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mCttsTableEntries.push_back(cttsEntry);
1198965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    ++mNumCttsTableEntries;
1199965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong}
1200965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
1201c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongvoid MPEG4Writer::Track::addChunkOffset(off64_t offset) {
12021f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    ++mNumStcoTableEntries;
12031f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mChunkOffsets.push_back(offset);
12041f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
12051f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1206c059860c73678a202bfa33062723e8f82fb779d9James Dongvoid MPEG4Writer::Track::setTimeScale() {
12073856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setTimeScale");
1208c059860c73678a202bfa33062723e8f82fb779d9James Dong    // Default time scale
1209c059860c73678a202bfa33062723e8f82fb779d9James Dong    mTimeScale = 90000;
1210c059860c73678a202bfa33062723e8f82fb779d9James Dong
1211c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mIsAudio) {
1212c059860c73678a202bfa33062723e8f82fb779d9James Dong        // Use the sampling rate as the default time scale for audio track.
1213c059860c73678a202bfa33062723e8f82fb779d9James Dong        int32_t sampleRate;
1214c059860c73678a202bfa33062723e8f82fb779d9James Dong        bool success = mMeta->findInt32(kKeySampleRate, &sampleRate);
1215c059860c73678a202bfa33062723e8f82fb779d9James Dong        CHECK(success);
1216c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = sampleRate;
1217c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
1218c059860c73678a202bfa33062723e8f82fb779d9James Dong
1219c059860c73678a202bfa33062723e8f82fb779d9James Dong    // If someone would like to overwrite the timescale, use user-supplied value.
1220c059860c73678a202bfa33062723e8f82fb779d9James Dong    int32_t timeScale;
1221c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mMeta->findInt32(kKeyTimeScale, &timeScale)) {
1222c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = timeScale;
1223c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
1224c059860c73678a202bfa33062723e8f82fb779d9James Dong
122543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mTimeScale, 0);
122619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber}
122719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
122819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Hubervoid MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() {
122919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    const char *mime;
123019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
123119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
123219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
123319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        uint32_t type;
123419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        const void *data;
123519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        size_t size;
123619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        if (mMeta->findData(kKeyAVCC, &type, &data, &size)) {
123719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mCodecSpecificData = malloc(size);
123819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mCodecSpecificDataSize = size;
123919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            memcpy(mCodecSpecificData, data, size);
124019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mGotAllCodecSpecificData = true;
124119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        }
124219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
124319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
124419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        uint32_t type;
124519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        const void *data;
124619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        size_t size;
124719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        if (mMeta->findData(kKeyESDS, &type, &data, &size)) {
124819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            ESDS esds(data, size);
124919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            if (esds.getCodecSpecificInfo(&data, &size) == OK) {
125019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mCodecSpecificData = malloc(size);
125119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mCodecSpecificDataSize = size;
125219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                memcpy(mCodecSpecificData, data, size);
125319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mGotAllCodecSpecificData = true;
125419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            }
125519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        }
125619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
125720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
125820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
125920111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() {
126020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    stop();
126120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
126220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mCodecSpecificData != NULL) {
126320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        free(mCodecSpecificData);
126420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mCodecSpecificData = NULL;
126520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
126620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
126720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
126893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) {
12693856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("initTrackingProgressStatus");
127093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mPreviousTrackTimeUs = -1;
127193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackingProgressStatus = false;
127293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackEveryTimeDurationUs = 0;
127393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    {
127493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        int64_t timeUs;
127593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) {
12763856b090cd04ba5dd4a59a12430ed724d5995909Steve Block            ALOGV("Receive request to track progress status for every %lld us", timeUs);
127793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackEveryTimeDurationUs = timeUs;
127893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackingProgressStatus = true;
127993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
128093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
128193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
128293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
12831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong// static
12841c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid *MPEG4Writer::ThreadWrapper(void *me) {
12853856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("ThreadWrapper: %p", me);
12861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    MPEG4Writer *writer = static_cast<MPEG4Writer *>(me);
12871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    writer->threadFunc();
12881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return NULL;
12891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
12901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
12911c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::bufferChunk(const Chunk& chunk) {
12923856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("bufferChunk: %p", chunk.mTrack);
12931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Mutex::Autolock autolock(mLock);
12941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    CHECK_EQ(mDone, false);
12951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
12961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
12971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
12981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
12991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (chunk.mTrack == it->mTrack) {  // Found owner
13001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            it->mChunks.push_back(chunk);
13011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.signal();
13021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            return;
13031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
13041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
13051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
130643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK(!"Received a chunk for a unknown track");
13071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
13081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1309fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeChunkToFile(Chunk* chunk) {
13103856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("writeChunkToFile: %lld from %s track",
13115410afcbb0af5d29d9f710a1c2978c500f9792dcPannag Sanketi        chunk->mTimeStampUs, chunk->mTrack->isAudio()? "audio": "video");
1312fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1313fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    int32_t isFirstSample = true;
1314fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    while (!chunk->mSamples.empty()) {
1315fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        List<MediaBuffer *>::iterator it = chunk->mSamples.begin();
1316fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1317fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        off64_t offset = chunk->mTrack->isAvc()
1318fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong                                ? addLengthPrefixedSample_l(*it)
1319fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong                                : addSample_l(*it);
1320fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1321fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        if (isFirstSample) {
1322fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            chunk->mTrack->addChunkOffset(offset);
1323fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            isFirstSample = false;
13241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
13251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
13261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it)->release();
13271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it) = NULL;
1328fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        chunk->mSamples.erase(it);
13291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1330fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    chunk->mSamples.clear();
13311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
13321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1333fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeAllChunks() {
13343856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("writeAllChunks");
13351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    size_t outstandingChunks = 0;
133670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    Chunk chunk;
133770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    while (findChunkToWrite(&chunk)) {
1338e9f6d0579603372fd2547e6c5ba6e114c6f8cba7James Dong        writeChunkToFile(&chunk);
133970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        ++outstandingChunks;
13401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
134170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
134270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    sendSessionSummary();
134370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
13441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mChunkInfos.clear();
1345b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("%d chunks are written in the last batch", outstandingChunks);
13461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
13471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1348fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongbool MPEG4Writer::findChunkToWrite(Chunk *chunk) {
13493856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("findChunkToWrite");
13501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
13511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL;
13521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Track *track = NULL;
13531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
13541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
13551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (!it->mChunks.empty()) {
13561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            List<Chunk>::iterator chunkIt = it->mChunks.begin();
13571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (chunkIt->mTimeStampUs < minTimestampUs) {
13581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                minTimestampUs = chunkIt->mTimeStampUs;
13591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                track = it->mTrack;
13601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            }
13611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
13621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
13631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
13641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (track == NULL) {
13653856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("Nothing to be written after all");
1366fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        return false;
13671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
13681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
13691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (mIsFirstChunk) {
13701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsFirstChunk = false;
13711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1372fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
13731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
13741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
13751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (it->mTrack == track) {
1376fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            *chunk = *(it->mChunks.begin());
1377fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            it->mChunks.erase(it->mChunks.begin());
1378fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            CHECK_EQ(chunk->mTrack, track);
137970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
138070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            int64_t interChunkTimeUs =
138170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                chunk->mTimeStampUs - it->mPrevChunkTimestampUs;
138270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            if (interChunkTimeUs > it->mPrevChunkTimestampUs) {
138370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                it->mMaxInterChunkDurUs = interChunkTimeUs;
138470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            }
138570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
1386fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            return true;
13871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
13881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1389fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1390fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    return false;
13911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
13921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
13931c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::threadFunc() {
13943856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("threadFunc");
13951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1396a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    prctl(PR_SET_NAME, (unsigned long)"MPEG4Writer", 0, 0, 0);
1397fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1398fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    Mutex::Autolock autoLock(mLock);
13991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    while (!mDone) {
1400fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        Chunk chunk;
1401fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        bool chunkFound = false;
1402fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1403fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        while (!mDone && !(chunkFound = findChunkToWrite(&chunk))) {
14041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.wait(mLock);
14051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
14061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1407fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        // Actual write without holding the lock in order to
1408fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        // reduce the blocking time for media track threads.
1409fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        if (chunkFound) {
1410fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            mLock.unlock();
1411fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            writeChunkToFile(&chunk);
1412fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            mLock.lock();
1413fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        }
14141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1415fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1416fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    writeAllChunks();
14171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
14181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
14191c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::startWriterThread() {
14203856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("startWriterThread");
14211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
14221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mDone = false;
14231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsFirstChunk = true;
1424e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    mDriftTimeUs = 0;
14251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<Track *>::iterator it = mTracks.begin();
14261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mTracks.end(); ++it) {
14271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        ChunkInfo info;
14281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        info.mTrack = *it;
142970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        info.mPrevChunkTimestampUs = 0;
143070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        info.mMaxInterChunkDurUs = 0;
14311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkInfos.push_back(info);
14321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
14331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
14341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_t attr;
14351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_init(&attr);
14361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
14371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_create(&mThread, &attr, ThreadWrapper, this);
14381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_destroy(&attr);
1439411ba422e3635d534928ffd81abf54f4f291c739James Dong    mWriterThreadStarted = true;
14401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return OK;
14411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
14421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
14431f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
144493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) {
1445a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (!mDone && mPaused) {
1446a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mPaused = false;
1447a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mResumed = true;
1448a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
1449a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
145025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
145193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t startTimeUs;
145219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) {
145319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        startTimeUs = 0;
145419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
145570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    mStartTimeRealUs = startTimeUs;
145619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
145713f6284305e4b27395a23db7882d670bdb1bcae1James Dong    int32_t rotationDegrees;
145813f6284305e4b27395a23db7882d670bdb1bcae1James Dong    if (!mIsAudio && params && params->findInt32(kKeyRotation, &rotationDegrees)) {
145913f6284305e4b27395a23db7882d670bdb1bcae1James Dong        mRotation = rotationDegrees;
146013f6284305e4b27395a23db7882d670bdb1bcae1James Dong    }
146113f6284305e4b27395a23db7882d670bdb1bcae1James Dong
14625b6a01e65aa4129a9226667536d1bc1dad5980d8James Dong    mIsRealTimeRecording = true;
1463e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    {
1464e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        int32_t isNotRealTime;
1465e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        if (params && params->findInt32(kKeyNotRealTime, &isNotRealTime)) {
1466e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            mIsRealTimeRecording = (isNotRealTime == 0);
1467e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        }
1468e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    }
1469e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
147093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    initTrackingProgressStatus(params);
147193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
1472f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    sp<MetaData> meta = new MetaData;
1473a472613aec322e25891abf5c77bf3f7e3c244920James Dong    if (mIsRealTimeRecording && mOwner->numTracks() > 1) {
1474a472613aec322e25891abf5c77bf3f7e3c244920James Dong        /*
1475a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * This extra delay of accepting incoming audio/video signals
1476a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * helps to align a/v start time at the beginning of a recording
1477a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * session, and it also helps eliminate the "recording" sound for
1478a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * camcorder applications.
1479a472613aec322e25891abf5c77bf3f7e3c244920James Dong         *
148086b7f47aa7482424cf8fd248f1315311919be3b0James Dong         * If client does not set the start time offset, we fall back to
148186b7f47aa7482424cf8fd248f1315311919be3b0James Dong         * use the default initial delay value.
1482a472613aec322e25891abf5c77bf3f7e3c244920James Dong         */
148386b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL;
148486b7f47aa7482424cf8fd248f1315311919be3b0James Dong        if (startTimeOffsetUs < 0) {  // Start time offset was not set
148586b7f47aa7482424cf8fd248f1315311919be3b0James Dong            startTimeOffsetUs = kInitialDelayTimeUs;
148686b7f47aa7482424cf8fd248f1315311919be3b0James Dong        }
148786b7f47aa7482424cf8fd248f1315311919be3b0James Dong        startTimeUs += startTimeOffsetUs;
1488df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("Start time offset: %lld us", startTimeOffsetUs);
1489a472613aec322e25891abf5c77bf3f7e3c244920James Dong    }
1490a472613aec322e25891abf5c77bf3f7e3c244920James Dong
1491f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    meta->setInt64(kKeyTime, startTimeUs);
1492a472613aec322e25891abf5c77bf3f7e3c244920James Dong
1493f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    status_t err = mSource->start(meta.get());
149425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    if (err != OK) {
149525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        mDone = mReachedEOS = true;
149625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return err;
149725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
149820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
149920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_t attr;
150020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_init(&attr);
150120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
150220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
150320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = false;
1504eaae38445a340c4857c1c5569475879a728e63b7James Dong    mStarted = true;
1505c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs = 0;
150625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = false;
1507956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    mEstimatedTrackSizeBytes = 0;
15081f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mNumStcoTableEntries = 0;
15091f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mNumStssTableEntries = 0;
15101f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mNumStscTableEntries = 0;
15111f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mNumSttsTableEntries = 0;
1512965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mNumCttsTableEntries = 0;
15131f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mMdatSizeBytes = 0;
1514f2ab12d0dcef27fd52dcae53221e9c51a369fef6James Dong
151543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mMaxChunkDurationUs = 0;
151620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
151725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    pthread_create(&mThread, &attr, ThreadWrapper, this);
151820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_destroy(&attr);
151925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
152025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
152120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
152220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
152337187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::pause() {
1524a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
152537187916a486504acaf83bea30147eb5fbf46ae5James Dong    return OK;
1526a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
1527a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
152837187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::stop() {
1529b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("Stopping %s track", mIsAudio? "Audio": "Video");
1530eaae38445a340c4857c1c5569475879a728e63b7James Dong    if (!mStarted) {
153129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Stop() called but track is not started");
1532eaae38445a340c4857c1c5569475879a728e63b7James Dong        return ERROR_END_OF_STREAM;
1533eaae38445a340c4857c1c5569475879a728e63b7James Dong    }
1534eaae38445a340c4857c1c5569475879a728e63b7James Dong
153520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mDone) {
153637187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
153720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
153820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = true;
153920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
154020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *dummy;
154120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_join(mThread, &dummy);
154220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
154337187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = (status_t) dummy;
154437187916a486504acaf83bea30147eb5fbf46ae5James Dong
1545b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("Stopping %s track source", mIsAudio? "Audio": "Video");
154637187916a486504acaf83bea30147eb5fbf46ae5James Dong    {
154737187916a486504acaf83bea30147eb5fbf46ae5James Dong        status_t status = mSource->stop();
154837187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (err == OK && status != OK && status != ERROR_END_OF_STREAM) {
154937187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
155037187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
155137187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
155237187916a486504acaf83bea30147eb5fbf46ae5James Dong
1553b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("%s track stopped", mIsAudio? "Audio": "Video");
155437187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
155520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
155620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
155725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() {
155825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return mReachedEOS;
155925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
156025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
156120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static
156220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) {
156320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = static_cast<Track *>(me);
156420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
156537187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = track->threadEntry();
156637187916a486504acaf83bea30147eb5fbf46ae5James Dong    return (void *) err;
156720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
156820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
15693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic void getNalUnitType(uint8_t byte, uint8_t* type) {
15703856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("getNalUnitType: %d", byte);
15713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
15723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // nal_unit_type: 5-bit unsigned integer
15733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *type = (byte & 0x1F);
15743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
15753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
15763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t *findNextStartCode(
15773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length) {
15783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
15793856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("findNextStartCode: %p %d", data, length);
15803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
15813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t bytesLeft = length;
15823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    while (bytesLeft > 4  &&
15833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            memcmp("\x00\x00\x00\x01", &data[length - bytesLeft], 4)) {
15843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        --bytesLeft;
15853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
15863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (bytesLeft <= 4) {
15873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        bytesLeft = 0; // Last parameter set
15883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
15893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return &data[length - bytesLeft];
15903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
15913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
15923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongconst uint8_t *MPEG4Writer::Track::parseParamSet(
15933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen) {
15943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
15953856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("parseParamSet");
15963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    CHECK(type == kNalUnitTypeSeqParamSet ||
15973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong          type == kNalUnitTypePicParamSet);
15983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
15993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *nextStartCode = findNextStartCode(data, length);
16003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *paramSetLen = nextStartCode - data;
16013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (*paramSetLen == 0) {
160229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Param set is malformed, since its length is 0");
16033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return NULL;
16043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
16053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
16063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    AVCParamSet paramSet(*paramSetLen, data);
16073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (type == kNalUnitTypeSeqParamSet) {
16083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (*paramSetLen < 4) {
160929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Seq parameter set malformed");
16103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return NULL;
16113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
16123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mSeqParamSets.empty()) {
16133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc = data[1];
16143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileCompatible = data[2];
16153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mLevelIdc = data[3];
16163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
16173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (mProfileIdc != data[1] ||
16183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mProfileCompatible != data[2] ||
16193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mLevelIdc != data[3]) {
162029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("Inconsistent profile/level found in seq parameter sets");
16213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return NULL;
16223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
16233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
16243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mSeqParamSets.push_back(paramSet);
16253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    } else {
16263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mPicParamSets.push_back(paramSet);
16273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
16283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return nextStartCode;
16293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
16303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
16313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::copyAVCCodecSpecificData(
16323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
16333856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("copyAVCCodecSpecificData");
16343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
16353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 2 bytes for each of the parameter set length field
16363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // plus the 7 bytes for the header
16373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (size < 4 + 7) {
163829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Codec specific data length too short: %d", size);
16393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return ERROR_MALFORMED;
16403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
16413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
16423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize = size;
16433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificData = malloc(size);
16443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    memcpy(mCodecSpecificData, data, size);
16453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
16463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
16473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
16483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::parseAVCCodecSpecificData(
16493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
16503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
16513856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("parseAVCCodecSpecificData");
16523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data starts with a start code.
16533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // SPS and PPS are separated with start codes.
16543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Also, SPS must come before PPS
16553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t type = kNalUnitTypeSeqParamSet;
16563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotSps = false;
16573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotPps = false;
16583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *tmp = data;
16593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *nextStartCode = data;
16603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t bytesLeft = size;
16613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t paramSetLen = 0;
16623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize = 0;
16633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) {
16643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        getNalUnitType(*(tmp + 4), &type);
16653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (type == kNalUnitTypeSeqParamSet) {
16663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (gotPps) {
166729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("SPS must come before PPS");
16683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
16693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
16703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
16713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotSps = true;
16723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
16733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
16743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else if (type == kNalUnitTypePicParamSet) {
16753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
167629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("SPS must come before PPS");
16773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
16783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
16793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotPps) {
16803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotPps = true;
16813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
16823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
16833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
168429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Only SPS and PPS Nal units are expected");
16853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
16863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
16873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
16883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nextStartCode == NULL) {
16893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
16903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
16913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
16923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Move on to find the next parameter set
16933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        bytesLeft -= nextStartCode - tmp;
16943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        tmp = nextStartCode;
16953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mCodecSpecificDataSize += (2 + paramSetLen);
16963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
16973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
16983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
16993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of seq parameter sets
17003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nSeqParamSets = mSeqParamSets.size();
17013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets == 0) {
170229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Cound not find sequence parameter set");
17033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
17043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
17053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
17063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets > 0x1F) {
170729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Too many seq parameter sets (%d) found", nSeqParamSets);
17083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
17093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
17103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
17113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
17123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
17133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of pic parameter sets
17143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nPicParamSets = mPicParamSets.size();
17153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets == 0) {
171629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Cound not find picture parameter set");
17173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
17183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
17193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets > 0xFF) {
172029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Too many pic parameter sets (%d) found", nPicParamSets);
17213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
17223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
17233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
17241374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// FIXME:
17251374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// Add chromat_format_idc, bit depth values, etc for AVC/h264 high profile and above
17261374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// and remove #if 0
17271374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#if 0
17283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
17293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the profiles
17303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // These profiles requires additional parameter set extensions
17313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mProfileIdc == 100 || mProfileIdc == 110 ||
17323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc == 122 || mProfileIdc == 144) {
173329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Sorry, no support for profile_idc: %d!", mProfileIdc);
17343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return BAD_VALUE;
17353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
17363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
17371374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#endif
17383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
17393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
1740548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
174103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData(
174203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        const uint8_t *data, size_t size) {
1743548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
174403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (mCodecSpecificData != NULL) {
174529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Already have codec specific data");
174603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
174703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
174803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
17493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (size < 4) {
175029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Codec specific data length too short: %d", size);
175103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
175203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
175303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
17543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data is in the form of AVCCodecSpecificData
17553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (memcmp("\x00\x00\x00\x01", data, 4)) {
17563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return copyAVCCodecSpecificData(data, size);
175703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
175803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
17593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (parseAVCCodecSpecificData(data, size) != OK) {
176003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
176103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
176203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
17633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // ISO 14496-15: AVC file format
17643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize += 7;  // 7 more bytes in the header
176503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    mCodecSpecificData = malloc(mCodecSpecificDataSize);
176603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    uint8_t *header = (uint8_t *)mCodecSpecificData;
17673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = 1;                     // version
17683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[1] = mProfileIdc;           // profile indication
17693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[2] = mProfileCompatible;    // profile compatibility
17703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[3] = mLevelIdc;
177103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
17723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne
1773b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (mOwner->useNalLengthFour()) {
1774b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        header[4] = 0xfc | 3;  // length size == 4 bytes
1775b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    } else {
1776b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        header[4] = 0xfc | 1;  // length size == 2 bytes
1777b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    }
177803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
17793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 3-bit '111' followed by 5-bit numSequenceParameterSets
17803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nSequenceParamSets = mSeqParamSets.size();
17813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[5] = 0xe0 | nSequenceParamSets;
17823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 6;
17833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mSeqParamSets.begin();
17843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mSeqParamSets.end(); ++it) {
17853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit sequence parameter set length
17863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t seqParamSetLength = it->mLength;
17873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = seqParamSetLength >> 8;
17883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = seqParamSetLength & 0xff;
17893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
17903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // SPS NAL unit (sequence parameter length bytes)
17913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, seqParamSetLength);
17923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + seqParamSetLength);
17933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
17943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
17953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 8-bit nPictureParameterSets
17963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nPictureParamSets = mPicParamSets.size();
17973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = nPictureParamSets;
17983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 1;
17993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mPicParamSets.begin();
18003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mPicParamSets.end(); ++it) {
18013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit picture parameter set length
18023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t picParamSetLength = it->mLength;
18033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = picParamSetLength >> 8;
18043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = picParamSetLength & 0xff;
18053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
18063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // PPS Nal unit (picture parameter set length bytes)
18073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, picParamSetLength);
18083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + picParamSetLength);
18093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
181003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
181103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    return OK;
181203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
181303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
1814872a481558350634a3fd5cb67939de288af00ecbJames Dong/*
1815872a481558350634a3fd5cb67939de288af00ecbJames Dong * Updates the drift time from the audio track so that
1816872a481558350634a3fd5cb67939de288af00ecbJames Dong * the video track can get the updated drift time information
1817872a481558350634a3fd5cb67939de288af00ecbJames Dong * from the file writer. The fluctuation of the drift time of the audio
1818872a481558350634a3fd5cb67939de288af00ecbJames Dong * encoding path is smoothed out with a simple filter by giving a larger
1819872a481558350634a3fd5cb67939de288af00ecbJames Dong * weight to more recently drift time. The filter coefficients, 0.5 and 0.5,
1820872a481558350634a3fd5cb67939de288af00ecbJames Dong * are heuristically determined.
1821872a481558350634a3fd5cb67939de288af00ecbJames Dong */
1822872a481558350634a3fd5cb67939de288af00ecbJames Dongvoid MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) {
1823872a481558350634a3fd5cb67939de288af00ecbJames Dong    int64_t driftTimeUs = 0;
1824872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) {
1825872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t prevDriftTimeUs = mOwner->getDriftTimeUs();
1826872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1;
1827872a481558350634a3fd5cb67939de288af00ecbJames Dong        mOwner->setDriftTimeUs(timeUs);
1828872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
1829872a481558350634a3fd5cb67939de288af00ecbJames Dong}
1830872a481558350634a3fd5cb67939de288af00ecbJames Dong
183137187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::threadEntry() {
183230ab66297501757d745b9ae10da61adcd891f497Andreas Huber    int32_t count = 0;
183313aec890216948b0c364f8f92792129d0335f506James Dong    const int64_t interleaveDurationUs = mOwner->interleaveDuration();
183443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    const bool hasMultipleTracks = (mOwner->numTracks() > 1);
183513aec890216948b0c364f8f92792129d0335f506James Dong    int64_t chunkTimestampUs = 0;
183613aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nChunks = 0;
183713aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nZeroLengthFrames = 0;
1838965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastTimestampUs = 0;      // Previous sample time stamp
1839965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastDurationUs = 0;       // Between the previous two samples
1840965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t currDurationTicks = 0;    // Timescale based ticks
1841965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastDurationTicks = 0;    // Timescale based ticks
1842965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int32_t sampleCount = 1;          // Sample count in the current stts table entry
1843000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    uint32_t previousSampleSize = 0;  // Size of the previous sample
1844a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    int64_t previousPausedDurationUs = 0;
1845965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t timestampUs = 0;
1846000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t cttsOffsetTimeUs = 0;
1847000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t currCttsOffsetTimeTicks = 0;   // Timescale based ticks
1848000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t lastCttsOffsetTimeTicks = -1;  // Timescale based ticks
184943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    int32_t cttsSampleCount = 0;           // Sample count in the current ctts table entry
1850e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
1851a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    if (mIsAudio) {
1852a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong        prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0);
1853a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    } else {
1854a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong        prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0);
1855a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    }
185686106f8b0641444c97a39e9788eeef55ab2a2ac6Glenn Kasten    androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
1857985f838934510983d8a887461e98dca60a6e858fJames Dong
1858d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong    sp<MetaData> meta_data;
185920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1860ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    mNumSamples = 0;
186193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t err = OK;
186220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBuffer *buffer;
186393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    while (!mDone && (err = mSource->read(&buffer)) == OK) {
186420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (buffer->range_length() == 0) {
186520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer->release();
186620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer = NULL;
186713aec890216948b0c364f8f92792129d0335f506James Dong            ++nZeroLengthFrames;
186820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            continue;
186920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
187020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1871a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // If the codec specific data has not been received yet, delay pause.
1872a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // After the codec specific data is received, discard what we received
1873a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // when the track is to be paused.
1874a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused && !mResumed) {
1875a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer->release();
1876a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer = NULL;
1877a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            continue;
1878a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
1879a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
188030ab66297501757d745b9ae10da61adcd891f497Andreas Huber        ++count;
188130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
188203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        int32_t isCodecConfig;
188303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig)
188403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                && isCodecConfig) {
1885548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            CHECK(!mGotAllCodecSpecificData);
1886548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
18871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (mIsAvc) {
188803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                status_t err = makeAVCCodecSpecificData(
188903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        (const uint8_t *)buffer->data()
189003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                            + buffer->range_offset(),
189103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        buffer->range_length());
189243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                CHECK_EQ((status_t)OK, err);
18931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            } else if (mIsMPEG4) {
189403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificDataSize = buffer->range_length();
189503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificData = malloc(mCodecSpecificDataSize);
189603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                memcpy(mCodecSpecificData,
189703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        (const uint8_t *)buffer->data()
189803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                            + buffer->range_offset(),
189903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                       buffer->range_length());
190030ab66297501757d745b9ae10da61adcd891f497Andreas Huber            }
190130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
190230ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer->release();
190330ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer = NULL;
190430ab66297501757d745b9ae10da61adcd891f497Andreas Huber
1905548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            mGotAllCodecSpecificData = true;
190630ab66297501757d745b9ae10da61adcd891f497Andreas Huber            continue;
1907a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
1908a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
1909d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // Make a deep copy of the MediaBuffer and Metadata and release
1910d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // the original as soon as we can
1911d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        MediaBuffer *copy = new MediaBuffer(buffer->range_length());
1912d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(),
1913d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong                buffer->range_length());
1914d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        copy->set_range(0, buffer->range_length());
1915d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data = new MetaData(*buffer->meta_data().get());
1916d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer->release();
1917d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer = NULL;
1918d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
19191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (mIsAvc) StripStartcode(copy);
1920e136c3bb38e88315bf8797a464ebf2c788296b22James Dong
1921b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        size_t sampleSize = copy->range_length();
1922b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        if (mIsAvc) {
1923b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            if (mOwner->useNalLengthFour()) {
1924b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                sampleSize += 4;
1925b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            } else {
1926b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                sampleSize += 2;
1927b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            }
1928b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        }
1929050b28a593350047845a45a14cc5026221ac1620James Dong
1930d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        // Max file size or duration handling
19311f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mMdatSizeBytes += sampleSize;
19321f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        updateTrackSizeEstimate();
19331f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1934d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileSizeLimit()) {
1935d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
1936d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
1937d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
1938d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileDurationLimit()) {
1939d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
1940d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
1941d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
1942d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1943050b28a593350047845a45a14cc5026221ac1620James Dong
1944d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        int32_t isSync = false;
1945d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data->findInt32(kKeyIsSyncFrame, &isSync);
1946d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        CHECK(meta_data->findInt64(kKeyTime, &timestampUs));
1947d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
1948d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong////////////////////////////////////////////////////////////////////////////////
194970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        if (mNumSamples == 0) {
195070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            mFirstSampleTimeRealUs = systemTime() / 1000;
1951f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mStartTimestampUs = timestampUs;
1952f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mOwner->setStartTimestampUs(mStartTimestampUs);
19538428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            previousPausedDurationUs = mStartTimestampUs;
19543c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        }
195548c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber
1956a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mResumed) {
19578428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs;
195843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            CHECK_GE(durExcludingEarlierPausesUs, 0ll);
19598428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs;
196043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            CHECK_GE(pausedDurationUs, lastDurationUs);
19618428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            previousPausedDurationUs += pausedDurationUs - lastDurationUs;
1962a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mResumed = false;
1963a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
1964a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
1965a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        timestampUs -= previousPausedDurationUs;
196643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_GE(timestampUs, 0ll);
1967000e18370baae60ffd9f25b509501dd8c26deabfJames Dong        if (!mIsAudio) {
1968965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            /*
1969965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             * Composition time: timestampUs
1970965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             * Decoding time: decodingTimeUs
1971000e18370baae60ffd9f25b509501dd8c26deabfJames Dong             * Composition time offset = composition time - decoding time
1972965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             */
1973965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            int64_t decodingTimeUs;
1974965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs));
1975965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            decodingTimeUs -= previousPausedDurationUs;
1976000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            cttsOffsetTimeUs =
1977000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs;
197843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            CHECK_GE(cttsOffsetTimeUs, 0ll);
1979965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            timestampUs = decodingTimeUs;
1980000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            ALOGV("decoding time: %lld and ctts offset time: %lld",
1981000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                timestampUs, cttsOffsetTimeUs);
1982000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
1983000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            // Update ctts box table if necessary
1984000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            currCttsOffsetTimeTicks =
1985000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    (cttsOffsetTimeUs * mTimeScale + 500000LL) / 1000000LL;
198643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            CHECK_LE(currCttsOffsetTimeTicks, 0x0FFFFFFFFLL);
198743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            if (mNumSamples == 0) {
198843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // Force the first ctts table entry to have one single entry
198943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // so that we can do adjustment for the initial track start
199043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // time offset easily in writeCttsBox().
199143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks;
199243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                addOneCttsTableEntry(1, currCttsOffsetTimeTicks);
199343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                cttsSampleCount = 0;      // No sample in ctts box is pending
199443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            } else {
199543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                if (currCttsOffsetTimeTicks != lastCttsOffsetTimeTicks) {
199643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
199743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks;
199843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    cttsSampleCount = 1;  // One sample in ctts box is pending
199943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                } else {
200043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    ++cttsSampleCount;
200143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                }
200243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            }
2003000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2004000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            // Update ctts time offset range
2005000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            if (mNumSamples == 0) {
2006000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2007000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2008000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            } else {
2009000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                if (currCttsOffsetTimeTicks > mMaxCttsOffsetTimeUs) {
2010000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2011000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                } else if (currCttsOffsetTimeTicks < mMinCttsOffsetTimeUs) {
2012000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2013000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                }
2014000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            }
2015000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2016965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        }
2017872a481558350634a3fd5cb67939de288af00ecbJames Dong
2018872a481558350634a3fd5cb67939de288af00ecbJames Dong        if (mIsRealTimeRecording) {
2019872a481558350634a3fd5cb67939de288af00ecbJames Dong            if (mIsAudio) {
2020872a481558350634a3fd5cb67939de288af00ecbJames Dong                updateDriftTime(meta_data);
2021e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            }
2022e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        }
2023872a481558350634a3fd5cb67939de288af00ecbJames Dong
202443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_GE(timestampUs, 0ll);
20253856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("%s media time stamp: %lld and previous paused duration %lld",
20268428af5381e835cc783b7ecb0d71cb60961c99c2James Dong                mIsAudio? "Audio": "Video", timestampUs, previousPausedDurationUs);
2027c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong        if (timestampUs > mTrackDurationUs) {
2028c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong            mTrackDurationUs = timestampUs;
20293b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber        }
20303b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber
20315a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // We need to use the time scale based ticks, rather than the
20325a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // timestamp itself to determine whether we have to use a new
20335a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // stts entry, since we may have rounding errors.
20345a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // The calculation is intended to reduce the accumulated
20355a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // rounding errors.
20365a217fba010e801c255503602bda4b86ac5a6ac9James Dong        currDurationTicks =
20375a217fba010e801c255503602bda4b86ac5a6ac9James Dong            ((timestampUs * mTimeScale + 500000LL) / 1000000LL -
20385a217fba010e801c255503602bda4b86ac5a6ac9James Dong                (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL);
203943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_GE(currDurationTicks, 0ll);
20405a217fba010e801c255503602bda4b86ac5a6ac9James Dong
20418644c14618d30d9e57a69df40ed939986ebf02c4James Dong        mSampleSizes.push_back(sampleSize);
2042ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong        ++mNumSamples;
2043ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong        if (mNumSamples > 2) {
2044c059860c73678a202bfa33062723e8f82fb779d9James Dong
2045a472613aec322e25891abf5c77bf3f7e3c244920James Dong            // Force the first sample to have its own stts entry so that
2046a472613aec322e25891abf5c77bf3f7e3c244920James Dong            // we can adjust its value later to maintain the A/V sync.
2047a472613aec322e25891abf5c77bf3f7e3c244920James Dong            if (mNumSamples == 3 || currDurationTicks != lastDurationTicks) {
204879761ab096f57c3027fad9556c2bc436672d614eJames Dong                addOneSttsTableEntry(sampleCount, lastDurationTicks);
2049be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                sampleCount = 1;
2050be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            } else {
2051be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                ++sampleCount;
2052be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
2053965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2054be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
2055be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        if (mSamplesHaveSameSize) {
2056ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong            if (mNumSamples >= 2 && previousSampleSize != sampleSize) {
2057be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mSamplesHaveSameSize = false;
2058be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
20598644c14618d30d9e57a69df40ed939986ebf02c4James Dong            previousSampleSize = sampleSize;
2060be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
20613856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("%s timestampUs/lastTimestampUs: %lld/%lld",
2062a472613aec322e25891abf5c77bf3f7e3c244920James Dong                mIsAudio? "Audio": "Video", timestampUs, lastTimestampUs);
20638644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastDurationUs = timestampUs - lastTimestampUs;
2064c059860c73678a202bfa33062723e8f82fb779d9James Dong        lastDurationTicks = currDurationTicks;
20658644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastTimestampUs = timestampUs;
206620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2067d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        if (isSync != 0) {
20681f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            addOneStssTableEntry(mNumSamples);
2069d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        }
2070d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
207193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (mTrackingProgressStatus) {
207293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            if (mPreviousTrackTimeUs <= 0) {
207393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong                mPreviousTrackTimeUs = mStartTimestampUs;
207493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            }
2075faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong            trackProgressStatus(timestampUs);
207693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
207743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong        if (!hasMultipleTracks) {
2078c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t offset = mIsAvc? mOwner->addLengthPrefixedSample_l(copy)
207958ae9c530247668f8af36e30d228c716c226b3d4James Dong                                 : mOwner->addSample_l(copy);
208058ae9c530247668f8af36e30d228c716c226b3d4James Dong            if (mChunkOffsets.empty()) {
20811f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                addChunkOffset(offset);
208258ae9c530247668f8af36e30d228c716c226b3d4James Dong            }
208358ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy->release();
208458ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy = NULL;
208558ae9c530247668f8af36e30d228c716c226b3d4James Dong            continue;
208658ae9c530247668f8af36e30d228c716c226b3d4James Dong        }
208713aec890216948b0c364f8f92792129d0335f506James Dong
208813aec890216948b0c364f8f92792129d0335f506James Dong        mChunkSamples.push_back(copy);
208913aec890216948b0c364f8f92792129d0335f506James Dong        if (interleaveDurationUs == 0) {
20901f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            addOneStscTableEntry(++nChunks, 1);
20911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            bufferChunk(timestampUs);
209213aec890216948b0c364f8f92792129d0335f506James Dong        } else {
209313aec890216948b0c364f8f92792129d0335f506James Dong            if (chunkTimestampUs == 0) {
209413aec890216948b0c364f8f92792129d0335f506James Dong                chunkTimestampUs = timestampUs;
209513aec890216948b0c364f8f92792129d0335f506James Dong            } else {
209643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                int64_t chunkDurationUs = timestampUs - chunkTimestampUs;
209743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                if (chunkDurationUs > interleaveDurationUs) {
209843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    if (chunkDurationUs > mMaxChunkDurationUs) {
209943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                        mMaxChunkDurationUs = chunkDurationUs;
210043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    }
210113aec890216948b0c364f8f92792129d0335f506James Dong                    ++nChunks;
210213aec890216948b0c364f8f92792129d0335f506James Dong                    if (nChunks == 1 ||  // First chunk
210313aec890216948b0c364f8f92792129d0335f506James Dong                        (--(mStscTableEntries.end()))->samplesPerChunk !=
210413aec890216948b0c364f8f92792129d0335f506James Dong                         mChunkSamples.size()) {
21051f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                        addOneStscTableEntry(nChunks, mChunkSamples.size());
210613aec890216948b0c364f8f92792129d0335f506James Dong                    }
21071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                    bufferChunk(timestampUs);
210813aec890216948b0c364f8f92792129d0335f506James Dong                    chunkTimestampUs = timestampUs;
210913aec890216948b0c364f8f92792129d0335f506James Dong                }
211013aec890216948b0c364f8f92792129d0335f506James Dong            }
211113aec890216948b0c364f8f92792129d0335f506James Dong        }
211213aec890216948b0c364f8f92792129d0335f506James Dong
211320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
211425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
211545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    if (isTrackMalFormed()) {
2116690f546b0ee548dbfe997df36418e5302ec2d786James Dong        err = ERROR_MALFORMED;
2117f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong    }
211845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
2119bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    mOwner->trackProgressStatus(mTrackId, -1, err);
2120be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
212113aec890216948b0c364f8f92792129d0335f506James Dong    // Last chunk
212243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    if (!hasMultipleTracks) {
21231f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        addOneStscTableEntry(1, mNumSamples);
212458ae9c530247668f8af36e30d228c716c226b3d4James Dong    } else if (!mChunkSamples.empty()) {
21251f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        addOneStscTableEntry(++nChunks, mChunkSamples.size());
21261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        bufferChunk(timestampUs);
212713aec890216948b0c364f8f92792129d0335f506James Dong    }
212813aec890216948b0c364f8f92792129d0335f506James Dong
2129be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // We don't really know how long the last frame lasts, since
2130be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // there is no frame time after it, just repeat the previous
2131be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // frame's duration.
2132ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    if (mNumSamples == 1) {
21338f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        lastDurationUs = 0;  // A single sample's duration
213479761ab096f57c3027fad9556c2bc436672d614eJames Dong        lastDurationTicks = 0;
2135be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    } else {
2136be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        ++sampleCount;  // Count for the last sample
2137be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    }
2138a472613aec322e25891abf5c77bf3f7e3c244920James Dong
2139a472613aec322e25891abf5c77bf3f7e3c244920James Dong    if (mNumSamples <= 2) {
214079761ab096f57c3027fad9556c2bc436672d614eJames Dong        addOneSttsTableEntry(1, lastDurationTicks);
2141a472613aec322e25891abf5c77bf3f7e3c244920James Dong        if (sampleCount - 1 > 0) {
214279761ab096f57c3027fad9556c2bc436672d614eJames Dong            addOneSttsTableEntry(sampleCount - 1, lastDurationTicks);
2143a472613aec322e25891abf5c77bf3f7e3c244920James Dong        }
2144a472613aec322e25891abf5c77bf3f7e3c244920James Dong    } else {
214579761ab096f57c3027fad9556c2bc436672d614eJames Dong        addOneSttsTableEntry(sampleCount, lastDurationTicks);
2146a472613aec322e25891abf5c77bf3f7e3c244920James Dong    }
2147a472613aec322e25891abf5c77bf3f7e3c244920James Dong
214843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    // The last ctts box may not have been written yet, and this
214943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    // is to make sure that we write out the last ctts box.
215043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    if (currCttsOffsetTimeTicks == lastCttsOffsetTimeTicks) {
215143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        if (cttsSampleCount > 0) {
215243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
215343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        }
215443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    }
215543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong
2156c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs += lastDurationUs;
215725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = true;
215843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
215943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    sendTrackSummary(hasMultipleTracks);
216043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
2161df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s",
21621f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            count, nZeroLengthFrames, mNumSamples, mIsAudio? "audio": "video");
2163872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (mIsAudio) {
2164df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("Audio track drift time: %lld us", mOwner->getDriftTimeUs());
2165872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
2166365a963142093a1cd8efdcea76b5f65096a5b115James Dong
216737187916a486504acaf83bea30147eb5fbf46ae5James Dong    if (err == ERROR_END_OF_STREAM) {
216837187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
216937187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
217037187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
2171365a963142093a1cd8efdcea76b5f65096a5b115James Dong}
2172365a963142093a1cd8efdcea76b5f65096a5b115James Dong
217345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dongbool MPEG4Writer::Track::isTrackMalFormed() const {
217445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    if (mSampleSizes.empty()) {                      // no samples written
217529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("The number of recorded samples is 0");
217645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
217745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
217845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
217945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    if (!mIsAudio && mNumStssTableEntries == 0) {  // no sync frames for video
218029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("There are no sync frames for video track");
218145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
218245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
218345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
218445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    if (OK != checkCodecSpecificData()) {         // no codec specific data
218545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
218645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
218745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
218845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    return false;
218945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong}
219045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
219143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dongvoid MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) {
219207ec01904613a0bac32caaa8444b4690998faed7James Dong
219307ec01904613a0bac32caaa8444b4690998faed7James Dong    // Send track summary only if test mode is enabled.
219407ec01904613a0bac32caaa8444b4690998faed7James Dong    if (!isTestModeEnabled()) {
219507ec01904613a0bac32caaa8444b4690998faed7James Dong        return;
219607ec01904613a0bac32caaa8444b4690998faed7James Dong    }
219707ec01904613a0bac32caaa8444b4690998faed7James Dong
219843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    int trackNum = (mTrackId << 28);
219943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
220043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
220143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_TYPE,
220243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mIsAudio? 0: 1);
220343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
220443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
220543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_DURATION_MS,
220643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mTrackDurationUs / 1000);
220743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
220843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
220943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES,
221043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mNumSamples);
221143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
221286b7f47aa7482424cf8fd248f1315311919be3b0James Dong    {
221386b7f47aa7482424cf8fd248f1315311919be3b0James Dong        // The system delay time excluding the requested initial delay that
221486b7f47aa7482424cf8fd248f1315311919be3b0James Dong        // is used to eliminate the recording sound.
221586b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL;
221686b7f47aa7482424cf8fd248f1315311919be3b0James Dong        if (startTimeOffsetUs < 0) {  // Start time offset was not set
221786b7f47aa7482424cf8fd248f1315311919be3b0James Dong            startTimeOffsetUs = kInitialDelayTimeUs;
221886b7f47aa7482424cf8fd248f1315311919be3b0James Dong        }
221986b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t initialDelayUs =
222086b7f47aa7482424cf8fd248f1315311919be3b0James Dong            mFirstSampleTimeRealUs - mStartTimeRealUs - startTimeOffsetUs;
222186b7f47aa7482424cf8fd248f1315311919be3b0James Dong
222286b7f47aa7482424cf8fd248f1315311919be3b0James Dong        mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
222370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS,
222470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    (initialDelayUs) / 1000);
222586b7f47aa7482424cf8fd248f1315311919be3b0James Dong    }
222670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
222707ec01904613a0bac32caaa8444b4690998faed7James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
222807ec01904613a0bac32caaa8444b4690998faed7James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES,
222907ec01904613a0bac32caaa8444b4690998faed7James Dong                    mMdatSizeBytes / 1024);
223007ec01904613a0bac32caaa8444b4690998faed7James Dong
223143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    if (hasMultipleTracks) {
223243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong        mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
223343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS,
223443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mMaxChunkDurationUs / 1000);
223570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
223670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
223770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        if (mStartTimestampUs != moovStartTimeUs) {
223870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            int64_t startTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
223970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
224070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS,
224170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    startTimeOffsetUs / 1000);
224270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        }
224343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    }
224443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong}
224543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
2246faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) {
22473856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("trackProgressStatus: %lld us", timeUs);
2248215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    if (mTrackEveryTimeDurationUs > 0 &&
2249215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) {
22503856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("Fire time tracking progress status at %lld us", timeUs);
2251bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err);
225293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        mPreviousTrackTimeUs = timeUs;
225393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
225493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
225593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
2256faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::trackProgressStatus(
2257bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        size_t trackId, int64_t timeUs, status_t err) {
2258faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    Mutex::Autolock lock(mLock);
2259bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    int32_t trackNum = (trackId << 28);
2260faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
2261faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Error notification
2262faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Do not consider ERROR_END_OF_STREAM an error
2263faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (err != OK && err != ERROR_END_OF_STREAM) {
2264bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_ERROR,
2265bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL,
2266faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
2267faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        return;
2268faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
2269faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
2270faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (timeUs == -1) {
2271faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send completion notification
2272bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
2273bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS,
2274faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
2275faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    } else {
2276faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send progress status
2277bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
2278bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME,
2279faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               timeUs / 1000);
2280faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
2281faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong}
2282faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
2283d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dongvoid MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) {
22843856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setDriftTimeUs: %lld us", driftTimeUs);
2285e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
2286d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong    mDriftTimeUs = driftTimeUs;
2287e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
2288e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
2289e259531ce59ab1f31de5a23124b22536f6a5a767James Dongint64_t MPEG4Writer::getDriftTimeUs() {
22903856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("getDriftTimeUs: %lld us", mDriftTimeUs);
2291e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
2292e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    return mDriftTimeUs;
2293e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
2294e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
2295b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dongbool MPEG4Writer::useNalLengthFour() {
2296b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    return mUse4ByteNalLength;
2297b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong}
2298b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong
22991c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::Track::bufferChunk(int64_t timestampUs) {
23003856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("bufferChunk");
23011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
23021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Chunk chunk(this, timestampUs, mChunkSamples);
23031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mOwner->bufferChunk(chunk);
230413aec890216948b0c364f8f92792129d0335f506James Dong    mChunkSamples.clear();
230520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
230620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
23073b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const {
2308c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    return mTrackDurationUs;
230920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
231020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2311d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const {
2312d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return mEstimatedTrackSizeBytes;
2313d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
2314d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
2315690f546b0ee548dbfe997df36418e5302ec2d786James Dongstatus_t MPEG4Writer::Track::checkCodecSpecificData() const {
2316690f546b0ee548dbfe997df36418e5302ec2d786James Dong    const char *mime;
2317690f546b0ee548dbfe997df36418e5302ec2d786James Dong    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
2318690f546b0ee548dbfe997df36418e5302ec2d786James Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) ||
2319690f546b0ee548dbfe997df36418e5302ec2d786James Dong        !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) ||
2320690f546b0ee548dbfe997df36418e5302ec2d786James Dong        !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
2321690f546b0ee548dbfe997df36418e5302ec2d786James Dong        if (!mCodecSpecificData ||
2322690f546b0ee548dbfe997df36418e5302ec2d786James Dong            mCodecSpecificDataSize <= 0) {
232329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Missing codec specific data");
2324690f546b0ee548dbfe997df36418e5302ec2d786James Dong            return ERROR_MALFORMED;
2325690f546b0ee548dbfe997df36418e5302ec2d786James Dong        }
2326690f546b0ee548dbfe997df36418e5302ec2d786James Dong    } else {
2327690f546b0ee548dbfe997df36418e5302ec2d786James Dong        if (mCodecSpecificData ||
2328690f546b0ee548dbfe997df36418e5302ec2d786James Dong            mCodecSpecificDataSize > 0) {
232929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Unexepected codec specific data found");
2330690f546b0ee548dbfe997df36418e5302ec2d786James Dong            return ERROR_MALFORMED;
2331690f546b0ee548dbfe997df36418e5302ec2d786James Dong        }
2332690f546b0ee548dbfe997df36418e5302ec2d786James Dong    }
2333690f546b0ee548dbfe997df36418e5302ec2d786James Dong    return OK;
2334690f546b0ee548dbfe997df36418e5302ec2d786James Dong}
2335690f546b0ee548dbfe997df36418e5302ec2d786James Dong
2336b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeTrackHeader(bool use32BitOffset) {
233720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
23383856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("%s track time scale: %d",
23391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsAudio? "Audio": "Video", mTimeScale);
23408f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
234120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    time_t now = time(NULL);
2342b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("trak");
2343b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeTkhdBox(now);
2344b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->beginBox("mdia");
2345b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            writeMdhdBox(now);
2346b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            writeHdlrBox();
2347b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            mOwner->beginBox("minf");
2348b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                if (mIsAudio) {
2349b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                    writeSmhdBox();
2350b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                } else {
2351b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                    writeVmhdBox();
2352b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                }
2353b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                writeDinfBox();
2354b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                writeStblBox(use32BitOffset);
2355b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            mOwner->endBox();  // minf
2356b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->endBox();  // mdia
2357b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // trak
2358b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2359b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2360b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStblBox(bool use32BitOffset) {
2361b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stbl");
2362b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsd");
2363b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);               // version=0, flags=0
2364b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);               // entry count
2365b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mIsAudio) {
2366b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeAudioFourCCBox();
2367b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
2368b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeVideoFourCCBox();
2369b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2370b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsd
2371b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeSttsBox();
2372965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    writeCttsBox();
2373b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!mIsAudio) {
2374b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeStssBox();
2375b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2376b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStszBox();
2377b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStscBox();
2378b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStcoBox(use32BitOffset);
2379b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stbl
2380b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2381b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2382b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVideoFourCCBox() {
2383b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    const char *mime;
2384b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    bool success = mMeta->findCString(kKeyMIMEType, &mime);
2385b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
2386b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
2387b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->beginBox("mp4v");
2388b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
2389b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->beginBox("s263");
2390b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
2391b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->beginBox("avc1");
2392b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
239329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Unknown mime type '%s'.", mime);
2394b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        CHECK(!"should not be here, unknown mime type.");
2395b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2396b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2397b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2398b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2399b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(1);           // data ref index
2400b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // predefined
2401b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2402b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
2403b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
2404b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
2405b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2406b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t width, height;
2407b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = mMeta->findInt32(kKeyWidth, &width);
2408b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = success && mMeta->findInt32(kKeyHeight, &height);
2409b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
2410b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2411b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(width);
2412b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(height);
2413b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x480000);    // horiz resolution
2414b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x480000);    // vert resolution
2415b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2416b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(1);           // frame count
2417b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write("                                ", 32);
2418b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x18);        // depth
2419b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(-1);          // predefined
2420b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
242143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_LT(23 + mCodecSpecificDataSize, 128);
2422b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2423b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
2424b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeMp4vEsdsBox();
2425b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
2426b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeD263Box();
2427b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
2428b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeAvccBox();
2429b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2430b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2431b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writePaspBox();
2432b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // mp4v, s263 or avc1
2433b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2434b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2435b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAudioFourCCBox() {
2436b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    const char *mime;
2437b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    bool success = mMeta->findCString(kKeyMIMEType, &mime);
2438b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
2439b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    const char *fourcc = NULL;
2440b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) {
2441b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        fourcc = "samr";
2442b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
2443b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        fourcc = "sawb";
2444b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
2445b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        fourcc = "mp4a";
2446b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
244729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Unknown mime type '%s'.", mime);
2448b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        CHECK(!"should not be here, unknown mime type.");
2449b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2450b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2451b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox(fourcc);        // audio format
2452b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2453b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2454b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x1);         // data ref index
2455b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2456b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2457b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t nChannels;
2458b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels));
2459b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(nChannels);   // channel count
2460b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(16);          // sample size
2461b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // predefined
2462b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2463b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2464b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t samplerate;
2465b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = mMeta->findInt32(kKeySampleRate, &samplerate);
2466b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
2467b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(samplerate << 16);
2468b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
2469b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeMp4aEsdsBox();
2470b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) ||
2471b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong               !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
2472b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeDamrBox();
2473b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2474b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2475b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2476b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2477b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4aEsdsBox() {
2478b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("esds");
2479b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
248043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mCodecSpecificDataSize, 0);
2481b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2482b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Make sure all sizes encode to a single byte.
248343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_LT(mCodecSpecificDataSize + 23, 128);
2484b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2485b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);     // version=0, flags=0
2486b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x03);   // ES_DescrTag
2487b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(23 + mCodecSpecificDataSize);
2488b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x0000);// ES_ID
2489b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x00);
2490b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2491b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x04);   // DecoderConfigDescrTag
2492b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(15 + mCodecSpecificDataSize);
2493b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x40);   // objectTypeIndication ISO/IEC 14492-2
2494b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x15);   // streamType AudioStream
2495b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2496b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x03);  // XXX
2497b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x00);   // buffer size 24-bit
2498b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(96000); // max bit rate
2499b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(96000); // avg bit rate
2500b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2501b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x05);   // DecoderSpecificInfoTag
2502b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(mCodecSpecificDataSize);
2503b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
2504b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2505b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData2[] = {
2506b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x06,  // SLConfigDescriptorTag
2507b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x01,
2508b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x02
2509b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
2510b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData2, sizeof(kData2));
2511b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2512b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // esds
2513b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2514b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2515b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4vEsdsBox() {
2516b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
251743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mCodecSpecificDataSize, 0);
2518b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("esds");
2519b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2520b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);    // version=0, flags=0
2521b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2522b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x03);  // ES_DescrTag
2523b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(23 + mCodecSpecificDataSize);
2524b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x0000);  // ES_ID
2525b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x1f);
2526b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2527b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x04);  // DecoderConfigDescrTag
2528b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(15 + mCodecSpecificDataSize);
2529b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x20);  // objectTypeIndication ISO/IEC 14492-2
2530b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x11);  // streamType VisualStream
2531b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2532b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData[] = {
2533b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x01, 0x77, 0x00,
2534b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x00, 0x03, 0xe8, 0x00,
2535b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x00, 0x03, 0xe8, 0x00
2536b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
2537b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData, sizeof(kData));
2538b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2539b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x05);  // DecoderSpecificInfoTag
2540b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2541b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(mCodecSpecificDataSize);
2542b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
2543b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2544b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData2[] = {
2545b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x06,  // SLConfigDescriptorTag
2546b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x01,
2547b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x02
2548b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
2549b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData2, sizeof(kData2));
2550b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2551b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // esds
2552b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2553b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2554b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeTkhdBox(time_t now) {
2555b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("tkhd");
2556b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Flags = 7 to indicate that the track is enabled, and
2557b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // part of the presentation
2558b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x07);          // version=0, flags=7
2559b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // creation time
2560b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // modification time
2561b5212db69734962f55e1493d3e696794172ced51James Dong    mOwner->writeInt32(mTrackId + 1);  // track id starts with 1
2562b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
25638f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t trakDurationUs = getDurationUs();
2564b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t mvhdTimeScale = mOwner->getTimeScale();
2565b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t tkhdDuration =
2566b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
2567b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(tkhdDuration);  // in mvhd timescale
2568b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
2569b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
2570b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // layer
2571b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // alternate group
2572b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(mIsAudio ? 0x100 : 0);  // volume
2573b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // reserved
2574b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2575b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCompositionMatrix(mRotation);       // matrix
257620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2577b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mIsAudio) {
2578b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(0);
2579b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(0);
2580b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
2581b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        int32_t width, height;
2582b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        bool success = mMeta->findInt32(kKeyWidth, &width);
2583b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        success = success && mMeta->findInt32(kKeyHeight, &height);
2584b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        CHECK(success);
2585b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2586b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(width << 16);   // 32-bit fixed-point value
2587b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(height << 16);  // 32-bit fixed-point value
2588b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2589b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // tkhd
2590b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2591b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2592b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVmhdBox() {
2593b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("vmhd");
2594b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x01);        // version=0, flags=1
2595b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // graphics mode
2596b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // opcolor
2597b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);
2598b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);
2599b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2600b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2601b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2602b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeSmhdBox() {
2603b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("smhd");
2604b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // version=0, flags=0
2605b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // balance
2606b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2607b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2608b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2609b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2610b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeHdlrBox() {
2611b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("hdlr");
2612b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // version=0, flags=0
2613b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // component type: should be mhlr
2614b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeFourcc(mIsAudio ? "soun" : "vide");  // component subtype
2615b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
2616b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
2617b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
2618b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Removing "r" for the name string just makes the string 4 byte aligned
2619b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle");  // name
2620b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2621b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2622b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2623b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMdhdBox(time_t now) {
2624b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int64_t trakDurationUs = getDurationUs();
2625b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("mdhd");
2626b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // version=0, flags=0
2627b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // creation time
2628b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // modification time
2629b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(mTimeScale);    // media timescale
2630b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6;
2631b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(mdhdDuration);  // use media timescale
2632b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Language follows the three letter standard ISO-639-2/T
2633b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // 'e', 'n', 'g' for "English", for instance.
2634b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Each character is packed as the difference between its ASCII value and 0x60.
2635b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // For "English", these are 00101, 01110, 00111.
2636b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // XXX: Where is the padding bit located: 0x15C7?
2637b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // language code
2638b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // predefined
2639b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2640b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2641b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2642b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDamrBox() {
2643b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // 3gpp2 Spec AMRSampleEntry fields
2644b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("damr");
2645b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCString("   ");  // vendor: 4 bytes
2646b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);         // decoder version
2647b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x83FF);   // mode set: all enabled
2648b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);         // mode change period
2649b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(1);         // frames per sample
2650b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2651b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2652b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2653b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeUrlBox() {
2654b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // The table index here refers to the sample description index
2655b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // in the sample table entries.
2656b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("url ");
2657b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);  // version=0, flags=1 (self-contained)
2658b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // url
2659b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2660b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2661b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDrefBox() {
2662b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("dref");
2663b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
2664b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);  // entry count (either url or urn)
2665b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeUrlBox();
2666b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // dref
2667b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2668b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2669b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDinfBox() {
2670b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("dinf");
2671b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeDrefBox();
2672b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // dinf
2673b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2674b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2675b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAvccBox() {
2676b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
267743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GE(mCodecSpecificDataSize, 5);
2678b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2679b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Patch avcc's lengthSize field to match the number
2680b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // of bytes we use to indicate the size of a nal unit.
2681b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    uint8_t *ptr = (uint8_t *)mCodecSpecificData;
2682b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    ptr[4] = (ptr[4] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1);
2683b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("avcC");
2684b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
2685b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // avcC
2686b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2687b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2688b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeD263Box() {
2689b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("d263");
2690b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // vendor
2691b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);   // decoder version
2692b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(10);  // level: 10
2693b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);   // profile: 0
2694b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // d263
2695b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2696b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2697b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong// This is useful if the pixel is not square
2698b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writePaspBox() {
2699b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("pasp");
2700b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1 << 16);  // hspacing
2701b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1 << 16);  // vspacing
2702b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // pasp
2703b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2704b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2705000e18370baae60ffd9f25b509501dd8c26deabfJames Dongint32_t MPEG4Writer::Track::getStartTimeOffsetScaledTime() const {
2706a472613aec322e25891abf5c77bf3f7e3c244920James Dong    int64_t trackStartTimeOffsetUs = 0;
2707b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
2708b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mStartTimestampUs != moovStartTimeUs) {
270943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_GT(mStartTimestampUs, moovStartTimeUs);
2710b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        trackStartTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
2711b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2712000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    return (trackStartTimeOffsetUs *  mTimeScale + 500000LL) / 1000000LL;
2713000e18370baae60ffd9f25b509501dd8c26deabfJames Dong}
2714000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2715000e18370baae60ffd9f25b509501dd8c26deabfJames Dongvoid MPEG4Writer::Track::writeSttsBox() {
2716000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->beginBox("stts");
2717000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
2718000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->writeInt32(mNumSttsTableEntries);
2719000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2720000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    // Compensate for small start time difference from different media tracks
272179761ab096f57c3027fad9556c2bc436672d614eJames Dong    List<SttsTableEntry>::iterator it = mSttsTableEntries.begin();
272279761ab096f57c3027fad9556c2bc436672d614eJames Dong    CHECK(it != mSttsTableEntries.end() && it->sampleCount == 1);
272379761ab096f57c3027fad9556c2bc436672d614eJames Dong    mOwner->writeInt32(it->sampleCount);
2724000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->writeInt32(getStartTimeOffsetScaledTime() + it->sampleDuration);
2725a472613aec322e25891abf5c77bf3f7e3c244920James Dong
2726965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t totalCount = 1;
272779761ab096f57c3027fad9556c2bc436672d614eJames Dong    while (++it != mSttsTableEntries.end()) {
272879761ab096f57c3027fad9556c2bc436672d614eJames Dong        mOwner->writeInt32(it->sampleCount);
272979761ab096f57c3027fad9556c2bc436672d614eJames Dong        mOwner->writeInt32(it->sampleDuration);
2730965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        totalCount += it->sampleCount;
2731b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
273243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_EQ(totalCount, mNumSamples);
2733b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stts
2734b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
273520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2736965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::writeCttsBox() {
2737965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    if (mIsAudio) {  // ctts is not for audio
2738965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
2739965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
2740965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2741000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    // There is no B frame at all
2742000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    if (mMinCttsOffsetTimeUs == mMaxCttsOffsetTimeUs) {
2743000e18370baae60ffd9f25b509501dd8c26deabfJames Dong        return;
2744000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    }
2745000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2746965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    // Do not write ctts box when there is no need to have it.
2747965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    if ((mNumCttsTableEntries == 1 &&
2748965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        mCttsTableEntries.begin()->sampleDuration == 0) ||
2749965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        mNumCttsTableEntries == 0) {
2750965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
2751965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
2752965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2753000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    ALOGD("ctts box has %d entries with range [%lld, %lld]",
2754000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            mNumCttsTableEntries, mMinCttsOffsetTimeUs, mMaxCttsOffsetTimeUs);
2755965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2756965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mOwner->beginBox("ctts");
2757000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    // Version 1 allows to use negative offset time value, but
2758000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    // we are sticking to version 0 for now.
2759000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
2760965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mOwner->writeInt32(mNumCttsTableEntries);
2761965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2762000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    // Compensate for small start time difference from different media tracks
2763000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    List<CttsTableEntry>::iterator it = mCttsTableEntries.begin();
2764000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    CHECK(it != mCttsTableEntries.end() && it->sampleCount == 1);
2765000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->writeInt32(it->sampleCount);
2766000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->writeInt32(getStartTimeOffsetScaledTime() +
2767000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            it->sampleDuration - mMinCttsOffsetTimeUs);
2768000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2769000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t totalCount = 1;
2770000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    while (++it != mCttsTableEntries.end()) {
2771965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        mOwner->writeInt32(it->sampleCount);
2772000e18370baae60ffd9f25b509501dd8c26deabfJames Dong        mOwner->writeInt32(it->sampleDuration - mMinCttsOffsetTimeUs);
2773965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        totalCount += it->sampleCount;
2774965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
277543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_EQ(totalCount, mNumSamples);
2776965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mOwner->endBox();  // ctts
2777965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong}
2778965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2779b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStssBox() {
2780b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stss");
2781b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
2782b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(mNumStssTableEntries);  // number of sync frames
2783b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    for (List<int32_t>::iterator it = mStssTableEntries.begin();
2784b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        it != mStssTableEntries.end(); ++it) {
2785b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(*it);
2786b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2787b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stss
2788b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
278925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
2790b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStszBox() {
2791b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsz");
2792b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
2793b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mSamplesHaveSameSize) {
2794b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        List<size_t>::iterator it = mSampleSizes.begin();
2795b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(*it);  // default sample size
2796b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
2797b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(0);
2798b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2799b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(mNumSamples);
2800b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!mSamplesHaveSameSize) {
2801b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        for (List<size_t>::iterator it = mSampleSizes.begin();
2802b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            it != mSampleSizes.end(); ++it) {
2803b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            mOwner->writeInt32(*it);
2804b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        }
2805b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2806b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsz
2807b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
280820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2809b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStscBox() {
2810b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsc");
2811b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
2812b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(mNumStscTableEntries);
2813b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    for (List<StscTableEntry>::iterator it = mStscTableEntries.begin();
2814b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        it != mStscTableEntries.end(); ++it) {
2815b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(it->firstChunk);
2816b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(it->samplesPerChunk);
2817b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(it->sampleDescriptionId);
2818b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2819b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsc
2820b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
282120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2822b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) {
2823b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox(use32BitOffset? "stco": "co64");
2824b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
2825b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(mNumStcoTableEntries);
2826b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    for (List<off64_t>::iterator it = mChunkOffsets.begin();
2827b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        it != mChunkOffsets.end(); ++it) {
2828b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        if (use32BitOffset) {
2829b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            mOwner->writeInt32(static_cast<int32_t>(*it));
2830b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        } else {
2831b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            mOwner->writeInt64((*it));
2832b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        }
2833b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2834b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stco or co64
283520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
283620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
283707b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeUdtaBox() {
283807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    beginBox("udta");
283907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeGeoDataBox();
284007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    endBox();
284107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
284207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
284307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/*
284407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard.
284507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */
284607b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeGeoDataBox() {
284707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    beginBox("\xA9xyz");
284807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    /*
284907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * For historical reasons, any user data start
285007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * with "\0xA9", must be followed by its assoicated
285107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * language code.
2852432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong     * 0x0012: text string length
2853432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong     * 0x15c7: lang (locale) code: en
285407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     */
285507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeInt32(0x001215c7);
285607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeLatitude(mLatitudex10000);
285707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeLongitude(mLongitudex10000);
285807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeInt8(0x2F);
285907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    endBox();
286007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
286107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
286220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
2863