MPEG4Writer.cpp revision 13210f3346462a86ce9fe3af72a0c200dba84e27
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
4577e8ae9967a078770416619e99ddb5b010def312James Dongstatic const int64_t kMinStreamableFileSizeInBytes = 5 * 1024 * 1024;
461f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongstatic const int64_t kMax32BitFileSize = 0x007fffffffLL;
473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypeSeqParamSet = 0x07;
483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypePicParamSet = 0x08;
4970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongstatic const int64_t kInitialDelayTimeUs     = 700000LL;
505b6a01e65aa4129a9226667536d1bc1dad5980d8James Dong
5120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Writer::Track {
5220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic:
53bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    Track(MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId);
548f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
5520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    ~Track();
5620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t start(MetaData *params);
5837187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t stop();
5937187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t pause();
6025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool reachedEOS();
6120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
623b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber    int64_t getDurationUs() const;
63d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t getEstimatedTrackSizeBytes() const;
64b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeTrackHeader(bool use32BitOffset = true);
651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void bufferChunk(int64_t timestampUs);
661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isAvc() const { return mIsAvc; }
671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isAudio() const { return mIsAudio; }
681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isMPEG4() const { return mIsMPEG4; }
69c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    void addChunkOffset(off64_t offset);
7070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int32_t getTrackId() const { return mTrackId; }
71dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    status_t dump(int fd, const Vector<String16>& args) const;
7220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate:
74000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    enum {
75000e18370baae60ffd9f25b509501dd8c26deabfJames Dong        kMaxCttsOffsetTimeUs = 1000000LL,  // 1 second
768c460498c028888c533ab442be12b6d4b669b965James Dong        kSampleArraySize = 1000,
77000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    };
78000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
7920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Writer *mOwner;
8020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MetaData> mMeta;
81693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    sp<MediaSource> mSource;
8220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    volatile bool mDone;
83a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mPaused;
84a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mResumed;
85eaae38445a340c4857c1c5569475879a728e63b7James Dong    volatile bool mStarted;
861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAvc;
871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAudio;
881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsMPEG4;
89bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    int32_t mTrackId;
90c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    int64_t mTrackDurationUs;
9143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    int64_t mMaxChunkDurationUs;
92e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
93e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    bool mIsRealTimeRecording;
94d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t mEstimatedTrackSizeBytes;
951f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    int64_t mMdatSizeBytes;
968f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int32_t mTimeScale;
9720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_t mThread;
9920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1008c460498c028888c533ab442be12b6d4b669b965James Dong    /*
1018c460498c028888c533ab442be12b6d4b669b965James Dong     * mNumSamples is used to track the total number of samples in
1028c460498c028888c533ab442be12b6d4b669b965James Dong     * mSampleSizes List.
1038c460498c028888c533ab442be12b6d4b669b965James Dong     *
1048c460498c028888c533ab442be12b6d4b669b965James Dong     * A linked list of fixed sized array is used here to reduce the time
1058c460498c028888c533ab442be12b6d4b669b965James Dong     * to write out stsz box.
1068c460498c028888c533ab442be12b6d4b669b965James Dong     */
1078c460498c028888c533ab442be12b6d4b669b965James Dong    uint32_t            mNumSamples;
1088c460498c028888c533ab442be12b6d4b669b965James Dong    uint32_t*           mCurrentSampleSizeArr;
1098c460498c028888c533ab442be12b6d4b669b965James Dong    List<uint32_t *>    mSampleSizes;
110be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    bool                mSamplesHaveSameSize;
111be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
11213aec890216948b0c364f8f92792129d0335f506James Dong    List<MediaBuffer *> mChunkSamples;
1131f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1141f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    size_t              mNumStcoTableEntries;
115c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    List<off64_t>         mChunkOffsets;
11613aec890216948b0c364f8f92792129d0335f506James Dong
1171f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    size_t              mNumStscTableEntries;
11813aec890216948b0c364f8f92792129d0335f506James Dong    struct StscTableEntry {
11913aec890216948b0c364f8f92792129d0335f506James Dong
12013aec890216948b0c364f8f92792129d0335f506James Dong        StscTableEntry(uint32_t chunk, uint32_t samples, uint32_t id)
12113aec890216948b0c364f8f92792129d0335f506James Dong            : firstChunk(chunk),
12213aec890216948b0c364f8f92792129d0335f506James Dong              samplesPerChunk(samples),
12313aec890216948b0c364f8f92792129d0335f506James Dong              sampleDescriptionId(id) {}
12413aec890216948b0c364f8f92792129d0335f506James Dong
12513aec890216948b0c364f8f92792129d0335f506James Dong        uint32_t firstChunk;
12613aec890216948b0c364f8f92792129d0335f506James Dong        uint32_t samplesPerChunk;
12713aec890216948b0c364f8f92792129d0335f506James Dong        uint32_t sampleDescriptionId;
12813aec890216948b0c364f8f92792129d0335f506James Dong    };
12913aec890216948b0c364f8f92792129d0335f506James Dong    List<StscTableEntry> mStscTableEntries;
13020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1311f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    size_t        mNumStssTableEntries;
132050b28a593350047845a45a14cc5026221ac1620James Dong    List<int32_t> mStssTableEntries;
133050b28a593350047845a45a14cc5026221ac1620James Dong
134be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    struct SttsTableEntry {
135be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
13679761ab096f57c3027fad9556c2bc436672d614eJames Dong        SttsTableEntry(uint32_t count, uint32_t duration)
13779761ab096f57c3027fad9556c2bc436672d614eJames Dong            : sampleCount(count), sampleDuration(duration) {}
138be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
139be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        uint32_t sampleCount;
14079761ab096f57c3027fad9556c2bc436672d614eJames Dong        uint32_t sampleDuration;  // time scale based
141be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    };
142965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    size_t        mNumSttsTableEntries;
143be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    List<SttsTableEntry> mSttsTableEntries;
144be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
145965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    struct CttsTableEntry {
146965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        CttsTableEntry(uint32_t count, int32_t timescaledDur)
147965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            : sampleCount(count), sampleDuration(timescaledDur) {}
148965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
149965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        uint32_t sampleCount;
15043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        uint32_t sampleDuration;  // time scale based
151965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    };
152965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    size_t        mNumCttsTableEntries;
153965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    List<CttsTableEntry> mCttsTableEntries;
154000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t mMinCttsOffsetTimeUs;
155000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t mMaxCttsOffsetTimeUs;
156965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
1573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Sequence parameter set or picture parameter set
1583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    struct AVCParamSet {
1593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        AVCParamSet(uint16_t length, const uint8_t *data)
1603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            : mLength(length), mData(data) {}
1613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
1623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t mLength;
1633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *mData;
1643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    };
1653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    List<AVCParamSet> mSeqParamSets;
1663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    List<AVCParamSet> mPicParamSets;
1673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mProfileIdc;
1683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mProfileCompatible;
1693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mLevelIdc;
1703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
17120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *mCodecSpecificData;
17220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t mCodecSpecificDataSize;
173548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    bool mGotAllCodecSpecificData;
17493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    bool mTrackingProgressStatus;
17520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
17625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool mReachedEOS;
1773c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    int64_t mStartTimestampUs;
17870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int64_t mStartTimeRealUs;
17970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int64_t mFirstSampleTimeRealUs;
18093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mPreviousTrackTimeUs;
18193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mTrackEveryTimeDurationUs;
18225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
183872a481558350634a3fd5cb67939de288af00ecbJames Dong    // Update the audio track's drift information.
184872a481558350634a3fd5cb67939de288af00ecbJames Dong    void updateDriftTime(const sp<MetaData>& meta);
185872a481558350634a3fd5cb67939de288af00ecbJames Dong
186000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int32_t getStartTimeOffsetScaledTime() const;
187000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
18820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    static void *ThreadWrapper(void *me);
18937187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t threadEntry();
19020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *parseParamSet(
1923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen);
1933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
194b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t makeAVCCodecSpecificData(const uint8_t *data, size_t size);
195b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t copyAVCCodecSpecificData(const uint8_t *data, size_t size);
196b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t parseAVCCodecSpecificData(const uint8_t *data, size_t size);
197215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong
198215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    // Track authoring progress status
199faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    void trackProgressStatus(int64_t timeUs, status_t err = OK);
20093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    void initTrackingProgressStatus(MetaData *params);
20103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
20219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    void getCodecSpecificDataFromInputFormatIfPossible();
20319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
204c059860c73678a202bfa33062723e8f82fb779d9James Dong    // Determine the track time scale
205c059860c73678a202bfa33062723e8f82fb779d9James Dong    // If it is an audio track, try to use the sampling rate as
206c059860c73678a202bfa33062723e8f82fb779d9James Dong    // the time scale; however, if user chooses the overwrite
207c059860c73678a202bfa33062723e8f82fb779d9James Dong    // value, the user-supplied time scale will be used.
208c059860c73678a202bfa33062723e8f82fb779d9James Dong    void setTimeScale();
209c059860c73678a202bfa33062723e8f82fb779d9James Dong
210690f546b0ee548dbfe997df36418e5302ec2d786James Dong    // Simple validation on the codec specific data
211690f546b0ee548dbfe997df36418e5302ec2d786James Dong    status_t checkCodecSpecificData() const;
21213f6284305e4b27395a23db7882d670bdb1bcae1James Dong    int32_t mRotation;
213690f546b0ee548dbfe997df36418e5302ec2d786James Dong
2141f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void updateTrackSizeEstimate();
2151f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void addOneStscTableEntry(size_t chunkId, size_t sampleId);
2161f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void addOneStssTableEntry(size_t sampleId);
21779761ab096f57c3027fad9556c2bc436672d614eJames Dong
21879761ab096f57c3027fad9556c2bc436672d614eJames Dong    // Duration is time scale based
21979761ab096f57c3027fad9556c2bc436672d614eJames Dong    void addOneSttsTableEntry(size_t sampleCount, int32_t timescaledDur);
220965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    void addOneCttsTableEntry(size_t sampleCount, int32_t timescaledDur);
22145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
22245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    bool isTrackMalFormed() const;
22343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    void sendTrackSummary(bool hasMultipleTracks);
2241f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
225b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Write the boxes
226b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStcoBox(bool use32BitOffset);
227b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStscBox();
228b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStszBox();
229b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStssBox();
230b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeSttsBox();
231965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    void writeCttsBox();
232b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeD263Box();
233b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writePaspBox();
234b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeAvccBox();
235b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeUrlBox();
236b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDrefBox();
237b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDinfBox();
238b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDamrBox();
239b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeMdhdBox(time_t now);
240b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeSmhdBox();
241b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeVmhdBox();
242b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeHdlrBox();
243b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeTkhdBox(time_t now);
244b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeMp4aEsdsBox();
245b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeMp4vEsdsBox();
246b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeAudioFourCCBox();
247b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeVideoFourCCBox();
248b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStblBox(bool use32BitOffset);
249b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
25020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track(const Track &);
25120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track &operator=(const Track &);
25220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
25320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
25420111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::MPEG4Writer(const char *filename)
255674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    : mFd(-1),
256674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong      mInitCheck(NO_INIT),
257b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong      mUse4ByteNalLength(true),
2581acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong      mUse32BitOffset(true),
259a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong      mIsFileSizeLimitExplicitlyRequested(false),
260a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
261a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mStarted(false),
262411ba422e3635d534928ffd81abf54f4f291c739James Dong      mWriterThreadStarted(false),
26320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOffset(0),
26413aec890216948b0c364f8f92792129d0335f506James Dong      mMdatOffset(0),
2657837c17063a4c50bc856ba59418516fdab731de7James Dong      mEstimatedMoovBoxSize(0),
26607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mInterleaveDurationUs(1000000),
26707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mLatitudex10000(0),
26807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mLongitudex10000(0),
26986b7f47aa7482424cf8fd248f1315311919be3b0James Dong      mAreGeoTagsAvailable(false),
27086b7f47aa7482424cf8fd248f1315311919be3b0James Dong      mStartTimeOffsetMs(-1) {
271674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong
272af8e8aa1ada2948972555592570ec9ad90cbf372Nick Kralevich    mFd = open(filename, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
273674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mFd >= 0) {
274674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        mInitCheck = OK;
275674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    }
27620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
27720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
27830ab66297501757d745b9ae10da61adcd891f497Andreas HuberMPEG4Writer::MPEG4Writer(int fd)
279674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    : mFd(dup(fd)),
280674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong      mInitCheck(mFd < 0? NO_INIT: OK),
281b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong      mUse4ByteNalLength(true),
2821acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong      mUse32BitOffset(true),
283a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong      mIsFileSizeLimitExplicitlyRequested(false),
284a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
285a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mStarted(false),
286411ba422e3635d534928ffd81abf54f4f291c739James Dong      mWriterThreadStarted(false),
28730ab66297501757d745b9ae10da61adcd891f497Andreas Huber      mOffset(0),
28813aec890216948b0c364f8f92792129d0335f506James Dong      mMdatOffset(0),
2897837c17063a4c50bc856ba59418516fdab731de7James Dong      mEstimatedMoovBoxSize(0),
29007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mInterleaveDurationUs(1000000),
29107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mLatitudex10000(0),
29207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mLongitudex10000(0),
29386b7f47aa7482424cf8fd248f1315311919be3b0James Dong      mAreGeoTagsAvailable(false),
29486b7f47aa7482424cf8fd248f1315311919be3b0James Dong      mStartTimeOffsetMs(-1) {
29530ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
29630ab66297501757d745b9ae10da61adcd891f497Andreas Huber
29720111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() {
2988bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dong    reset();
29920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3001f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    while (!mTracks.empty()) {
3011f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        List<Track *>::iterator it = mTracks.begin();
30220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        delete *it;
3031f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        (*it) = NULL;
3041f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mTracks.erase(it);
30520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
30620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.clear();
30720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
30820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
309dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::dump(
310dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        int fd, const Vector<String16>& args) {
311dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    const size_t SIZE = 256;
312dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    char buffer[SIZE];
313dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    String8 result;
314dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "   MPEG4Writer %p\n", this);
315dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
316dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "     mStarted: %s\n", mStarted? "true": "false");
317dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
318dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    ::write(fd, result.string(), result.size());
319dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    for (List<Track *>::iterator it = mTracks.begin();
320dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong         it != mTracks.end(); ++it) {
321dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        (*it)->dump(fd, args);
322dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    }
323dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    return OK;
324dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong}
325dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong
326dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::Track::dump(
327dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        int fd, const Vector<String16>& args) const {
328dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    const size_t SIZE = 256;
329dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    char buffer[SIZE];
330dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    String8 result;
331dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "     %s track\n", mIsAudio? "Audio": "Video");
332dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
333dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "       reached EOS: %s\n",
334dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong            mReachedEOS? "true": "false");
335dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
33613210f3346462a86ce9fe3af72a0c200dba84e27James Dong    snprintf(buffer, SIZE, "       frames encoded : %d\n", mNumSamples);
33713210f3346462a86ce9fe3af72a0c200dba84e27James Dong    result.append(buffer);
33813210f3346462a86ce9fe3af72a0c200dba84e27James Dong    snprintf(buffer, SIZE, "       duration encoded : %lld us\n", mTrackDurationUs);
33913210f3346462a86ce9fe3af72a0c200dba84e27James Dong    result.append(buffer);
340dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    ::write(fd, result.string(), result.size());
341dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    return OK;
342dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong}
343dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong
3442dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huberstatus_t MPEG4Writer::addSource(const sp<MediaSource> &source) {
345bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    Mutex::Autolock l(mLock);
346bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    if (mStarted) {
34729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Attempt to add source AFTER recording is started");
348bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        return UNKNOWN_ERROR;
349bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    }
350bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    Track *track = new Track(this, source, mTracks.size());
35120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.push_back(track);
3522dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
3532dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    return OK;
35420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
35520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
35693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::startTracks(MetaData *params) {
357a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
358a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
35993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        status_t err = (*it)->start(params);
360a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
361a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (err != OK) {
362a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            for (List<Track *>::iterator it2 = mTracks.begin();
363a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                 it2 != it; ++it2) {
364a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                (*it2)->stop();
365a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            }
366a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
367a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            return err;
368a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
369a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
370a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    return OK;
371a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
372a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
3732dec2b5be2056c6d9428897dc672185872d30d17James Dongint64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) {
3742dec2b5be2056c6d9428897dc672185872d30d17James Dong    // This implementation is highly experimental/heurisitic.
3752dec2b5be2056c6d9428897dc672185872d30d17James Dong    //
3762dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Statistical analysis shows that metadata usually accounts
3772dec2b5be2056c6d9428897dc672185872d30d17James Dong    // for a small portion of the total file size, usually < 0.6%.
3782dec2b5be2056c6d9428897dc672185872d30d17James Dong
37978a1a286f736888ae7af8860b2c424af0d978848James Dong    // The default MIN_MOOV_BOX_SIZE is set to 0.6% x 1MB / 2,
3802dec2b5be2056c6d9428897dc672185872d30d17James Dong    // where 1MB is the common file size limit for MMS application.
38178a1a286f736888ae7af8860b2c424af0d978848James Dong    // The default MAX _MOOV_BOX_SIZE value is based on about 3
3822dec2b5be2056c6d9428897dc672185872d30d17James Dong    // minute video recording with a bit rate about 3 Mbps, because
3832dec2b5be2056c6d9428897dc672185872d30d17James Dong    // statistics also show that most of the video captured are going
3842dec2b5be2056c6d9428897dc672185872d30d17James Dong    // to be less than 3 minutes.
3852dec2b5be2056c6d9428897dc672185872d30d17James Dong
3862dec2b5be2056c6d9428897dc672185872d30d17James Dong    // If the estimation is wrong, we will pay the price of wasting
3872dec2b5be2056c6d9428897dc672185872d30d17James Dong    // some reserved space. This should not happen so often statistically.
3882dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int32_t factor = mUse32BitOffset? 1: 2;
38978a1a286f736888ae7af8860b2c424af0d978848James Dong    static const int64_t MIN_MOOV_BOX_SIZE = 3 * 1024;  // 3 KB
3902dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000);
3912dec2b5be2056c6d9428897dc672185872d30d17James Dong    int64_t size = MIN_MOOV_BOX_SIZE;
3922dec2b5be2056c6d9428897dc672185872d30d17James Dong
39378a1a286f736888ae7af8860b2c424af0d978848James Dong    // Max file size limit is set
394a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
39578a1a286f736888ae7af8860b2c424af0d978848James Dong        size = mMaxFileSizeLimitBytes * 6 / 1000;
39678a1a286f736888ae7af8860b2c424af0d978848James Dong    }
39778a1a286f736888ae7af8860b2c424af0d978848James Dong
39878a1a286f736888ae7af8860b2c424af0d978848James Dong    // Max file duration limit is set
39978a1a286f736888ae7af8860b2c424af0d978848James Dong    if (mMaxFileDurationLimitUs != 0) {
40078a1a286f736888ae7af8860b2c424af0d978848James Dong        if (bitRate > 0) {
40178a1a286f736888ae7af8860b2c424af0d978848James Dong            int64_t size2 =
40278a1a286f736888ae7af8860b2c424af0d978848James Dong                ((mMaxFileDurationLimitUs * bitRate * 6) / 1000 / 8000000);
40378a1a286f736888ae7af8860b2c424af0d978848James Dong            if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
40478a1a286f736888ae7af8860b2c424af0d978848James Dong                // When both file size and duration limits are set,
40578a1a286f736888ae7af8860b2c424af0d978848James Dong                // we use the smaller limit of the two.
40678a1a286f736888ae7af8860b2c424af0d978848James Dong                if (size > size2) {
40778a1a286f736888ae7af8860b2c424af0d978848James Dong                    size = size2;
40878a1a286f736888ae7af8860b2c424af0d978848James Dong                }
40978a1a286f736888ae7af8860b2c424af0d978848James Dong            } else {
41078a1a286f736888ae7af8860b2c424af0d978848James Dong                // Only max file duration limit is set
41178a1a286f736888ae7af8860b2c424af0d978848James Dong                size = size2;
41278a1a286f736888ae7af8860b2c424af0d978848James Dong            }
4132dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
4142dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
41578a1a286f736888ae7af8860b2c424af0d978848James Dong
4162dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size < MIN_MOOV_BOX_SIZE) {
4172dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MIN_MOOV_BOX_SIZE;
4182dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
4192dec2b5be2056c6d9428897dc672185872d30d17James Dong
4202dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Any long duration recording will be probably end up with
4212dec2b5be2056c6d9428897dc672185872d30d17James Dong    // non-streamable mp4 file.
4222dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size > MAX_MOOV_BOX_SIZE) {
4232dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MAX_MOOV_BOX_SIZE;
4242dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
4252dec2b5be2056c6d9428897dc672185872d30d17James Dong
426df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("limits: %lld/%lld bytes/us, bit rate: %d bps and the estimated"
4272dec2b5be2056c6d9428897dc672185872d30d17James Dong         " moov size %lld bytes",
4282dec2b5be2056c6d9428897dc672185872d30d17James Dong         mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size);
4292dec2b5be2056c6d9428897dc672185872d30d17James Dong    return factor * size;
4302dec2b5be2056c6d9428897dc672185872d30d17James Dong}
4312dec2b5be2056c6d9428897dc672185872d30d17James Dong
4322dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t MPEG4Writer::start(MetaData *param) {
433674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
43425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return UNKNOWN_ERROR;
43520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
43620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
437a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    /*
438a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * Check mMaxFileSizeLimitBytes at the beginning
439a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * since mMaxFileSizeLimitBytes may be implicitly
440a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * changed later for 32-bit file offset even if
441a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * user does not ask to set it explicitly.
442a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     */
443a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    if (mMaxFileSizeLimitBytes != 0) {
444a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong        mIsFileSizeLimitExplicitlyRequested = true;
445a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    }
446a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong
4472dec2b5be2056c6d9428897dc672185872d30d17James Dong    int32_t use64BitOffset;
4482dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (param &&
4492dec2b5be2056c6d9428897dc672185872d30d17James Dong        param->findInt32(kKey64BitFileOffset, &use64BitOffset) &&
4502dec2b5be2056c6d9428897dc672185872d30d17James Dong        use64BitOffset) {
4512dec2b5be2056c6d9428897dc672185872d30d17James Dong        mUse32BitOffset = false;
4522dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
4532dec2b5be2056c6d9428897dc672185872d30d17James Dong
4541f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    if (mUse32BitOffset) {
4551f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // Implicit 32 bit file size limit
4561f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        if (mMaxFileSizeLimitBytes == 0) {
4571f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            mMaxFileSizeLimitBytes = kMax32BitFileSize;
4581f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        }
4591f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
4601f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // If file size is set to be larger than the 32 bit file
4611f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // size limit, treat it as an error.
4621f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        if (mMaxFileSizeLimitBytes > kMax32BitFileSize) {
4635ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block            ALOGW("32-bit file size limit (%lld bytes) too big. "
464d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong                 "It is changed to %lld bytes",
465d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong                mMaxFileSizeLimitBytes, kMax32BitFileSize);
466d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong            mMaxFileSizeLimitBytes = kMax32BitFileSize;
4671f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        }
4681f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    }
4691f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
470b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    int32_t use2ByteNalLength;
471b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (param &&
472b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        param->findInt32(kKey2ByteNalLength, &use2ByteNalLength) &&
473b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        use2ByteNalLength) {
474b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mUse4ByteNalLength = false;
4752dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
4762dec2b5be2056c6d9428897dc672185872d30d17James Dong
477065d1aff96818df54456053f1574aec8a234d0deJames Dong    mStartTimestampUs = -1;
47893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
479a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (mStarted) {
480a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused) {
481a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mPaused = false;
48293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            return startTracks(param);
483a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
484a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
485a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
486a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
4878f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    if (!param ||
4888f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        !param->findInt32(kKeyTimeScale, &mTimeScale)) {
4898f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        mTimeScale = 1000;
4908f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    }
49143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mTimeScale, 0);
4923856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("movie time scale: %d", mTimeScale);
4938f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
49477e8ae9967a078770416619e99ddb5b010def312James Dong    /*
49577e8ae9967a078770416619e99ddb5b010def312James Dong     * When the requested file size limit is small, the priority
49677e8ae9967a078770416619e99ddb5b010def312James Dong     * is to meet the file size limit requirement, rather than
49777e8ae9967a078770416619e99ddb5b010def312James Dong     * to make the file streamable.
49877e8ae9967a078770416619e99ddb5b010def312James Dong     */
49977e8ae9967a078770416619e99ddb5b010def312James Dong    mStreamableFile =
50077e8ae9967a078770416619e99ddb5b010def312James Dong        (mMaxFileSizeLimitBytes != 0 &&
50177e8ae9967a078770416619e99ddb5b010def312James Dong         mMaxFileSizeLimitBytes >= kMinStreamableFileSizeInBytes);
50277e8ae9967a078770416619e99ddb5b010def312James Dong
50377e8ae9967a078770416619e99ddb5b010def312James Dong    mWriteMoovBoxToMemory = mStreamableFile;
5047837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBuffer = NULL;
5057837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
5067837c17063a4c50bc856ba59418516fdab731de7James Dong
507b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeFtypBox(param);
50820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5097837c17063a4c50bc856ba59418516fdab731de7James Dong    mFreeBoxOffset = mOffset;
51020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5117837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mEstimatedMoovBoxSize == 0) {
5122dec2b5be2056c6d9428897dc672185872d30d17James Dong        int32_t bitRate = -1;
5132dec2b5be2056c6d9428897dc672185872d30d17James Dong        if (param) {
5142dec2b5be2056c6d9428897dc672185872d30d17James Dong            param->findInt32(kKeyBitRate, &bitRate);
5152dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
5162dec2b5be2056c6d9428897dc672185872d30d17James Dong        mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate);
5177837c17063a4c50bc856ba59418516fdab731de7James Dong    }
51843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GE(mEstimatedMoovBoxSize, 8);
51977e8ae9967a078770416619e99ddb5b010def312James Dong    if (mStreamableFile) {
52077e8ae9967a078770416619e99ddb5b010def312James Dong        // Reserve a 'free' box only for streamable file
52177e8ae9967a078770416619e99ddb5b010def312James Dong        lseek64(mFd, mFreeBoxOffset, SEEK_SET);
52277e8ae9967a078770416619e99ddb5b010def312James Dong        writeInt32(mEstimatedMoovBoxSize);
52377e8ae9967a078770416619e99ddb5b010def312James Dong        write("free", 4);
52477e8ae9967a078770416619e99ddb5b010def312James Dong        mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize;
52577e8ae9967a078770416619e99ddb5b010def312James Dong    } else {
52677e8ae9967a078770416619e99ddb5b010def312James Dong        mMdatOffset = mOffset;
52777e8ae9967a078770416619e99ddb5b010def312James Dong    }
5287837c17063a4c50bc856ba59418516fdab731de7James Dong
5297837c17063a4c50bc856ba59418516fdab731de7James Dong    mOffset = mMdatOffset;
530c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    lseek64(mFd, mMdatOffset, SEEK_SET);
5311acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
5321acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("????mdat", 8);
5331acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
5341acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("\x00\x00\x00\x01mdat????????", 16);
5351acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
5361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
5371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    status_t err = startWriterThread();
5381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (err != OK) {
5391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        return err;
5401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
5411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
5421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    err = startTracks(param);
543a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (err != OK) {
544a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return err;
54520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
5461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
547a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mStarted = true;
54825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
54920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
55020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5511f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongbool MPEG4Writer::use32BitFileOffset() const {
5521f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    return mUse32BitOffset;
5531f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
5541f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
55537187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::pause() {
556674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
55737187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
558a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
559a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
56037187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = OK;
561a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
562a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
56337187916a486504acaf83bea30147eb5fbf46ae5James Dong        status_t status = (*it)->pause();
56437187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (status != OK) {
56537187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
56637187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
567a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
56837187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
569a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
570a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
5711c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::stopWriterThread() {
572b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("Stopping writer thread");
573411ba422e3635d534928ffd81abf54f4f291c739James Dong    if (!mWriterThreadStarted) {
574411ba422e3635d534928ffd81abf54f4f291c739James Dong        return;
575411ba422e3635d534928ffd81abf54f4f291c739James Dong    }
5761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
5771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    {
5781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        Mutex::Autolock autolock(mLock);
5791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
5801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mDone = true;
5811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkReadyCondition.signal();
5821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
5831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
5841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void *dummy;
5851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_join(mThread, &dummy);
586411ba422e3635d534928ffd81abf54f4f291c739James Dong    mWriterThreadStarted = false;
587b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("Writer thread stopped");
5881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
5891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
59013f6284305e4b27395a23db7882d670bdb1bcae1James Dong/*
59113f6284305e4b27395a23db7882d670bdb1bcae1James Dong * MP4 file standard defines a composition matrix:
59213f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | a  b  u |
59313f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | c  d  v |
59413f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | x  y  w |
59513f6284305e4b27395a23db7882d670bdb1bcae1James Dong *
59613f6284305e4b27395a23db7882d670bdb1bcae1James Dong * the element in the matrix is stored in the following
59713f6284305e4b27395a23db7882d670bdb1bcae1James Dong * order: {a, b, u, c, d, v, x, y, w},
59813f6284305e4b27395a23db7882d670bdb1bcae1James Dong * where a, b, c, d, x, and y is in 16.16 format, while
59913f6284305e4b27395a23db7882d670bdb1bcae1James Dong * u, v and w is in 2.30 format.
60013f6284305e4b27395a23db7882d670bdb1bcae1James Dong */
60113f6284305e4b27395a23db7882d670bdb1bcae1James Dongvoid MPEG4Writer::writeCompositionMatrix(int degrees) {
6023856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("writeCompositionMatrix");
60313f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t a = 0x00010000;
60413f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t b = 0;
60513f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t c = 0;
60613f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t d = 0x00010000;
60713f6284305e4b27395a23db7882d670bdb1bcae1James Dong    switch (degrees) {
60813f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 0:
60913f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
61013f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 90:
61113f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0;
61213f6284305e4b27395a23db7882d670bdb1bcae1James Dong            b = 0x00010000;
61313f6284305e4b27395a23db7882d670bdb1bcae1James Dong            c = 0xFFFF0000;
61413f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0;
61513f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
61613f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 180:
61713f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0xFFFF0000;
61813f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0xFFFF0000;
61913f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
62013f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 270:
62113f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0;
62213f6284305e4b27395a23db7882d670bdb1bcae1James Dong            b = 0xFFFF0000;
62313f6284305e4b27395a23db7882d670bdb1bcae1James Dong            c = 0x00010000;
62413f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0;
62513f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
62613f6284305e4b27395a23db7882d670bdb1bcae1James Dong        default:
62713f6284305e4b27395a23db7882d670bdb1bcae1James Dong            CHECK(!"Should never reach this unknown rotation");
62813f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
62913f6284305e4b27395a23db7882d670bdb1bcae1James Dong    }
63013f6284305e4b27395a23db7882d670bdb1bcae1James Dong
63113f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(a);           // a
63213f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(b);           // b
63313f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // u
63413f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(c);           // c
63513f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(d);           // d
63613f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // v
63713f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // x
63813f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // y
63913f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0x40000000);  // w
64013f6284305e4b27395a23db7882d670bdb1bcae1James Dong}
64113f6284305e4b27395a23db7882d670bdb1bcae1James Dong
642411ba422e3635d534928ffd81abf54f4f291c739James Dongvoid MPEG4Writer::release() {
643411ba422e3635d534928ffd81abf54f4f291c739James Dong    close(mFd);
644411ba422e3635d534928ffd81abf54f4f291c739James Dong    mFd = -1;
645411ba422e3635d534928ffd81abf54f4f291c739James Dong    mInitCheck = NO_INIT;
646411ba422e3635d534928ffd81abf54f4f291c739James Dong    mStarted = false;
647411ba422e3635d534928ffd81abf54f4f291c739James Dong}
64813f6284305e4b27395a23db7882d670bdb1bcae1James Dong
6498bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dongstatus_t MPEG4Writer::reset() {
650674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
65137187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
652411ba422e3635d534928ffd81abf54f4f291c739James Dong    } else {
653411ba422e3635d534928ffd81abf54f4f291c739James Dong        if (!mWriterThreadStarted ||
654411ba422e3635d534928ffd81abf54f4f291c739James Dong            !mStarted) {
655411ba422e3635d534928ffd81abf54f4f291c739James Dong            if (mWriterThreadStarted) {
656411ba422e3635d534928ffd81abf54f4f291c739James Dong                stopWriterThread();
657411ba422e3635d534928ffd81abf54f4f291c739James Dong            }
658411ba422e3635d534928ffd81abf54f4f291c739James Dong            release();
659411ba422e3635d534928ffd81abf54f4f291c739James Dong            return OK;
660411ba422e3635d534928ffd81abf54f4f291c739James Dong        }
66120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
66220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
66337187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = OK;
6648f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t maxDurationUs = 0;
66565b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    int64_t minDurationUs = 0x7fffffffffffffffLL;
66620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
66720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber         it != mTracks.end(); ++it) {
66837187916a486504acaf83bea30147eb5fbf46ae5James Dong        status_t status = (*it)->stop();
66937187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (err == OK && status != OK) {
67037187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
67137187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
67220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6738f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int64_t durationUs = (*it)->getDurationUs();
6748f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        if (durationUs > maxDurationUs) {
6758f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            maxDurationUs = durationUs;
67620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
67765b3d76025c71d755b0fb3b6ead90255f25417edJames Dong        if (durationUs < minDurationUs) {
67865b3d76025c71d755b0fb3b6ead90255f25417edJames Dong            minDurationUs = durationUs;
67965b3d76025c71d755b0fb3b6ead90255f25417edJames Dong        }
68065b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    }
68165b3d76025c71d755b0fb3b6ead90255f25417edJames Dong
68265b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    if (mTracks.size() > 1) {
683b8a805261bf0282e992d3608035e47d05a898710Steve Block        ALOGD("Duration from tracks range is [%lld, %lld] us",
68465b3d76025c71d755b0fb3b6ead90255f25417edJames Dong            minDurationUs, maxDurationUs);
68520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
68620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    stopWriterThread();
6887837c17063a4c50bc856ba59418516fdab731de7James Dong
68937187916a486504acaf83bea30147eb5fbf46ae5James Dong    // Do not write out movie header on error.
69037187916a486504acaf83bea30147eb5fbf46ae5James Dong    if (err != OK) {
691411ba422e3635d534928ffd81abf54f4f291c739James Dong        release();
69237187916a486504acaf83bea30147eb5fbf46ae5James Dong        return err;
69337187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
69437187916a486504acaf83bea30147eb5fbf46ae5James Dong
69520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // Fix up the size of the 'mdat' chunk.
6961acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
697c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mMdatOffset, SEEK_SET);
6981acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        int32_t size = htonl(static_cast<int32_t>(mOffset - mMdatOffset));
699c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &size, 4);
7001acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
701c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mMdatOffset + 8, SEEK_SET);
7021acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        int64_t size = mOffset - mMdatOffset;
7031acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        size = hton64(size);
704c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &size, 8);
7051acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
706c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    lseek64(mFd, mOffset, SEEK_SET);
70720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
708c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    const off64_t moovOffset = mOffset;
70977e8ae9967a078770416619e99ddb5b010def312James Dong    mWriteMoovBoxToMemory = mStreamableFile;
7107837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize);
7117837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
7127837c17063a4c50bc856ba59418516fdab731de7James Dong    CHECK(mMoovBoxBuffer != NULL);
713b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeMoovBox(maxDurationUs);
71420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7157837c17063a4c50bc856ba59418516fdab731de7James Dong    mWriteMoovBoxToMemory = false;
7167837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mStreamableFile) {
71743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_LE(mMoovBoxBufferOffset + 8, mEstimatedMoovBoxSize);
7187837c17063a4c50bc856ba59418516fdab731de7James Dong
7197837c17063a4c50bc856ba59418516fdab731de7James Dong        // Moov box
720c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mFreeBoxOffset, SEEK_SET);
7217837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset = mFreeBoxOffset;
722674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset);
7237837c17063a4c50bc856ba59418516fdab731de7James Dong
7247837c17063a4c50bc856ba59418516fdab731de7James Dong        // Free box
725c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mOffset, SEEK_SET);
7267837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset);
7277837c17063a4c50bc856ba59418516fdab731de7James Dong        write("free", 4);
7287837c17063a4c50bc856ba59418516fdab731de7James Dong
7297837c17063a4c50bc856ba59418516fdab731de7James Dong        // Free temp memory
7307837c17063a4c50bc856ba59418516fdab731de7James Dong        free(mMoovBoxBuffer);
7317837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBuffer = NULL;
7327837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBufferOffset = 0;
7332dec2b5be2056c6d9428897dc672185872d30d17James Dong    } else {
734df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("The mp4 file will not be streamable.");
7357837c17063a4c50bc856ba59418516fdab731de7James Dong    }
7367837c17063a4c50bc856ba59418516fdab731de7James Dong
7370c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(mBoxes.empty());
73820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
739411ba422e3635d534928ffd81abf54f4f291c739James Dong    release();
74037187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
74120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
74220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
743b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::writeMvhdBox(int64_t durationUs) {
744b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    time_t now = time(NULL);
745b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("mvhd");
746b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // version=0, flags=0
747b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(now);           // creation time
748b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(now);           // modification time
749b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(mTimeScale);    // mvhd timescale
750b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t duration = (durationUs * mTimeScale + 5E5) / 1E6;
751b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(duration);
752b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0x10000);       // rate: 1.0
753b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt16(0x100);         // volume
754b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt16(0);             // reserved
755b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // reserved
756b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // reserved
757b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeCompositionMatrix(0); // matrix
758b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
759b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
760b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
761b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
762b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
763b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
764b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(mTracks.size() + 1);  // nextTrackID
765b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();  // mvhd
766b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
767b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
768b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::writeMoovBox(int64_t durationUs) {
769b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("moov");
770b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeMvhdBox(durationUs);
77107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (mAreGeoTagsAvailable) {
77207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        writeUdtaBox();
77307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
774b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t id = 1;
775b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    for (List<Track *>::iterator it = mTracks.begin();
776b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        it != mTracks.end(); ++it, ++id) {
777b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        (*it)->writeTrackHeader(mUse32BitOffset);
778b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
779b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();  // moov
780b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
781b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
7822cf9c5073ca3342ee52673ad68763fadd2c2be79James Dongvoid MPEG4Writer::writeFtypBox(MetaData *param) {
783b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("ftyp");
784b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
785b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t fileType;
786b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (param && param->findInt32(kKeyFileType, &fileType) &&
787b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        fileType != OUTPUT_FORMAT_MPEG_4) {
788b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeFourcc("3gp4");
789b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
790b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeFourcc("isom");
791b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
792b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
793b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);
794b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeFourcc("isom");
795b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeFourcc("3gp4");
796b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();
797b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
798b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
79907ec01904613a0bac32caaa8444b4690998faed7James Dongstatic bool isTestModeEnabled() {
80007ec01904613a0bac32caaa8444b4690998faed7James Dong#if (PROPERTY_VALUE_MAX < 5)
80107ec01904613a0bac32caaa8444b4690998faed7James Dong#error "PROPERTY_VALUE_MAX must be at least 5"
80207ec01904613a0bac32caaa8444b4690998faed7James Dong#endif
80307ec01904613a0bac32caaa8444b4690998faed7James Dong
80407ec01904613a0bac32caaa8444b4690998faed7James Dong    // Test mode is enabled only if rw.media.record.test system
80507ec01904613a0bac32caaa8444b4690998faed7James Dong    // property is enabled.
80607ec01904613a0bac32caaa8444b4690998faed7James Dong    char value[PROPERTY_VALUE_MAX];
80707ec01904613a0bac32caaa8444b4690998faed7James Dong    if (property_get("rw.media.record.test", value, NULL) &&
80807ec01904613a0bac32caaa8444b4690998faed7James Dong        (!strcasecmp(value, "true") || !strcasecmp(value, "1"))) {
80907ec01904613a0bac32caaa8444b4690998faed7James Dong        return true;
81007ec01904613a0bac32caaa8444b4690998faed7James Dong    }
81107ec01904613a0bac32caaa8444b4690998faed7James Dong    return false;
81207ec01904613a0bac32caaa8444b4690998faed7James Dong}
81307ec01904613a0bac32caaa8444b4690998faed7James Dong
81470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongvoid MPEG4Writer::sendSessionSummary() {
81507ec01904613a0bac32caaa8444b4690998faed7James Dong    // Send session summary only if test mode is enabled
81607ec01904613a0bac32caaa8444b4690998faed7James Dong    if (!isTestModeEnabled()) {
81707ec01904613a0bac32caaa8444b4690998faed7James Dong        return;
81807ec01904613a0bac32caaa8444b4690998faed7James Dong    }
81907ec01904613a0bac32caaa8444b4690998faed7James Dong
82070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
82170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong         it != mChunkInfos.end(); ++it) {
82270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        int trackNum = it->mTrack->getTrackId() << 28;
82370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
82470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                trackNum | MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS,
82570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                it->mMaxInterChunkDurUs);
82670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    }
82770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong}
82870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
82913aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) {
83013aec890216948b0c364f8f92792129d0335f506James Dong    mInterleaveDurationUs = durationUs;
83113aec890216948b0c364f8f92792129d0335f506James Dong    return OK;
83213aec890216948b0c364f8f92792129d0335f506James Dong}
83313aec890216948b0c364f8f92792129d0335f506James Dong
83413aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() {
83513aec890216948b0c364f8f92792129d0335f506James Dong    mLock.lock();
83613aec890216948b0c364f8f92792129d0335f506James Dong}
83713aec890216948b0c364f8f92792129d0335f506James Dong
83813aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() {
83913aec890216948b0c364f8f92792129d0335f506James Dong    mLock.unlock();
84013aec890216948b0c364f8f92792129d0335f506James Dong}
84120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
842c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addSample_l(MediaBuffer *buffer) {
843c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t old_offset = mOffset;
84420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
845c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    ::write(mFd,
846c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong          (const uint8_t *)buffer->data() + buffer->range_offset(),
847c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong          buffer->range_length());
84820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
84920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += buffer->range_length();
85020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
85120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return old_offset;
85220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
85320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
85403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) {
85503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (buffer->range_length() < 4) {
85603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return;
85703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
85803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
85903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    const uint8_t *ptr =
86003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        (const uint8_t *)buffer->data() + buffer->range_offset();
86103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
86203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) {
86303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        buffer->set_range(
86403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                buffer->range_offset() + 4, buffer->range_length() - 4);
86503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
86603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
86703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
868c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) {
869c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t old_offset = mOffset;
87030ab66297501757d745b9ae10da61adcd891f497Andreas Huber
87130ab66297501757d745b9ae10da61adcd891f497Andreas Huber    size_t length = buffer->range_length();
87203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
873b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (mUse4ByteNalLength) {
874b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        uint8_t x = length >> 24;
875c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
876b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = (length >> 16) & 0xff;
877c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
878b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = (length >> 8) & 0xff;
879c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
880b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = length & 0xff;
881c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
882c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong
883c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd,
884c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong              (const uint8_t *)buffer->data() + buffer->range_offset(),
885c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong              length);
886b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong
887b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mOffset += length + 4;
888b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    } else {
88943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_LT(length, 65536);
89030ab66297501757d745b9ae10da61adcd891f497Andreas Huber
891b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        uint8_t x = length >> 8;
892c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
893b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = length & 0xff;
894c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
895c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, (const uint8_t *)buffer->data() + buffer->range_offset(), length);
896b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mOffset += length + 2;
897b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    }
89830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
89930ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return old_offset;
90030ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
90130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
9027837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write(
903674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        const void *ptr, size_t size, size_t nmemb) {
9047837c17063a4c50bc856ba59418516fdab731de7James Dong
9057837c17063a4c50bc856ba59418516fdab731de7James Dong    const size_t bytes = size * nmemb;
9067837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
907674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        // This happens only when we write the moov box at the end of
908674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        // recording, not for each output video/audio frame we receive.
909c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes;
9101acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        if (moovBoxSize > mEstimatedMoovBoxSize) {
911c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            for (List<off64_t>::iterator it = mBoxes.begin();
9127837c17063a4c50bc856ba59418516fdab731de7James Dong                 it != mBoxes.end(); ++it) {
9137837c17063a4c50bc856ba59418516fdab731de7James Dong                (*it) += mOffset;
9147837c17063a4c50bc856ba59418516fdab731de7James Dong            }
915674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong            lseek64(mFd, mOffset, SEEK_SET);
916674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong            ::write(mFd, mMoovBoxBuffer, mMoovBoxBufferOffset);
917674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong            ::write(mFd, ptr, size * nmemb);
9187837c17063a4c50bc856ba59418516fdab731de7James Dong            mOffset += (bytes + mMoovBoxBufferOffset);
9197837c17063a4c50bc856ba59418516fdab731de7James Dong            free(mMoovBoxBuffer);
9207837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBuffer = NULL;
9217837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset = 0;
9227837c17063a4c50bc856ba59418516fdab731de7James Dong            mWriteMoovBoxToMemory = false;
9237837c17063a4c50bc856ba59418516fdab731de7James Dong            mStreamableFile = false;
9247837c17063a4c50bc856ba59418516fdab731de7James Dong        } else {
9257837c17063a4c50bc856ba59418516fdab731de7James Dong            memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes);
9267837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset += bytes;
9277837c17063a4c50bc856ba59418516fdab731de7James Dong        }
9287837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
929674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        ::write(mFd, ptr, size * nmemb);
9307837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset += bytes;
9317837c17063a4c50bc856ba59418516fdab731de7James Dong    }
9327837c17063a4c50bc856ba59418516fdab731de7James Dong    return bytes;
9337837c17063a4c50bc856ba59418516fdab731de7James Dong}
9347837c17063a4c50bc856ba59418516fdab731de7James Dong
93520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) {
9360c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(fourcc), 4);
93720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9387837c17063a4c50bc856ba59418516fdab731de7James Dong    mBoxes.push_back(mWriteMoovBoxToMemory?
9397837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset: mOffset);
94020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
94120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeInt32(0);
94220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeFourcc(fourcc);
94320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
94420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
94520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() {
9460c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(!mBoxes.empty());
94720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
948c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t offset = *--mBoxes.end();
94920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mBoxes.erase(--mBoxes.end());
95020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9517837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
9527837c17063a4c50bc856ba59418516fdab731de7James Dong       int32_t x = htonl(mMoovBoxBufferOffset - offset);
9537837c17063a4c50bc856ba59418516fdab731de7James Dong       memcpy(mMoovBoxBuffer + offset, &x, 4);
9547837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
955c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, offset, SEEK_SET);
9567837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mOffset - offset);
9577837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset -= 4;
958c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mOffset, SEEK_SET);
9597837c17063a4c50bc856ba59418516fdab731de7James Dong    }
96020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
96120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
96220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) {
963674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 1);
96420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
96520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
96620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) {
96720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htons(x);
968674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 2);
96920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
97020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
97120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) {
97220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htonl(x);
973674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 4);
97420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
97520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
97620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) {
97720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = hton64(x);
978674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 8);
97920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
98020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
98120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) {
98220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t n = strlen(s);
983674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(s, 1, n + 1);
98420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
98520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
98620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) {
9870c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(s), 4);
988674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(s, 1, 4);
98920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
99020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
99107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
99207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/-DD.DDDD format
99307b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLatitude(int degreex10000) {
99407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    bool isNegative = (degreex10000 < 0);
99507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char sign = isNegative? '-': '+';
99607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
99707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the whole part
99807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char str[9];
99907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int wholePart = degreex10000 / 10000;
100007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (wholePart == 0) {
100107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 5, "%c%.2d.", sign, wholePart);
100207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    } else {
100307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 5, "%+.2d.", wholePart);
100407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
100507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
100607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the fractional part
100707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int fractionalPart = degreex10000 - (wholePart * 10000);
100807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (fractionalPart < 0) {
100907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        fractionalPart = -fractionalPart;
101007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
101107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    snprintf(&str[4], 5, "%.4d", fractionalPart);
101207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
101307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Do not write the null terminator
101407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    write(str, 1, 8);
101507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
101607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
101707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/- DDD.DDDD format
101807b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLongitude(int degreex10000) {
101907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    bool isNegative = (degreex10000 < 0);
102007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char sign = isNegative? '-': '+';
102107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
102207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the whole part
102307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char str[10];
102407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int wholePart = degreex10000 / 10000;
102507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (wholePart == 0) {
102607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 6, "%c%.3d.", sign, wholePart);
102707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    } else {
102807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 6, "%+.3d.", wholePart);
102907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
103007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
103107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the fractional part
103207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int fractionalPart = degreex10000 - (wholePart * 10000);
103307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (fractionalPart < 0) {
103407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        fractionalPart = -fractionalPart;
103507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
103607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    snprintf(&str[5], 5, "%.4d", fractionalPart);
103707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
103807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Do not write the null terminator
103907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    write(str, 1, 9);
104007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
104107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
104207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/*
104307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard.
104407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * latitudex10000 is latitude in degrees times 10000, and
104507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * longitudex10000 is longitude in degrees times 10000.
104607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the latitude is in [-90, +90], and
104707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the longitude is in [-180, +180]
104807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */
104907b1bb529a1ae76c46a71b01338c166f9490629dJames Dongstatus_t MPEG4Writer::setGeoData(int latitudex10000, int longitudex10000) {
105007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Is latitude or longitude out of range?
105107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (latitudex10000 < -900000 || latitudex10000 > 900000 ||
105207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        longitudex10000 < -1800000 || longitudex10000 > 1800000) {
105307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        return BAD_VALUE;
105407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
105507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
105607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mLatitudex10000 = latitudex10000;
105707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mLongitudex10000 = longitudex10000;
105807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mAreGeoTagsAvailable = true;
105907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    return OK;
106007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
106107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
106220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) {
1063674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(data, 1, size);
106420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
106520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
106678a1a286f736888ae7af8860b2c424af0d978848James Dongbool MPEG4Writer::isFileStreamable() const {
106778a1a286f736888ae7af8860b2c424af0d978848James Dong    return mStreamableFile;
106878a1a286f736888ae7af8860b2c424af0d978848James Dong}
106978a1a286f736888ae7af8860b2c424af0d978848James Dong
1070d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() {
1071d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
1072d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileSizeLimitBytes == 0) {
1073d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
1074d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1075d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1076956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize);
1077d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
1078d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
1079d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes();
1080d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
10811f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
108277e8ae9967a078770416619e99ddb5b010def312James Dong    if (!mStreamableFile) {
108377e8ae9967a078770416619e99ddb5b010def312James Dong        // Add 1024 bytes as error tolerance
108477e8ae9967a078770416619e99ddb5b010def312James Dong        return nTotalBytesEstimate + 1024 >= mMaxFileSizeLimitBytes;
108577e8ae9967a078770416619e99ddb5b010def312James Dong    }
1086acd234bba9f048971d66890009eeff9a8db94be3James Dong    // Be conservative in the estimate: do not exceed 95% of
1087acd234bba9f048971d66890009eeff9a8db94be3James Dong    // the target file limit. For small target file size limit, though,
1088acd234bba9f048971d66890009eeff9a8db94be3James Dong    // this will not help.
1089acd234bba9f048971d66890009eeff9a8db94be3James Dong    return (nTotalBytesEstimate >= (95 * mMaxFileSizeLimitBytes) / 100);
1090d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
1091d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1092d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() {
1093d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
1094d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileDurationLimitUs == 0) {
1095d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
1096d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1097d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1098d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
1099d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
1100d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) {
1101d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            return true;
1102d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
1103d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1104d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return false;
1105d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
1106d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
110725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() {
110825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool allDone = true;
110925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
111025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber         it != mTracks.end(); ++it) {
111125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        if (!(*it)->reachedEOS()) {
111225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            allDone = false;
111325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            break;
111425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        }
111525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
111625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
111725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return allDone;
111825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
111925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
1120f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) {
1121df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("setStartTimestampUs: %lld", timeUs);
112243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GE(timeUs, 0ll);
11233c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
1124065d1aff96818df54456053f1574aec8a234d0deJames Dong    if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) {
1125f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mStartTimestampUs = timeUs;
1126df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("Earliest track starting time: %lld", mStartTimestampUs);
11273c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    }
11283c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
11293c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
1130f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() {
11313c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
11323c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    return mStartTimestampUs;
11333c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
11343c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
113558ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() {
113658ae9c530247668f8af36e30d228c716c226b3d4James Dong    Mutex::Autolock autolock(mLock);
113758ae9c530247668f8af36e30d228c716c226b3d4James Dong    return mTracks.size();
113858ae9c530247668f8af36e30d228c716c226b3d4James Dong}
113958ae9c530247668f8af36e30d228c716c226b3d4James Dong
114020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
114120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
114220111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track(
1143bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId)
114420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mOwner(owner),
114525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mMeta(source->getFormat()),
114620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSource(source),
114720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDone(false),
1148a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
1149a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mResumed(false),
1150eaae38445a340c4857c1c5569475879a728e63b7James Dong      mStarted(false),
1151bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong      mTrackId(trackId),
1152c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong      mTrackDurationUs(0),
115313210f3346462a86ce9fe3af72a0c200dba84e27James Dong      mNumSamples(0),
1154956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      mEstimatedTrackSizeBytes(0),
1155be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong      mSamplesHaveSameSize(true),
115620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCodecSpecificData(NULL),
115725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mCodecSpecificDataSize(0),
1158548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber      mGotAllCodecSpecificData(false),
115913f6284305e4b27395a23db7882d670bdb1bcae1James Dong      mReachedEOS(false),
116013f6284305e4b27395a23db7882d670bdb1bcae1James Dong      mRotation(0) {
116119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    getCodecSpecificDataFromInputFormatIfPossible();
11628f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
11631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    const char *mime;
11641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mMeta->findCString(kKeyMIMEType, &mime);
11651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
11661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAudio = !strncasecmp(mime, "audio/", 6);
11671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
11681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong               !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC);
11691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1170c059860c73678a202bfa33062723e8f82fb779d9James Dong    setTimeScale();
1171c059860c73678a202bfa33062723e8f82fb779d9James Dong}
1172c059860c73678a202bfa33062723e8f82fb779d9James Dong
11731f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::updateTrackSizeEstimate() {
11741f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
11751f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    int64_t stcoBoxSizeBytes = mOwner->use32BitFileOffset()
11761f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                                ? mNumStcoTableEntries * 4
11771f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                                : mNumStcoTableEntries * 8;
11781f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
11791f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mNumSamples * 4);
11801f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
118178a1a286f736888ae7af8860b2c424af0d978848James Dong    mEstimatedTrackSizeBytes = mMdatSizeBytes;  // media data size
118278a1a286f736888ae7af8860b2c424af0d978848James Dong    if (!mOwner->isFileStreamable()) {
118378a1a286f736888ae7af8860b2c424af0d978848James Dong        // Reserved free space is not large enough to hold
118478a1a286f736888ae7af8860b2c424af0d978848James Dong        // all meta data and thus wasted.
118578a1a286f736888ae7af8860b2c424af0d978848James Dong        mEstimatedTrackSizeBytes += mNumStscTableEntries * 12 +  // stsc box size
118678a1a286f736888ae7af8860b2c424af0d978848James Dong                                    mNumStssTableEntries * 4 +   // stss box size
118778a1a286f736888ae7af8860b2c424af0d978848James Dong                                    mNumSttsTableEntries * 8 +   // stts box size
1188965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong                                    mNumCttsTableEntries * 8 +   // ctts box size
118978a1a286f736888ae7af8860b2c424af0d978848James Dong                                    stcoBoxSizeBytes +           // stco box size
119078a1a286f736888ae7af8860b2c424af0d978848James Dong                                    stszBoxSizeBytes;            // stsz box size
119178a1a286f736888ae7af8860b2c424af0d978848James Dong    }
11921f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
11931f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
11941f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStscTableEntry(
11951f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        size_t chunkId, size_t sampleId) {
11961f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
11971f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        StscTableEntry stscEntry(chunkId, sampleId, 1);
11981f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mStscTableEntries.push_back(stscEntry);
11991f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        ++mNumStscTableEntries;
12001f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
12011f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
12021f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) {
12031f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mStssTableEntries.push_back(sampleId);
12041f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    ++mNumStssTableEntries;
12051f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
12061f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
12071f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneSttsTableEntry(
120879761ab096f57c3027fad9556c2bc436672d614eJames Dong        size_t sampleCount, int32_t duration) {
12091f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
12105a217fba010e801c255503602bda4b86ac5a6ac9James Dong    if (duration == 0) {
12115ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("0-duration samples found: %d", sampleCount);
12125a217fba010e801c255503602bda4b86ac5a6ac9James Dong    }
121379761ab096f57c3027fad9556c2bc436672d614eJames Dong    SttsTableEntry sttsEntry(sampleCount, duration);
12141f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mSttsTableEntries.push_back(sttsEntry);
12151f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    ++mNumSttsTableEntries;
12161f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
12171f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1218965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::addOneCttsTableEntry(
1219965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        size_t sampleCount, int32_t duration) {
1220965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
1221965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    if (mIsAudio) {
1222965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
1223965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
1224965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    CttsTableEntry cttsEntry(sampleCount, duration);
1225965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mCttsTableEntries.push_back(cttsEntry);
1226965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    ++mNumCttsTableEntries;
1227965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong}
1228965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
1229c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongvoid MPEG4Writer::Track::addChunkOffset(off64_t offset) {
12301f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    ++mNumStcoTableEntries;
12311f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mChunkOffsets.push_back(offset);
12321f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
12331f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1234c059860c73678a202bfa33062723e8f82fb779d9James Dongvoid MPEG4Writer::Track::setTimeScale() {
12353856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setTimeScale");
1236c059860c73678a202bfa33062723e8f82fb779d9James Dong    // Default time scale
1237c059860c73678a202bfa33062723e8f82fb779d9James Dong    mTimeScale = 90000;
1238c059860c73678a202bfa33062723e8f82fb779d9James Dong
1239c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mIsAudio) {
1240c059860c73678a202bfa33062723e8f82fb779d9James Dong        // Use the sampling rate as the default time scale for audio track.
1241c059860c73678a202bfa33062723e8f82fb779d9James Dong        int32_t sampleRate;
1242c059860c73678a202bfa33062723e8f82fb779d9James Dong        bool success = mMeta->findInt32(kKeySampleRate, &sampleRate);
1243c059860c73678a202bfa33062723e8f82fb779d9James Dong        CHECK(success);
1244c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = sampleRate;
1245c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
1246c059860c73678a202bfa33062723e8f82fb779d9James Dong
1247c059860c73678a202bfa33062723e8f82fb779d9James Dong    // If someone would like to overwrite the timescale, use user-supplied value.
1248c059860c73678a202bfa33062723e8f82fb779d9James Dong    int32_t timeScale;
1249c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mMeta->findInt32(kKeyTimeScale, &timeScale)) {
1250c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = timeScale;
1251c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
1252c059860c73678a202bfa33062723e8f82fb779d9James Dong
125343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mTimeScale, 0);
125419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber}
125519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
125619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Hubervoid MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() {
125719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    const char *mime;
125819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
125919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
126019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
126119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        uint32_t type;
126219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        const void *data;
126319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        size_t size;
126419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        if (mMeta->findData(kKeyAVCC, &type, &data, &size)) {
126519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mCodecSpecificData = malloc(size);
126619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mCodecSpecificDataSize = size;
126719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            memcpy(mCodecSpecificData, data, size);
126819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mGotAllCodecSpecificData = true;
126919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        }
127019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
127119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
127219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        uint32_t type;
127319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        const void *data;
127419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        size_t size;
127519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        if (mMeta->findData(kKeyESDS, &type, &data, &size)) {
127619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            ESDS esds(data, size);
127719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            if (esds.getCodecSpecificInfo(&data, &size) == OK) {
127819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mCodecSpecificData = malloc(size);
127919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mCodecSpecificDataSize = size;
128019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                memcpy(mCodecSpecificData, data, size);
128119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mGotAllCodecSpecificData = true;
128219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            }
128319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        }
128419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
128520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
128620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
128720111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() {
128820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    stop();
128920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
129020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mCodecSpecificData != NULL) {
129120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        free(mCodecSpecificData);
129220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mCodecSpecificData = NULL;
129320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
12948c460498c028888c533ab442be12b6d4b669b965James Dong
12958c460498c028888c533ab442be12b6d4b669b965James Dong    while (!mSampleSizes.empty()) {
12968c460498c028888c533ab442be12b6d4b669b965James Dong        List<uint32_t *>::iterator it = mSampleSizes.begin();
12978c460498c028888c533ab442be12b6d4b669b965James Dong        delete[] (*it);
12988c460498c028888c533ab442be12b6d4b669b965James Dong        mSampleSizes.erase(it);
12998c460498c028888c533ab442be12b6d4b669b965James Dong    }
130020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
130120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
130293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) {
13033856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("initTrackingProgressStatus");
130493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mPreviousTrackTimeUs = -1;
130593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackingProgressStatus = false;
130693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackEveryTimeDurationUs = 0;
130793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    {
130893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        int64_t timeUs;
130993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) {
13103856b090cd04ba5dd4a59a12430ed724d5995909Steve Block            ALOGV("Receive request to track progress status for every %lld us", timeUs);
131193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackEveryTimeDurationUs = timeUs;
131293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackingProgressStatus = true;
131393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
131493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
131593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
131693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
13171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong// static
13181c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid *MPEG4Writer::ThreadWrapper(void *me) {
13193856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("ThreadWrapper: %p", me);
13201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    MPEG4Writer *writer = static_cast<MPEG4Writer *>(me);
13211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    writer->threadFunc();
13221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return NULL;
13231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
13241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
13251c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::bufferChunk(const Chunk& chunk) {
13263856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("bufferChunk: %p", chunk.mTrack);
13271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Mutex::Autolock autolock(mLock);
13281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    CHECK_EQ(mDone, false);
13291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
13301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
13311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
13321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
13331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (chunk.mTrack == it->mTrack) {  // Found owner
13341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            it->mChunks.push_back(chunk);
13351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.signal();
13361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            return;
13371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
13381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
13391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
134043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK(!"Received a chunk for a unknown track");
13411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
13421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1343fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeChunkToFile(Chunk* chunk) {
13443856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("writeChunkToFile: %lld from %s track",
13455410afcbb0af5d29d9f710a1c2978c500f9792dcPannag Sanketi        chunk->mTimeStampUs, chunk->mTrack->isAudio()? "audio": "video");
1346fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1347fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    int32_t isFirstSample = true;
1348fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    while (!chunk->mSamples.empty()) {
1349fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        List<MediaBuffer *>::iterator it = chunk->mSamples.begin();
1350fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1351fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        off64_t offset = chunk->mTrack->isAvc()
1352fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong                                ? addLengthPrefixedSample_l(*it)
1353fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong                                : addSample_l(*it);
1354fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1355fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        if (isFirstSample) {
1356fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            chunk->mTrack->addChunkOffset(offset);
1357fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            isFirstSample = false;
13581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
13591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
13601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it)->release();
13611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it) = NULL;
1362fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        chunk->mSamples.erase(it);
13631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1364fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    chunk->mSamples.clear();
13651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
13661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1367fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeAllChunks() {
13683856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("writeAllChunks");
13691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    size_t outstandingChunks = 0;
137070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    Chunk chunk;
137170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    while (findChunkToWrite(&chunk)) {
1372e9f6d0579603372fd2547e6c5ba6e114c6f8cba7James Dong        writeChunkToFile(&chunk);
137370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        ++outstandingChunks;
13741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
137570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
137670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    sendSessionSummary();
137770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
13781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mChunkInfos.clear();
1379b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("%d chunks are written in the last batch", outstandingChunks);
13801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
13811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1382fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongbool MPEG4Writer::findChunkToWrite(Chunk *chunk) {
13833856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("findChunkToWrite");
13841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
13851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL;
13861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Track *track = NULL;
13871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
13881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
13891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (!it->mChunks.empty()) {
13901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            List<Chunk>::iterator chunkIt = it->mChunks.begin();
13911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (chunkIt->mTimeStampUs < minTimestampUs) {
13921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                minTimestampUs = chunkIt->mTimeStampUs;
13931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                track = it->mTrack;
13941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            }
13951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
13961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
13971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
13981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (track == NULL) {
13993856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("Nothing to be written after all");
1400fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        return false;
14011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
14021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
14031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (mIsFirstChunk) {
14041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsFirstChunk = false;
14051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1406fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
14071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
14081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
14091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (it->mTrack == track) {
1410fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            *chunk = *(it->mChunks.begin());
1411fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            it->mChunks.erase(it->mChunks.begin());
1412fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            CHECK_EQ(chunk->mTrack, track);
141370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
141470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            int64_t interChunkTimeUs =
141570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                chunk->mTimeStampUs - it->mPrevChunkTimestampUs;
141670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            if (interChunkTimeUs > it->mPrevChunkTimestampUs) {
141770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                it->mMaxInterChunkDurUs = interChunkTimeUs;
141870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            }
141970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
1420fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            return true;
14211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
14221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1423fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1424fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    return false;
14251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
14261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
14271c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::threadFunc() {
14283856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("threadFunc");
14291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1430a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    prctl(PR_SET_NAME, (unsigned long)"MPEG4Writer", 0, 0, 0);
1431fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1432fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    Mutex::Autolock autoLock(mLock);
14331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    while (!mDone) {
1434fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        Chunk chunk;
1435fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        bool chunkFound = false;
1436fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1437fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        while (!mDone && !(chunkFound = findChunkToWrite(&chunk))) {
14381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.wait(mLock);
14391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
14401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1441fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        // Actual write without holding the lock in order to
1442fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        // reduce the blocking time for media track threads.
1443fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        if (chunkFound) {
1444fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            mLock.unlock();
1445fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            writeChunkToFile(&chunk);
1446fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            mLock.lock();
1447fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        }
14481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1449fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1450fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    writeAllChunks();
14511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
14521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
14531c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::startWriterThread() {
14543856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("startWriterThread");
14551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
14561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mDone = false;
14571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsFirstChunk = true;
1458e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    mDriftTimeUs = 0;
14591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<Track *>::iterator it = mTracks.begin();
14601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mTracks.end(); ++it) {
14611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        ChunkInfo info;
14621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        info.mTrack = *it;
146370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        info.mPrevChunkTimestampUs = 0;
146470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        info.mMaxInterChunkDurUs = 0;
14651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkInfos.push_back(info);
14661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
14671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
14681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_t attr;
14691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_init(&attr);
14701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
14711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_create(&mThread, &attr, ThreadWrapper, this);
14721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_destroy(&attr);
1473411ba422e3635d534928ffd81abf54f4f291c739James Dong    mWriterThreadStarted = true;
14741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return OK;
14751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
14761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
14771f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
147893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) {
1479a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (!mDone && mPaused) {
1480a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mPaused = false;
1481a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mResumed = true;
1482a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
1483a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
148425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
148593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t startTimeUs;
148619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) {
148719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        startTimeUs = 0;
148819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
148970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    mStartTimeRealUs = startTimeUs;
149019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
149113f6284305e4b27395a23db7882d670bdb1bcae1James Dong    int32_t rotationDegrees;
149213f6284305e4b27395a23db7882d670bdb1bcae1James Dong    if (!mIsAudio && params && params->findInt32(kKeyRotation, &rotationDegrees)) {
149313f6284305e4b27395a23db7882d670bdb1bcae1James Dong        mRotation = rotationDegrees;
149413f6284305e4b27395a23db7882d670bdb1bcae1James Dong    }
149513f6284305e4b27395a23db7882d670bdb1bcae1James Dong
14965b6a01e65aa4129a9226667536d1bc1dad5980d8James Dong    mIsRealTimeRecording = true;
1497e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    {
1498e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        int32_t isNotRealTime;
1499e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        if (params && params->findInt32(kKeyNotRealTime, &isNotRealTime)) {
1500e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            mIsRealTimeRecording = (isNotRealTime == 0);
1501e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        }
1502e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    }
1503e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
150493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    initTrackingProgressStatus(params);
150593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
1506f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    sp<MetaData> meta = new MetaData;
1507a472613aec322e25891abf5c77bf3f7e3c244920James Dong    if (mIsRealTimeRecording && mOwner->numTracks() > 1) {
1508a472613aec322e25891abf5c77bf3f7e3c244920James Dong        /*
1509a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * This extra delay of accepting incoming audio/video signals
1510a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * helps to align a/v start time at the beginning of a recording
1511a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * session, and it also helps eliminate the "recording" sound for
1512a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * camcorder applications.
1513a472613aec322e25891abf5c77bf3f7e3c244920James Dong         *
151486b7f47aa7482424cf8fd248f1315311919be3b0James Dong         * If client does not set the start time offset, we fall back to
151586b7f47aa7482424cf8fd248f1315311919be3b0James Dong         * use the default initial delay value.
1516a472613aec322e25891abf5c77bf3f7e3c244920James Dong         */
151786b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL;
151886b7f47aa7482424cf8fd248f1315311919be3b0James Dong        if (startTimeOffsetUs < 0) {  // Start time offset was not set
151986b7f47aa7482424cf8fd248f1315311919be3b0James Dong            startTimeOffsetUs = kInitialDelayTimeUs;
152086b7f47aa7482424cf8fd248f1315311919be3b0James Dong        }
152186b7f47aa7482424cf8fd248f1315311919be3b0James Dong        startTimeUs += startTimeOffsetUs;
1522df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("Start time offset: %lld us", startTimeOffsetUs);
1523a472613aec322e25891abf5c77bf3f7e3c244920James Dong    }
1524a472613aec322e25891abf5c77bf3f7e3c244920James Dong
1525f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    meta->setInt64(kKeyTime, startTimeUs);
1526a472613aec322e25891abf5c77bf3f7e3c244920James Dong
1527f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    status_t err = mSource->start(meta.get());
152825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    if (err != OK) {
152925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        mDone = mReachedEOS = true;
153025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return err;
153125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
153220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
153320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_t attr;
153420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_init(&attr);
153520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
153620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
153720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = false;
1538eaae38445a340c4857c1c5569475879a728e63b7James Dong    mStarted = true;
1539c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs = 0;
154025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = false;
1541956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    mEstimatedTrackSizeBytes = 0;
15421f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mNumStcoTableEntries = 0;
15431f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mNumStssTableEntries = 0;
15441f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mNumStscTableEntries = 0;
15451f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mNumSttsTableEntries = 0;
1546965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mNumCttsTableEntries = 0;
15471f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mMdatSizeBytes = 0;
1548f2ab12d0dcef27fd52dcae53221e9c51a369fef6James Dong
154943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mMaxChunkDurationUs = 0;
155020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
155125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    pthread_create(&mThread, &attr, ThreadWrapper, this);
155220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_destroy(&attr);
155325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
155425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
155520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
155620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
155737187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::pause() {
1558a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
155937187916a486504acaf83bea30147eb5fbf46ae5James Dong    return OK;
1560a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
1561a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
156237187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::stop() {
1563b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("Stopping %s track", mIsAudio? "Audio": "Video");
1564eaae38445a340c4857c1c5569475879a728e63b7James Dong    if (!mStarted) {
156529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Stop() called but track is not started");
1566eaae38445a340c4857c1c5569475879a728e63b7James Dong        return ERROR_END_OF_STREAM;
1567eaae38445a340c4857c1c5569475879a728e63b7James Dong    }
1568eaae38445a340c4857c1c5569475879a728e63b7James Dong
156920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mDone) {
157037187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
157120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
157220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = true;
157320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
157420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *dummy;
157520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_join(mThread, &dummy);
157620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
157737187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = (status_t) dummy;
157837187916a486504acaf83bea30147eb5fbf46ae5James Dong
1579b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("Stopping %s track source", mIsAudio? "Audio": "Video");
158037187916a486504acaf83bea30147eb5fbf46ae5James Dong    {
158137187916a486504acaf83bea30147eb5fbf46ae5James Dong        status_t status = mSource->stop();
158237187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (err == OK && status != OK && status != ERROR_END_OF_STREAM) {
158337187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
158437187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
158537187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
158637187916a486504acaf83bea30147eb5fbf46ae5James Dong
1587b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("%s track stopped", mIsAudio? "Audio": "Video");
158837187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
158920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
159020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
159125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() {
159225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return mReachedEOS;
159325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
159425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
159520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static
159620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) {
159720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = static_cast<Track *>(me);
159820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
159937187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = track->threadEntry();
160037187916a486504acaf83bea30147eb5fbf46ae5James Dong    return (void *) err;
160120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
160220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
16033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic void getNalUnitType(uint8_t byte, uint8_t* type) {
16043856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("getNalUnitType: %d", byte);
16053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
16063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // nal_unit_type: 5-bit unsigned integer
16073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *type = (byte & 0x1F);
16083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
16093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
16103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t *findNextStartCode(
16113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length) {
16123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
16133856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("findNextStartCode: %p %d", data, length);
16143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
16153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t bytesLeft = length;
16163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    while (bytesLeft > 4  &&
16173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            memcmp("\x00\x00\x00\x01", &data[length - bytesLeft], 4)) {
16183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        --bytesLeft;
16193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
16203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (bytesLeft <= 4) {
16213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        bytesLeft = 0; // Last parameter set
16223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
16233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return &data[length - bytesLeft];
16243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
16253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
16263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongconst uint8_t *MPEG4Writer::Track::parseParamSet(
16273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen) {
16283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
16293856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("parseParamSet");
16303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    CHECK(type == kNalUnitTypeSeqParamSet ||
16313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong          type == kNalUnitTypePicParamSet);
16323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
16333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *nextStartCode = findNextStartCode(data, length);
16343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *paramSetLen = nextStartCode - data;
16353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (*paramSetLen == 0) {
163629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Param set is malformed, since its length is 0");
16373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return NULL;
16383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
16393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
16403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    AVCParamSet paramSet(*paramSetLen, data);
16413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (type == kNalUnitTypeSeqParamSet) {
16423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (*paramSetLen < 4) {
164329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Seq parameter set malformed");
16443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return NULL;
16453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
16463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mSeqParamSets.empty()) {
16473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc = data[1];
16483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileCompatible = data[2];
16493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mLevelIdc = data[3];
16503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
16513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (mProfileIdc != data[1] ||
16523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mProfileCompatible != data[2] ||
16533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mLevelIdc != data[3]) {
165429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("Inconsistent profile/level found in seq parameter sets");
16553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return NULL;
16563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
16573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
16583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mSeqParamSets.push_back(paramSet);
16593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    } else {
16603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mPicParamSets.push_back(paramSet);
16613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
16623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return nextStartCode;
16633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
16643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
16653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::copyAVCCodecSpecificData(
16663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
16673856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("copyAVCCodecSpecificData");
16683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
16693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 2 bytes for each of the parameter set length field
16703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // plus the 7 bytes for the header
16713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (size < 4 + 7) {
167229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Codec specific data length too short: %d", size);
16733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return ERROR_MALFORMED;
16743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
16753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
16763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize = size;
16773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificData = malloc(size);
16783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    memcpy(mCodecSpecificData, data, size);
16793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
16803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
16813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
16823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::parseAVCCodecSpecificData(
16833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
16843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
16853856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("parseAVCCodecSpecificData");
16863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data starts with a start code.
16873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // SPS and PPS are separated with start codes.
16883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Also, SPS must come before PPS
16893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t type = kNalUnitTypeSeqParamSet;
16903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotSps = false;
16913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotPps = false;
16923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *tmp = data;
16933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *nextStartCode = data;
16943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t bytesLeft = size;
16953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t paramSetLen = 0;
16963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize = 0;
16973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) {
16983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        getNalUnitType(*(tmp + 4), &type);
16993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (type == kNalUnitTypeSeqParamSet) {
17003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (gotPps) {
170129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("SPS must come before PPS");
17023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
17033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
17043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
17053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotSps = true;
17063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
17073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
17083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else if (type == kNalUnitTypePicParamSet) {
17093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
171029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("SPS must come before PPS");
17113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
17123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
17133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotPps) {
17143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotPps = true;
17153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
17163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
17173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
171829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Only SPS and PPS Nal units are expected");
17193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
17203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
17213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
17223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nextStartCode == NULL) {
17233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
17243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
17253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
17263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Move on to find the next parameter set
17273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        bytesLeft -= nextStartCode - tmp;
17283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        tmp = nextStartCode;
17293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mCodecSpecificDataSize += (2 + paramSetLen);
17303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
17313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
17323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
17333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of seq parameter sets
17343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nSeqParamSets = mSeqParamSets.size();
17353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets == 0) {
173629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Cound not find sequence parameter set");
17373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
17383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
17393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
17403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets > 0x1F) {
174129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Too many seq parameter sets (%d) found", nSeqParamSets);
17423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
17433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
17443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
17453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
17463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
17473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of pic parameter sets
17483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nPicParamSets = mPicParamSets.size();
17493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets == 0) {
175029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Cound not find picture parameter set");
17513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
17523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
17533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets > 0xFF) {
175429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Too many pic parameter sets (%d) found", nPicParamSets);
17553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
17563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
17573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
17581374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// FIXME:
17591374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// Add chromat_format_idc, bit depth values, etc for AVC/h264 high profile and above
17601374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// and remove #if 0
17611374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#if 0
17623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
17633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the profiles
17643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // These profiles requires additional parameter set extensions
17653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mProfileIdc == 100 || mProfileIdc == 110 ||
17663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc == 122 || mProfileIdc == 144) {
176729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Sorry, no support for profile_idc: %d!", mProfileIdc);
17683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return BAD_VALUE;
17693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
17703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
17711374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#endif
17723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
17733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
1774548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
177503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData(
177603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        const uint8_t *data, size_t size) {
1777548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
177803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (mCodecSpecificData != NULL) {
177929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Already have codec specific data");
178003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
178103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
178203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
17833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (size < 4) {
178429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Codec specific data length too short: %d", size);
178503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
178603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
178703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
17883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data is in the form of AVCCodecSpecificData
17893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (memcmp("\x00\x00\x00\x01", data, 4)) {
17903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return copyAVCCodecSpecificData(data, size);
179103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
179203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
17933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (parseAVCCodecSpecificData(data, size) != OK) {
179403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
179503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
179603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
17973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // ISO 14496-15: AVC file format
17983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize += 7;  // 7 more bytes in the header
179903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    mCodecSpecificData = malloc(mCodecSpecificDataSize);
180003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    uint8_t *header = (uint8_t *)mCodecSpecificData;
18013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = 1;                     // version
18023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[1] = mProfileIdc;           // profile indication
18033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[2] = mProfileCompatible;    // profile compatibility
18043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[3] = mLevelIdc;
180503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
18063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne
1807b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (mOwner->useNalLengthFour()) {
1808b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        header[4] = 0xfc | 3;  // length size == 4 bytes
1809b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    } else {
1810b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        header[4] = 0xfc | 1;  // length size == 2 bytes
1811b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    }
181203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
18133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 3-bit '111' followed by 5-bit numSequenceParameterSets
18143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nSequenceParamSets = mSeqParamSets.size();
18153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[5] = 0xe0 | nSequenceParamSets;
18163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 6;
18173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mSeqParamSets.begin();
18183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mSeqParamSets.end(); ++it) {
18193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit sequence parameter set length
18203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t seqParamSetLength = it->mLength;
18213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = seqParamSetLength >> 8;
18223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = seqParamSetLength & 0xff;
18233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
18243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // SPS NAL unit (sequence parameter length bytes)
18253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, seqParamSetLength);
18263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + seqParamSetLength);
18273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
18283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
18293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 8-bit nPictureParameterSets
18303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nPictureParamSets = mPicParamSets.size();
18313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = nPictureParamSets;
18323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 1;
18333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mPicParamSets.begin();
18343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mPicParamSets.end(); ++it) {
18353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit picture parameter set length
18363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t picParamSetLength = it->mLength;
18373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = picParamSetLength >> 8;
18383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = picParamSetLength & 0xff;
18393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
18403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // PPS Nal unit (picture parameter set length bytes)
18413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, picParamSetLength);
18423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + picParamSetLength);
18433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
184403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
184503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    return OK;
184603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
184703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
1848872a481558350634a3fd5cb67939de288af00ecbJames Dong/*
1849872a481558350634a3fd5cb67939de288af00ecbJames Dong * Updates the drift time from the audio track so that
1850872a481558350634a3fd5cb67939de288af00ecbJames Dong * the video track can get the updated drift time information
1851872a481558350634a3fd5cb67939de288af00ecbJames Dong * from the file writer. The fluctuation of the drift time of the audio
1852872a481558350634a3fd5cb67939de288af00ecbJames Dong * encoding path is smoothed out with a simple filter by giving a larger
1853872a481558350634a3fd5cb67939de288af00ecbJames Dong * weight to more recently drift time. The filter coefficients, 0.5 and 0.5,
1854872a481558350634a3fd5cb67939de288af00ecbJames Dong * are heuristically determined.
1855872a481558350634a3fd5cb67939de288af00ecbJames Dong */
1856872a481558350634a3fd5cb67939de288af00ecbJames Dongvoid MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) {
1857872a481558350634a3fd5cb67939de288af00ecbJames Dong    int64_t driftTimeUs = 0;
1858872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) {
1859872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t prevDriftTimeUs = mOwner->getDriftTimeUs();
1860872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1;
1861872a481558350634a3fd5cb67939de288af00ecbJames Dong        mOwner->setDriftTimeUs(timeUs);
1862872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
1863872a481558350634a3fd5cb67939de288af00ecbJames Dong}
1864872a481558350634a3fd5cb67939de288af00ecbJames Dong
186537187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::threadEntry() {
186630ab66297501757d745b9ae10da61adcd891f497Andreas Huber    int32_t count = 0;
186713aec890216948b0c364f8f92792129d0335f506James Dong    const int64_t interleaveDurationUs = mOwner->interleaveDuration();
186843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    const bool hasMultipleTracks = (mOwner->numTracks() > 1);
186913aec890216948b0c364f8f92792129d0335f506James Dong    int64_t chunkTimestampUs = 0;
187013aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nChunks = 0;
187113aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nZeroLengthFrames = 0;
1872965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastTimestampUs = 0;      // Previous sample time stamp
1873965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastDurationUs = 0;       // Between the previous two samples
1874965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t currDurationTicks = 0;    // Timescale based ticks
1875965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastDurationTicks = 0;    // Timescale based ticks
1876965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int32_t sampleCount = 1;          // Sample count in the current stts table entry
1877000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    uint32_t previousSampleSize = 0;  // Size of the previous sample
1878a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    int64_t previousPausedDurationUs = 0;
1879965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t timestampUs = 0;
1880000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t cttsOffsetTimeUs = 0;
1881000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t currCttsOffsetTimeTicks = 0;   // Timescale based ticks
1882000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t lastCttsOffsetTimeTicks = -1;  // Timescale based ticks
188343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    int32_t cttsSampleCount = 0;           // Sample count in the current ctts table entry
1884e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
1885a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    if (mIsAudio) {
1886a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong        prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0);
1887a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    } else {
1888a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong        prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0);
1889a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    }
189086106f8b0641444c97a39e9788eeef55ab2a2ac6Glenn Kasten    androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
1891985f838934510983d8a887461e98dca60a6e858fJames Dong
1892d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong    sp<MetaData> meta_data;
189320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1894ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    mNumSamples = 0;
189593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t err = OK;
189620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBuffer *buffer;
189793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    while (!mDone && (err = mSource->read(&buffer)) == OK) {
189820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (buffer->range_length() == 0) {
189920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer->release();
190020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer = NULL;
190113aec890216948b0c364f8f92792129d0335f506James Dong            ++nZeroLengthFrames;
190220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            continue;
190320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
190420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1905a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // If the codec specific data has not been received yet, delay pause.
1906a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // After the codec specific data is received, discard what we received
1907a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // when the track is to be paused.
1908a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused && !mResumed) {
1909a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer->release();
1910a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer = NULL;
1911a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            continue;
1912a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
1913a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
191430ab66297501757d745b9ae10da61adcd891f497Andreas Huber        ++count;
191530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
191603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        int32_t isCodecConfig;
191703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig)
191803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                && isCodecConfig) {
1919548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            CHECK(!mGotAllCodecSpecificData);
1920548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
19211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (mIsAvc) {
192203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                status_t err = makeAVCCodecSpecificData(
192303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        (const uint8_t *)buffer->data()
192403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                            + buffer->range_offset(),
192503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        buffer->range_length());
192643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                CHECK_EQ((status_t)OK, err);
19271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            } else if (mIsMPEG4) {
192803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificDataSize = buffer->range_length();
192903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificData = malloc(mCodecSpecificDataSize);
193003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                memcpy(mCodecSpecificData,
193103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        (const uint8_t *)buffer->data()
193203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                            + buffer->range_offset(),
193303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                       buffer->range_length());
193430ab66297501757d745b9ae10da61adcd891f497Andreas Huber            }
193530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
193630ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer->release();
193730ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer = NULL;
193830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
1939548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            mGotAllCodecSpecificData = true;
194030ab66297501757d745b9ae10da61adcd891f497Andreas Huber            continue;
1941a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
1942a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
1943d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // Make a deep copy of the MediaBuffer and Metadata and release
1944d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // the original as soon as we can
1945d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        MediaBuffer *copy = new MediaBuffer(buffer->range_length());
1946d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(),
1947d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong                buffer->range_length());
1948d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        copy->set_range(0, buffer->range_length());
1949d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data = new MetaData(*buffer->meta_data().get());
1950d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer->release();
1951d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer = NULL;
1952d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
19531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (mIsAvc) StripStartcode(copy);
1954e136c3bb38e88315bf8797a464ebf2c788296b22James Dong
1955b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        size_t sampleSize = copy->range_length();
1956b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        if (mIsAvc) {
1957b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            if (mOwner->useNalLengthFour()) {
1958b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                sampleSize += 4;
1959b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            } else {
1960b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                sampleSize += 2;
1961b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            }
1962b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        }
1963050b28a593350047845a45a14cc5026221ac1620James Dong
1964d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        // Max file size or duration handling
19651f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mMdatSizeBytes += sampleSize;
19661f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        updateTrackSizeEstimate();
19671f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1968d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileSizeLimit()) {
1969d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
1970d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
1971d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
1972d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileDurationLimit()) {
1973d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
1974d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
1975d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
1976d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1977050b28a593350047845a45a14cc5026221ac1620James Dong
1978d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        int32_t isSync = false;
1979d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data->findInt32(kKeyIsSyncFrame, &isSync);
1980d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        CHECK(meta_data->findInt64(kKeyTime, &timestampUs));
1981d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
1982d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong////////////////////////////////////////////////////////////////////////////////
198370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        if (mNumSamples == 0) {
198470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            mFirstSampleTimeRealUs = systemTime() / 1000;
1985f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mStartTimestampUs = timestampUs;
1986f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mOwner->setStartTimestampUs(mStartTimestampUs);
19878428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            previousPausedDurationUs = mStartTimestampUs;
19883c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        }
198948c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber
1990a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mResumed) {
19918428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs;
199243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            CHECK_GE(durExcludingEarlierPausesUs, 0ll);
19938428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs;
199443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            CHECK_GE(pausedDurationUs, lastDurationUs);
19958428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            previousPausedDurationUs += pausedDurationUs - lastDurationUs;
1996a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mResumed = false;
1997a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
1998a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
1999a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        timestampUs -= previousPausedDurationUs;
200043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_GE(timestampUs, 0ll);
2001000e18370baae60ffd9f25b509501dd8c26deabfJames Dong        if (!mIsAudio) {
2002965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            /*
2003965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             * Composition time: timestampUs
2004965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             * Decoding time: decodingTimeUs
2005000e18370baae60ffd9f25b509501dd8c26deabfJames Dong             * Composition time offset = composition time - decoding time
2006965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             */
2007965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            int64_t decodingTimeUs;
2008965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs));
2009965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            decodingTimeUs -= previousPausedDurationUs;
2010000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            cttsOffsetTimeUs =
2011000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs;
201243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            CHECK_GE(cttsOffsetTimeUs, 0ll);
2013965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            timestampUs = decodingTimeUs;
2014000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            ALOGV("decoding time: %lld and ctts offset time: %lld",
2015000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                timestampUs, cttsOffsetTimeUs);
2016000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2017000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            // Update ctts box table if necessary
2018000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            currCttsOffsetTimeTicks =
2019000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    (cttsOffsetTimeUs * mTimeScale + 500000LL) / 1000000LL;
202043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            CHECK_LE(currCttsOffsetTimeTicks, 0x0FFFFFFFFLL);
202143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            if (mNumSamples == 0) {
202243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // Force the first ctts table entry to have one single entry
202343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // so that we can do adjustment for the initial track start
202443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // time offset easily in writeCttsBox().
202543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks;
202643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                addOneCttsTableEntry(1, currCttsOffsetTimeTicks);
202743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                cttsSampleCount = 0;      // No sample in ctts box is pending
202843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            } else {
202943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                if (currCttsOffsetTimeTicks != lastCttsOffsetTimeTicks) {
203043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
203143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks;
203243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    cttsSampleCount = 1;  // One sample in ctts box is pending
203343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                } else {
203443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    ++cttsSampleCount;
203543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                }
203643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            }
2037000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2038000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            // Update ctts time offset range
2039000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            if (mNumSamples == 0) {
2040000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2041000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2042000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            } else {
2043000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                if (currCttsOffsetTimeTicks > mMaxCttsOffsetTimeUs) {
2044000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2045000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                } else if (currCttsOffsetTimeTicks < mMinCttsOffsetTimeUs) {
2046000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2047000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                }
2048000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            }
2049000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2050965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        }
2051872a481558350634a3fd5cb67939de288af00ecbJames Dong
2052872a481558350634a3fd5cb67939de288af00ecbJames Dong        if (mIsRealTimeRecording) {
2053872a481558350634a3fd5cb67939de288af00ecbJames Dong            if (mIsAudio) {
2054872a481558350634a3fd5cb67939de288af00ecbJames Dong                updateDriftTime(meta_data);
2055e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            }
2056e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        }
2057872a481558350634a3fd5cb67939de288af00ecbJames Dong
205843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_GE(timestampUs, 0ll);
20593856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("%s media time stamp: %lld and previous paused duration %lld",
20608428af5381e835cc783b7ecb0d71cb60961c99c2James Dong                mIsAudio? "Audio": "Video", timestampUs, previousPausedDurationUs);
2061c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong        if (timestampUs > mTrackDurationUs) {
2062c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong            mTrackDurationUs = timestampUs;
20633b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber        }
20643b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber
20655a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // We need to use the time scale based ticks, rather than the
20665a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // timestamp itself to determine whether we have to use a new
20675a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // stts entry, since we may have rounding errors.
20685a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // The calculation is intended to reduce the accumulated
20695a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // rounding errors.
20705a217fba010e801c255503602bda4b86ac5a6ac9James Dong        currDurationTicks =
20715a217fba010e801c255503602bda4b86ac5a6ac9James Dong            ((timestampUs * mTimeScale + 500000LL) / 1000000LL -
20725a217fba010e801c255503602bda4b86ac5a6ac9James Dong                (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL);
207343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_GE(currDurationTicks, 0ll);
20745a217fba010e801c255503602bda4b86ac5a6ac9James Dong
20758c460498c028888c533ab442be12b6d4b669b965James Dong        if ((mNumSamples % kSampleArraySize) == 0) {
20768c460498c028888c533ab442be12b6d4b669b965James Dong            uint32_t *arr = new uint32_t[kSampleArraySize];
20778c460498c028888c533ab442be12b6d4b669b965James Dong            CHECK(arr != NULL);
20788c460498c028888c533ab442be12b6d4b669b965James Dong            mSampleSizes.push_back(arr);
20798c460498c028888c533ab442be12b6d4b669b965James Dong            mCurrentSampleSizeArr = arr;
20808c460498c028888c533ab442be12b6d4b669b965James Dong        }
20818c460498c028888c533ab442be12b6d4b669b965James Dong
20828c460498c028888c533ab442be12b6d4b669b965James Dong        mCurrentSampleSizeArr[mNumSamples % kSampleArraySize] = htonl(sampleSize);
2083ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong        ++mNumSamples;
2084ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong        if (mNumSamples > 2) {
2085c059860c73678a202bfa33062723e8f82fb779d9James Dong
2086a472613aec322e25891abf5c77bf3f7e3c244920James Dong            // Force the first sample to have its own stts entry so that
2087a472613aec322e25891abf5c77bf3f7e3c244920James Dong            // we can adjust its value later to maintain the A/V sync.
2088a472613aec322e25891abf5c77bf3f7e3c244920James Dong            if (mNumSamples == 3 || currDurationTicks != lastDurationTicks) {
208979761ab096f57c3027fad9556c2bc436672d614eJames Dong                addOneSttsTableEntry(sampleCount, lastDurationTicks);
2090be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                sampleCount = 1;
2091be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            } else {
2092be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                ++sampleCount;
2093be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
2094965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2095be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
2096be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        if (mSamplesHaveSameSize) {
2097ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong            if (mNumSamples >= 2 && previousSampleSize != sampleSize) {
2098be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mSamplesHaveSameSize = false;
2099be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
21008644c14618d30d9e57a69df40ed939986ebf02c4James Dong            previousSampleSize = sampleSize;
2101be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
21023856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("%s timestampUs/lastTimestampUs: %lld/%lld",
2103a472613aec322e25891abf5c77bf3f7e3c244920James Dong                mIsAudio? "Audio": "Video", timestampUs, lastTimestampUs);
21048644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastDurationUs = timestampUs - lastTimestampUs;
2105c059860c73678a202bfa33062723e8f82fb779d9James Dong        lastDurationTicks = currDurationTicks;
21068644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastTimestampUs = timestampUs;
210720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2108d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        if (isSync != 0) {
21091f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            addOneStssTableEntry(mNumSamples);
2110d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        }
2111d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
211293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (mTrackingProgressStatus) {
211393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            if (mPreviousTrackTimeUs <= 0) {
211493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong                mPreviousTrackTimeUs = mStartTimestampUs;
211593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            }
2116faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong            trackProgressStatus(timestampUs);
211793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
211843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong        if (!hasMultipleTracks) {
2119c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t offset = mIsAvc? mOwner->addLengthPrefixedSample_l(copy)
212058ae9c530247668f8af36e30d228c716c226b3d4James Dong                                 : mOwner->addSample_l(copy);
212158ae9c530247668f8af36e30d228c716c226b3d4James Dong            if (mChunkOffsets.empty()) {
21221f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                addChunkOffset(offset);
212358ae9c530247668f8af36e30d228c716c226b3d4James Dong            }
212458ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy->release();
212558ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy = NULL;
212658ae9c530247668f8af36e30d228c716c226b3d4James Dong            continue;
212758ae9c530247668f8af36e30d228c716c226b3d4James Dong        }
212813aec890216948b0c364f8f92792129d0335f506James Dong
212913aec890216948b0c364f8f92792129d0335f506James Dong        mChunkSamples.push_back(copy);
213013aec890216948b0c364f8f92792129d0335f506James Dong        if (interleaveDurationUs == 0) {
21311f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            addOneStscTableEntry(++nChunks, 1);
21321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            bufferChunk(timestampUs);
213313aec890216948b0c364f8f92792129d0335f506James Dong        } else {
213413aec890216948b0c364f8f92792129d0335f506James Dong            if (chunkTimestampUs == 0) {
213513aec890216948b0c364f8f92792129d0335f506James Dong                chunkTimestampUs = timestampUs;
213613aec890216948b0c364f8f92792129d0335f506James Dong            } else {
213743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                int64_t chunkDurationUs = timestampUs - chunkTimestampUs;
213843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                if (chunkDurationUs > interleaveDurationUs) {
213943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    if (chunkDurationUs > mMaxChunkDurationUs) {
214043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                        mMaxChunkDurationUs = chunkDurationUs;
214143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    }
214213aec890216948b0c364f8f92792129d0335f506James Dong                    ++nChunks;
214313aec890216948b0c364f8f92792129d0335f506James Dong                    if (nChunks == 1 ||  // First chunk
214413aec890216948b0c364f8f92792129d0335f506James Dong                        (--(mStscTableEntries.end()))->samplesPerChunk !=
214513aec890216948b0c364f8f92792129d0335f506James Dong                         mChunkSamples.size()) {
21461f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                        addOneStscTableEntry(nChunks, mChunkSamples.size());
214713aec890216948b0c364f8f92792129d0335f506James Dong                    }
21481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                    bufferChunk(timestampUs);
214913aec890216948b0c364f8f92792129d0335f506James Dong                    chunkTimestampUs = timestampUs;
215013aec890216948b0c364f8f92792129d0335f506James Dong                }
215113aec890216948b0c364f8f92792129d0335f506James Dong            }
215213aec890216948b0c364f8f92792129d0335f506James Dong        }
215313aec890216948b0c364f8f92792129d0335f506James Dong
215420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
215525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
215645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    if (isTrackMalFormed()) {
2157690f546b0ee548dbfe997df36418e5302ec2d786James Dong        err = ERROR_MALFORMED;
2158f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong    }
215945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
2160bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    mOwner->trackProgressStatus(mTrackId, -1, err);
2161be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
216213aec890216948b0c364f8f92792129d0335f506James Dong    // Last chunk
216343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    if (!hasMultipleTracks) {
21641f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        addOneStscTableEntry(1, mNumSamples);
216558ae9c530247668f8af36e30d228c716c226b3d4James Dong    } else if (!mChunkSamples.empty()) {
21661f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        addOneStscTableEntry(++nChunks, mChunkSamples.size());
21671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        bufferChunk(timestampUs);
216813aec890216948b0c364f8f92792129d0335f506James Dong    }
216913aec890216948b0c364f8f92792129d0335f506James Dong
2170be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // We don't really know how long the last frame lasts, since
2171be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // there is no frame time after it, just repeat the previous
2172be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // frame's duration.
2173ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    if (mNumSamples == 1) {
21748f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        lastDurationUs = 0;  // A single sample's duration
217579761ab096f57c3027fad9556c2bc436672d614eJames Dong        lastDurationTicks = 0;
2176be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    } else {
2177be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        ++sampleCount;  // Count for the last sample
2178be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    }
2179a472613aec322e25891abf5c77bf3f7e3c244920James Dong
2180a472613aec322e25891abf5c77bf3f7e3c244920James Dong    if (mNumSamples <= 2) {
218179761ab096f57c3027fad9556c2bc436672d614eJames Dong        addOneSttsTableEntry(1, lastDurationTicks);
2182a472613aec322e25891abf5c77bf3f7e3c244920James Dong        if (sampleCount - 1 > 0) {
218379761ab096f57c3027fad9556c2bc436672d614eJames Dong            addOneSttsTableEntry(sampleCount - 1, lastDurationTicks);
2184a472613aec322e25891abf5c77bf3f7e3c244920James Dong        }
2185a472613aec322e25891abf5c77bf3f7e3c244920James Dong    } else {
218679761ab096f57c3027fad9556c2bc436672d614eJames Dong        addOneSttsTableEntry(sampleCount, lastDurationTicks);
2187a472613aec322e25891abf5c77bf3f7e3c244920James Dong    }
2188a472613aec322e25891abf5c77bf3f7e3c244920James Dong
218943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    // The last ctts box may not have been written yet, and this
219043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    // is to make sure that we write out the last ctts box.
219143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    if (currCttsOffsetTimeTicks == lastCttsOffsetTimeTicks) {
219243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        if (cttsSampleCount > 0) {
219343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
219443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        }
219543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    }
219643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong
2197c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs += lastDurationUs;
219825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = true;
219943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
220043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    sendTrackSummary(hasMultipleTracks);
220143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
2202df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s",
22031f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            count, nZeroLengthFrames, mNumSamples, mIsAudio? "audio": "video");
2204872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (mIsAudio) {
2205df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("Audio track drift time: %lld us", mOwner->getDriftTimeUs());
2206872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
2207365a963142093a1cd8efdcea76b5f65096a5b115James Dong
220837187916a486504acaf83bea30147eb5fbf46ae5James Dong    if (err == ERROR_END_OF_STREAM) {
220937187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
221037187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
221137187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
2212365a963142093a1cd8efdcea76b5f65096a5b115James Dong}
2213365a963142093a1cd8efdcea76b5f65096a5b115James Dong
221445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dongbool MPEG4Writer::Track::isTrackMalFormed() const {
221545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    if (mSampleSizes.empty()) {                      // no samples written
221629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("The number of recorded samples is 0");
221745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
221845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
221945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
222045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    if (!mIsAudio && mNumStssTableEntries == 0) {  // no sync frames for video
222129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("There are no sync frames for video track");
222245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
222345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
222445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
222545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    if (OK != checkCodecSpecificData()) {         // no codec specific data
222645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
222745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
222845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
222945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    return false;
223045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong}
223145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
223243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dongvoid MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) {
223307ec01904613a0bac32caaa8444b4690998faed7James Dong
223407ec01904613a0bac32caaa8444b4690998faed7James Dong    // Send track summary only if test mode is enabled.
223507ec01904613a0bac32caaa8444b4690998faed7James Dong    if (!isTestModeEnabled()) {
223607ec01904613a0bac32caaa8444b4690998faed7James Dong        return;
223707ec01904613a0bac32caaa8444b4690998faed7James Dong    }
223807ec01904613a0bac32caaa8444b4690998faed7James Dong
223943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    int trackNum = (mTrackId << 28);
224043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
224143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
224243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_TYPE,
224343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mIsAudio? 0: 1);
224443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
224543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
224643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_DURATION_MS,
224743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mTrackDurationUs / 1000);
224843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
224943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
225043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES,
225143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mNumSamples);
225243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
225386b7f47aa7482424cf8fd248f1315311919be3b0James Dong    {
225486b7f47aa7482424cf8fd248f1315311919be3b0James Dong        // The system delay time excluding the requested initial delay that
225586b7f47aa7482424cf8fd248f1315311919be3b0James Dong        // is used to eliminate the recording sound.
225686b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL;
225786b7f47aa7482424cf8fd248f1315311919be3b0James Dong        if (startTimeOffsetUs < 0) {  // Start time offset was not set
225886b7f47aa7482424cf8fd248f1315311919be3b0James Dong            startTimeOffsetUs = kInitialDelayTimeUs;
225986b7f47aa7482424cf8fd248f1315311919be3b0James Dong        }
226086b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t initialDelayUs =
226186b7f47aa7482424cf8fd248f1315311919be3b0James Dong            mFirstSampleTimeRealUs - mStartTimeRealUs - startTimeOffsetUs;
226286b7f47aa7482424cf8fd248f1315311919be3b0James Dong
226386b7f47aa7482424cf8fd248f1315311919be3b0James Dong        mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
226470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS,
226570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    (initialDelayUs) / 1000);
226686b7f47aa7482424cf8fd248f1315311919be3b0James Dong    }
226770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
226807ec01904613a0bac32caaa8444b4690998faed7James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
226907ec01904613a0bac32caaa8444b4690998faed7James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES,
227007ec01904613a0bac32caaa8444b4690998faed7James Dong                    mMdatSizeBytes / 1024);
227107ec01904613a0bac32caaa8444b4690998faed7James Dong
227243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    if (hasMultipleTracks) {
227343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong        mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
227443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS,
227543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mMaxChunkDurationUs / 1000);
227670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
227770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
227870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        if (mStartTimestampUs != moovStartTimeUs) {
227970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            int64_t startTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
228070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
228170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS,
228270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    startTimeOffsetUs / 1000);
228370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        }
228443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    }
228543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong}
228643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
2287faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) {
22883856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("trackProgressStatus: %lld us", timeUs);
2289215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    if (mTrackEveryTimeDurationUs > 0 &&
2290215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) {
22913856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("Fire time tracking progress status at %lld us", timeUs);
2292bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err);
229393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        mPreviousTrackTimeUs = timeUs;
229493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
229593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
229693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
2297faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::trackProgressStatus(
2298bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        size_t trackId, int64_t timeUs, status_t err) {
2299faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    Mutex::Autolock lock(mLock);
2300bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    int32_t trackNum = (trackId << 28);
2301faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
2302faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Error notification
2303faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Do not consider ERROR_END_OF_STREAM an error
2304faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (err != OK && err != ERROR_END_OF_STREAM) {
2305bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_ERROR,
2306bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL,
2307faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
2308faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        return;
2309faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
2310faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
2311faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (timeUs == -1) {
2312faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send completion notification
2313bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
2314bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS,
2315faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
2316faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    } else {
2317faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send progress status
2318bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
2319bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME,
2320faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               timeUs / 1000);
2321faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
2322faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong}
2323faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
2324d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dongvoid MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) {
23253856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setDriftTimeUs: %lld us", driftTimeUs);
2326e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
2327d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong    mDriftTimeUs = driftTimeUs;
2328e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
2329e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
2330e259531ce59ab1f31de5a23124b22536f6a5a767James Dongint64_t MPEG4Writer::getDriftTimeUs() {
23313856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("getDriftTimeUs: %lld us", mDriftTimeUs);
2332e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
2333e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    return mDriftTimeUs;
2334e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
2335e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
2336b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dongbool MPEG4Writer::useNalLengthFour() {
2337b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    return mUse4ByteNalLength;
2338b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong}
2339b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong
23401c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::Track::bufferChunk(int64_t timestampUs) {
23413856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("bufferChunk");
23421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
23431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Chunk chunk(this, timestampUs, mChunkSamples);
23441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mOwner->bufferChunk(chunk);
234513aec890216948b0c364f8f92792129d0335f506James Dong    mChunkSamples.clear();
234620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
234720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
23483b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const {
2349c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    return mTrackDurationUs;
235020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
235120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2352d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const {
2353d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return mEstimatedTrackSizeBytes;
2354d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
2355d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
2356690f546b0ee548dbfe997df36418e5302ec2d786James Dongstatus_t MPEG4Writer::Track::checkCodecSpecificData() const {
2357690f546b0ee548dbfe997df36418e5302ec2d786James Dong    const char *mime;
2358690f546b0ee548dbfe997df36418e5302ec2d786James Dong    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
2359690f546b0ee548dbfe997df36418e5302ec2d786James Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) ||
2360690f546b0ee548dbfe997df36418e5302ec2d786James Dong        !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) ||
2361690f546b0ee548dbfe997df36418e5302ec2d786James Dong        !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
2362690f546b0ee548dbfe997df36418e5302ec2d786James Dong        if (!mCodecSpecificData ||
2363690f546b0ee548dbfe997df36418e5302ec2d786James Dong            mCodecSpecificDataSize <= 0) {
236429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Missing codec specific data");
2365690f546b0ee548dbfe997df36418e5302ec2d786James Dong            return ERROR_MALFORMED;
2366690f546b0ee548dbfe997df36418e5302ec2d786James Dong        }
2367690f546b0ee548dbfe997df36418e5302ec2d786James Dong    } else {
2368690f546b0ee548dbfe997df36418e5302ec2d786James Dong        if (mCodecSpecificData ||
2369690f546b0ee548dbfe997df36418e5302ec2d786James Dong            mCodecSpecificDataSize > 0) {
237029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Unexepected codec specific data found");
2371690f546b0ee548dbfe997df36418e5302ec2d786James Dong            return ERROR_MALFORMED;
2372690f546b0ee548dbfe997df36418e5302ec2d786James Dong        }
2373690f546b0ee548dbfe997df36418e5302ec2d786James Dong    }
2374690f546b0ee548dbfe997df36418e5302ec2d786James Dong    return OK;
2375690f546b0ee548dbfe997df36418e5302ec2d786James Dong}
2376690f546b0ee548dbfe997df36418e5302ec2d786James Dong
2377b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeTrackHeader(bool use32BitOffset) {
237820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
23793856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("%s track time scale: %d",
23801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsAudio? "Audio": "Video", mTimeScale);
23818f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
238220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    time_t now = time(NULL);
2383b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("trak");
2384b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeTkhdBox(now);
2385b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->beginBox("mdia");
2386b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            writeMdhdBox(now);
2387b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            writeHdlrBox();
2388b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            mOwner->beginBox("minf");
2389b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                if (mIsAudio) {
2390b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                    writeSmhdBox();
2391b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                } else {
2392b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                    writeVmhdBox();
2393b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                }
2394b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                writeDinfBox();
2395b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                writeStblBox(use32BitOffset);
2396b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            mOwner->endBox();  // minf
2397b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->endBox();  // mdia
2398b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // trak
2399b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2400b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2401b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStblBox(bool use32BitOffset) {
2402b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stbl");
2403b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsd");
2404b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);               // version=0, flags=0
2405b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);               // entry count
2406b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mIsAudio) {
2407b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeAudioFourCCBox();
2408b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
2409b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeVideoFourCCBox();
2410b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2411b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsd
2412b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeSttsBox();
2413965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    writeCttsBox();
2414b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!mIsAudio) {
2415b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeStssBox();
2416b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2417b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStszBox();
2418b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStscBox();
2419b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStcoBox(use32BitOffset);
2420b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stbl
2421b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2422b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2423b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVideoFourCCBox() {
2424b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    const char *mime;
2425b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    bool success = mMeta->findCString(kKeyMIMEType, &mime);
2426b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
2427b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
2428b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->beginBox("mp4v");
2429b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
2430b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->beginBox("s263");
2431b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
2432b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->beginBox("avc1");
2433b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
243429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Unknown mime type '%s'.", mime);
2435b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        CHECK(!"should not be here, unknown mime type.");
2436b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2437b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2438b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2439b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2440b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(1);           // data ref index
2441b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // predefined
2442b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2443b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
2444b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
2445b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
2446b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2447b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t width, height;
2448b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = mMeta->findInt32(kKeyWidth, &width);
2449b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = success && mMeta->findInt32(kKeyHeight, &height);
2450b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
2451b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2452b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(width);
2453b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(height);
2454b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x480000);    // horiz resolution
2455b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x480000);    // vert resolution
2456b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2457b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(1);           // frame count
2458b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write("                                ", 32);
2459b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x18);        // depth
2460b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(-1);          // predefined
2461b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
246243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_LT(23 + mCodecSpecificDataSize, 128);
2463b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2464b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
2465b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeMp4vEsdsBox();
2466b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
2467b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeD263Box();
2468b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
2469b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeAvccBox();
2470b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2471b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2472b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writePaspBox();
2473b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // mp4v, s263 or avc1
2474b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2475b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2476b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAudioFourCCBox() {
2477b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    const char *mime;
2478b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    bool success = mMeta->findCString(kKeyMIMEType, &mime);
2479b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
2480b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    const char *fourcc = NULL;
2481b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) {
2482b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        fourcc = "samr";
2483b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
2484b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        fourcc = "sawb";
2485b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
2486b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        fourcc = "mp4a";
2487b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
248829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Unknown mime type '%s'.", mime);
2489b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        CHECK(!"should not be here, unknown mime type.");
2490b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2491b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2492b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox(fourcc);        // audio format
2493b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2494b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2495b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x1);         // data ref index
2496b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2497b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2498b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t nChannels;
2499b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels));
2500b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(nChannels);   // channel count
2501b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(16);          // sample size
2502b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // predefined
2503b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2504b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2505b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t samplerate;
2506b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = mMeta->findInt32(kKeySampleRate, &samplerate);
2507b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
2508b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(samplerate << 16);
2509b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
2510b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeMp4aEsdsBox();
2511b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) ||
2512b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong               !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
2513b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeDamrBox();
2514b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2515b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2516b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2517b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2518b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4aEsdsBox() {
2519b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("esds");
2520b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
252143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mCodecSpecificDataSize, 0);
2522b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2523b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Make sure all sizes encode to a single byte.
252443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_LT(mCodecSpecificDataSize + 23, 128);
2525b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2526b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);     // version=0, flags=0
2527b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x03);   // ES_DescrTag
2528b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(23 + mCodecSpecificDataSize);
2529b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x0000);// ES_ID
2530b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x00);
2531b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2532b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x04);   // DecoderConfigDescrTag
2533b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(15 + mCodecSpecificDataSize);
2534b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x40);   // objectTypeIndication ISO/IEC 14492-2
2535b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x15);   // streamType AudioStream
2536b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2537b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x03);  // XXX
2538b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x00);   // buffer size 24-bit
2539b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(96000); // max bit rate
2540b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(96000); // avg bit rate
2541b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2542b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x05);   // DecoderSpecificInfoTag
2543b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(mCodecSpecificDataSize);
2544b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
2545b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2546b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData2[] = {
2547b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x06,  // SLConfigDescriptorTag
2548b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x01,
2549b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x02
2550b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
2551b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData2, sizeof(kData2));
2552b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2553b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // esds
2554b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2555b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2556b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4vEsdsBox() {
2557b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
255843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mCodecSpecificDataSize, 0);
2559b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("esds");
2560b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2561b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);    // version=0, flags=0
2562b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2563b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x03);  // ES_DescrTag
2564b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(23 + mCodecSpecificDataSize);
2565b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x0000);  // ES_ID
2566b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x1f);
2567b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2568b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x04);  // DecoderConfigDescrTag
2569b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(15 + mCodecSpecificDataSize);
2570b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x20);  // objectTypeIndication ISO/IEC 14492-2
2571b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x11);  // streamType VisualStream
2572b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2573b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData[] = {
2574b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x01, 0x77, 0x00,
2575b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x00, 0x03, 0xe8, 0x00,
2576b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x00, 0x03, 0xe8, 0x00
2577b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
2578b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData, sizeof(kData));
2579b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2580b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x05);  // DecoderSpecificInfoTag
2581b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2582b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(mCodecSpecificDataSize);
2583b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
2584b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2585b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData2[] = {
2586b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x06,  // SLConfigDescriptorTag
2587b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x01,
2588b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x02
2589b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
2590b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData2, sizeof(kData2));
2591b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2592b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // esds
2593b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2594b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2595b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeTkhdBox(time_t now) {
2596b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("tkhd");
2597b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Flags = 7 to indicate that the track is enabled, and
2598b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // part of the presentation
2599b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x07);          // version=0, flags=7
2600b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // creation time
2601b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // modification time
2602b5212db69734962f55e1493d3e696794172ced51James Dong    mOwner->writeInt32(mTrackId + 1);  // track id starts with 1
2603b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
26048f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t trakDurationUs = getDurationUs();
2605b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t mvhdTimeScale = mOwner->getTimeScale();
2606b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t tkhdDuration =
2607b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
2608b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(tkhdDuration);  // in mvhd timescale
2609b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
2610b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
2611b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // layer
2612b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // alternate group
2613b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(mIsAudio ? 0x100 : 0);  // volume
2614b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // reserved
2615b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2616b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCompositionMatrix(mRotation);       // matrix
261720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2618b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mIsAudio) {
2619b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(0);
2620b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(0);
2621b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
2622b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        int32_t width, height;
2623b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        bool success = mMeta->findInt32(kKeyWidth, &width);
2624b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        success = success && mMeta->findInt32(kKeyHeight, &height);
2625b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        CHECK(success);
2626b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2627b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(width << 16);   // 32-bit fixed-point value
2628b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(height << 16);  // 32-bit fixed-point value
2629b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2630b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // tkhd
2631b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2632b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2633b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVmhdBox() {
2634b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("vmhd");
2635b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x01);        // version=0, flags=1
2636b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // graphics mode
2637b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // opcolor
2638b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);
2639b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);
2640b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2641b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2642b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2643b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeSmhdBox() {
2644b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("smhd");
2645b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // version=0, flags=0
2646b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // balance
2647b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2648b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2649b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2650b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2651b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeHdlrBox() {
2652b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("hdlr");
2653b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // version=0, flags=0
2654b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // component type: should be mhlr
2655b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeFourcc(mIsAudio ? "soun" : "vide");  // component subtype
2656b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
2657b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
2658b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
2659b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Removing "r" for the name string just makes the string 4 byte aligned
2660b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle");  // name
2661b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2662b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2663b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2664b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMdhdBox(time_t now) {
2665b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int64_t trakDurationUs = getDurationUs();
2666b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("mdhd");
2667b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // version=0, flags=0
2668b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // creation time
2669b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // modification time
2670b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(mTimeScale);    // media timescale
2671b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6;
2672b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(mdhdDuration);  // use media timescale
2673b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Language follows the three letter standard ISO-639-2/T
2674b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // 'e', 'n', 'g' for "English", for instance.
2675b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Each character is packed as the difference between its ASCII value and 0x60.
2676b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // For "English", these are 00101, 01110, 00111.
2677b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // XXX: Where is the padding bit located: 0x15C7?
2678b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // language code
2679b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // predefined
2680b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2681b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2682b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2683b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDamrBox() {
2684b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // 3gpp2 Spec AMRSampleEntry fields
2685b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("damr");
2686b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCString("   ");  // vendor: 4 bytes
2687b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);         // decoder version
2688b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x83FF);   // mode set: all enabled
2689b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);         // mode change period
2690b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(1);         // frames per sample
2691b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2692b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2693b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2694b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeUrlBox() {
2695b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // The table index here refers to the sample description index
2696b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // in the sample table entries.
2697b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("url ");
2698b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);  // version=0, flags=1 (self-contained)
2699b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // url
2700b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2701b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2702b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDrefBox() {
2703b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("dref");
2704b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
2705b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);  // entry count (either url or urn)
2706b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeUrlBox();
2707b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // dref
2708b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2709b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2710b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDinfBox() {
2711b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("dinf");
2712b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeDrefBox();
2713b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // dinf
2714b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2715b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2716b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAvccBox() {
2717b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
271843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GE(mCodecSpecificDataSize, 5);
2719b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2720b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Patch avcc's lengthSize field to match the number
2721b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // of bytes we use to indicate the size of a nal unit.
2722b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    uint8_t *ptr = (uint8_t *)mCodecSpecificData;
2723b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    ptr[4] = (ptr[4] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1);
2724b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("avcC");
2725b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
2726b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // avcC
2727b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2728b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2729b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeD263Box() {
2730b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("d263");
2731b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // vendor
2732b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);   // decoder version
2733b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(10);  // level: 10
2734b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);   // profile: 0
2735b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // d263
2736b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2737b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2738b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong// This is useful if the pixel is not square
2739b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writePaspBox() {
2740b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("pasp");
2741b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1 << 16);  // hspacing
2742b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1 << 16);  // vspacing
2743b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // pasp
2744b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2745b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2746000e18370baae60ffd9f25b509501dd8c26deabfJames Dongint32_t MPEG4Writer::Track::getStartTimeOffsetScaledTime() const {
2747a472613aec322e25891abf5c77bf3f7e3c244920James Dong    int64_t trackStartTimeOffsetUs = 0;
2748b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
2749b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mStartTimestampUs != moovStartTimeUs) {
275043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_GT(mStartTimestampUs, moovStartTimeUs);
2751b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        trackStartTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
2752b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2753000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    return (trackStartTimeOffsetUs *  mTimeScale + 500000LL) / 1000000LL;
2754000e18370baae60ffd9f25b509501dd8c26deabfJames Dong}
2755000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2756000e18370baae60ffd9f25b509501dd8c26deabfJames Dongvoid MPEG4Writer::Track::writeSttsBox() {
2757000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->beginBox("stts");
2758000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
2759000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->writeInt32(mNumSttsTableEntries);
2760000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2761000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    // Compensate for small start time difference from different media tracks
276279761ab096f57c3027fad9556c2bc436672d614eJames Dong    List<SttsTableEntry>::iterator it = mSttsTableEntries.begin();
276379761ab096f57c3027fad9556c2bc436672d614eJames Dong    CHECK(it != mSttsTableEntries.end() && it->sampleCount == 1);
276479761ab096f57c3027fad9556c2bc436672d614eJames Dong    mOwner->writeInt32(it->sampleCount);
2765000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->writeInt32(getStartTimeOffsetScaledTime() + it->sampleDuration);
2766a472613aec322e25891abf5c77bf3f7e3c244920James Dong
2767965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t totalCount = 1;
276879761ab096f57c3027fad9556c2bc436672d614eJames Dong    while (++it != mSttsTableEntries.end()) {
276979761ab096f57c3027fad9556c2bc436672d614eJames Dong        mOwner->writeInt32(it->sampleCount);
277079761ab096f57c3027fad9556c2bc436672d614eJames Dong        mOwner->writeInt32(it->sampleDuration);
2771965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        totalCount += it->sampleCount;
2772b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
277343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_EQ(totalCount, mNumSamples);
2774b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stts
2775b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
277620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2777965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::writeCttsBox() {
2778965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    if (mIsAudio) {  // ctts is not for audio
2779965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
2780965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
2781965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2782000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    // There is no B frame at all
2783000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    if (mMinCttsOffsetTimeUs == mMaxCttsOffsetTimeUs) {
2784000e18370baae60ffd9f25b509501dd8c26deabfJames Dong        return;
2785000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    }
2786000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2787965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    // Do not write ctts box when there is no need to have it.
2788965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    if ((mNumCttsTableEntries == 1 &&
2789965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        mCttsTableEntries.begin()->sampleDuration == 0) ||
2790965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        mNumCttsTableEntries == 0) {
2791965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
2792965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
2793965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2794000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    ALOGD("ctts box has %d entries with range [%lld, %lld]",
2795000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            mNumCttsTableEntries, mMinCttsOffsetTimeUs, mMaxCttsOffsetTimeUs);
2796965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2797965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mOwner->beginBox("ctts");
2798000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    // Version 1 allows to use negative offset time value, but
2799000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    // we are sticking to version 0 for now.
2800000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
2801965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mOwner->writeInt32(mNumCttsTableEntries);
2802965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2803000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    // Compensate for small start time difference from different media tracks
2804000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    List<CttsTableEntry>::iterator it = mCttsTableEntries.begin();
2805000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    CHECK(it != mCttsTableEntries.end() && it->sampleCount == 1);
2806000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->writeInt32(it->sampleCount);
2807000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->writeInt32(getStartTimeOffsetScaledTime() +
2808000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            it->sampleDuration - mMinCttsOffsetTimeUs);
2809000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2810000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t totalCount = 1;
2811000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    while (++it != mCttsTableEntries.end()) {
2812965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        mOwner->writeInt32(it->sampleCount);
2813000e18370baae60ffd9f25b509501dd8c26deabfJames Dong        mOwner->writeInt32(it->sampleDuration - mMinCttsOffsetTimeUs);
2814965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        totalCount += it->sampleCount;
2815965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
281643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_EQ(totalCount, mNumSamples);
2817965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mOwner->endBox();  // ctts
2818965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong}
2819965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2820b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStssBox() {
2821b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stss");
2822b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
2823b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(mNumStssTableEntries);  // number of sync frames
2824b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    for (List<int32_t>::iterator it = mStssTableEntries.begin();
2825b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        it != mStssTableEntries.end(); ++it) {
2826b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(*it);
2827b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2828b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stss
2829b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
283025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
2831b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStszBox() {
28328c460498c028888c533ab442be12b6d4b669b965James Dong    ALOGD("writeStszBox for %s track", isAudio()? "Audio": "Video");
2833b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsz");
2834b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
2835b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mSamplesHaveSameSize) {
283649fcd3cc0c0bf352c5c0516e53805278e94951caJames Dong        CHECK(mCurrentSampleSizeArr != 0);
283749fcd3cc0c0bf352c5c0516e53805278e94951caJames Dong        mOwner->write(mCurrentSampleSizeArr, 4, 1);  // default sample size
2838b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
2839b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(0);
2840b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2841b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(mNumSamples);
28428c460498c028888c533ab442be12b6d4b669b965James Dong    uint32_t nSamples = mNumSamples;
2843b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!mSamplesHaveSameSize) {
28448c460498c028888c533ab442be12b6d4b669b965James Dong        for (List<uint32_t *>::iterator it = mSampleSizes.begin();
2845b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            it != mSampleSizes.end(); ++it) {
28468c460498c028888c533ab442be12b6d4b669b965James Dong            if (nSamples >= kSampleArraySize) {
28478c460498c028888c533ab442be12b6d4b669b965James Dong                mOwner->write(*it, 4, kSampleArraySize);
28488c460498c028888c533ab442be12b6d4b669b965James Dong                nSamples -= kSampleArraySize;
28498c460498c028888c533ab442be12b6d4b669b965James Dong            } else {
28508c460498c028888c533ab442be12b6d4b669b965James Dong                mOwner->write(*it, 4, nSamples);
28518c460498c028888c533ab442be12b6d4b669b965James Dong                break;
28528c460498c028888c533ab442be12b6d4b669b965James Dong            }
2853b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        }
2854b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2855b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsz
28568c460498c028888c533ab442be12b6d4b669b965James Dong    ALOGD("writeStszBox: X");
2857b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
285820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2859b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStscBox() {
2860b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsc");
2861b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
2862b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(mNumStscTableEntries);
2863b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    for (List<StscTableEntry>::iterator it = mStscTableEntries.begin();
2864b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        it != mStscTableEntries.end(); ++it) {
2865b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(it->firstChunk);
2866b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(it->samplesPerChunk);
2867b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(it->sampleDescriptionId);
2868b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2869b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsc
2870b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
287120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2872b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) {
2873b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox(use32BitOffset? "stco": "co64");
2874b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
2875b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(mNumStcoTableEntries);
2876b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    for (List<off64_t>::iterator it = mChunkOffsets.begin();
2877b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        it != mChunkOffsets.end(); ++it) {
2878b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        if (use32BitOffset) {
2879b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            mOwner->writeInt32(static_cast<int32_t>(*it));
2880b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        } else {
2881b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            mOwner->writeInt64((*it));
2882b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        }
2883b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2884b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stco or co64
288520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
288620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
288707b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeUdtaBox() {
288807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    beginBox("udta");
288907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeGeoDataBox();
289007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    endBox();
289107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
289207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
289307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/*
289407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard.
289507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */
289607b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeGeoDataBox() {
289707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    beginBox("\xA9xyz");
289807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    /*
289907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * For historical reasons, any user data start
290007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * with "\0xA9", must be followed by its assoicated
290107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * language code.
2902432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong     * 0x0012: text string length
2903432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong     * 0x15c7: lang (locale) code: en
290407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     */
290507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeInt32(0x001215c7);
290607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeLatitude(mLatitudex10000);
290707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeLongitude(mLongitudex10000);
290807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeInt8(0x2F);
290907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    endBox();
291007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
291107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
291220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
2913