MPEG4Writer.cpp revision 5f995b0e72ed6f186cb0ab2a525c4cfce614f3a9
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>
25a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong#include <sys/resource.h>
2620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MPEG4Writer.h>
2820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBuffer.h>
2920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h>
300c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber#include <media/stagefright/MediaDebug.h>
3118291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h>
3203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#include <media/stagefright/MediaErrors.h>
3320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaSource.h>
3420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/Utils.h>
35d599cd4573b5a2d5914c5040e0565ef866749b77James Dong#include <media/mediarecorder.h>
3620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber#include "include/ESDS.h"
3819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
3920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android {
4020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
411f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongstatic const int64_t kMax32BitFileSize = 0x007fffffffLL;
423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypeSeqParamSet = 0x07;
433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypePicParamSet = 0x08;
44872a481558350634a3fd5cb67939de288af00ecbJames Dongstatic const int64_t kVideoMediaTimeAdjustPeriodTimeUs = 10000000LL;  // 10s
453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
4620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Writer::Track {
4720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic:
4825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    Track(MPEG4Writer *owner, const sp<MediaSource> &source);
498f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
5020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    ~Track();
5120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t start(MetaData *params);
5337187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t stop();
5437187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t pause();
5525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool reachedEOS();
5620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
573b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber    int64_t getDurationUs() const;
58d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t getEstimatedTrackSizeBytes() const;
591acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    void writeTrackHeader(int32_t trackID, bool use32BitOffset = true);
601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void bufferChunk(int64_t timestampUs);
611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isAvc() const { return mIsAvc; }
621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isAudio() const { return mIsAudio; }
631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isMPEG4() const { return mIsMPEG4; }
641f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void addChunkOffset(off_t offset);
65dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    status_t dump(int fd, const Vector<String16>& args) const;
6620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate:
6820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Writer *mOwner;
6920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MetaData> mMeta;
70693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    sp<MediaSource> mSource;
7120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    volatile bool mDone;
72a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mPaused;
73a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mResumed;
741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAvc;
751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAudio;
761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsMPEG4;
77c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    int64_t mTrackDurationUs;
78e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
79e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    // For realtime applications, we need to adjust the media clock
80e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    // for video track based on the audio media clock
81e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    bool mIsRealTimeRecording;
82e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    int64_t mMaxTimeStampUs;
83d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t mEstimatedTrackSizeBytes;
841f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    int64_t mMdatSizeBytes;
858f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int32_t mTimeScale;
8620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_t mThread;
8820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
89ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    // mNumSamples is used to track how many samples in mSampleSizes List.
90ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    // This is to reduce the cost associated with mSampleSizes.size() call,
91ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    // since it is O(n). Ideally, the fix should be in List class.
92ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    size_t              mNumSamples;
938644c14618d30d9e57a69df40ed939986ebf02c4James Dong    List<size_t>        mSampleSizes;
94be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    bool                mSamplesHaveSameSize;
95be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
9613aec890216948b0c364f8f92792129d0335f506James Dong    List<MediaBuffer *> mChunkSamples;
971f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
981f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    size_t              mNumStcoTableEntries;
9913aec890216948b0c364f8f92792129d0335f506James Dong    List<off_t>         mChunkOffsets;
10013aec890216948b0c364f8f92792129d0335f506James Dong
1011f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    size_t              mNumStscTableEntries;
10213aec890216948b0c364f8f92792129d0335f506James Dong    struct StscTableEntry {
10313aec890216948b0c364f8f92792129d0335f506James Dong
10413aec890216948b0c364f8f92792129d0335f506James Dong        StscTableEntry(uint32_t chunk, uint32_t samples, uint32_t id)
10513aec890216948b0c364f8f92792129d0335f506James Dong            : firstChunk(chunk),
10613aec890216948b0c364f8f92792129d0335f506James Dong              samplesPerChunk(samples),
10713aec890216948b0c364f8f92792129d0335f506James Dong              sampleDescriptionId(id) {}
10813aec890216948b0c364f8f92792129d0335f506James Dong
10913aec890216948b0c364f8f92792129d0335f506James Dong        uint32_t firstChunk;
11013aec890216948b0c364f8f92792129d0335f506James Dong        uint32_t samplesPerChunk;
11113aec890216948b0c364f8f92792129d0335f506James Dong        uint32_t sampleDescriptionId;
11213aec890216948b0c364f8f92792129d0335f506James Dong    };
11313aec890216948b0c364f8f92792129d0335f506James Dong    List<StscTableEntry> mStscTableEntries;
11420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1151f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    size_t        mNumStssTableEntries;
116050b28a593350047845a45a14cc5026221ac1620James Dong    List<int32_t> mStssTableEntries;
117050b28a593350047845a45a14cc5026221ac1620James Dong
1181f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    size_t        mNumSttsTableEntries;
119be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    struct SttsTableEntry {
120be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
1218f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        SttsTableEntry(uint32_t count, uint32_t durationUs)
1228f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            : sampleCount(count), sampleDurationUs(durationUs) {}
123be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
124be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        uint32_t sampleCount;
1258f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        uint32_t sampleDurationUs;
126be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    };
127be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    List<SttsTableEntry> mSttsTableEntries;
128be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
1293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Sequence parameter set or picture parameter set
1303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    struct AVCParamSet {
1313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        AVCParamSet(uint16_t length, const uint8_t *data)
1323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            : mLength(length), mData(data) {}
1333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
1343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t mLength;
1353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *mData;
1363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    };
1373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    List<AVCParamSet> mSeqParamSets;
1383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    List<AVCParamSet> mPicParamSets;
1393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mProfileIdc;
1403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mProfileCompatible;
1413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mLevelIdc;
1423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
14320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *mCodecSpecificData;
14420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t mCodecSpecificDataSize;
145548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    bool mGotAllCodecSpecificData;
14693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    bool mTrackingProgressStatus;
14720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool mReachedEOS;
1493c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    int64_t mStartTimestampUs;
15093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mPreviousTrackTimeUs;
15193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mTrackEveryTimeDurationUs;
15225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
153872a481558350634a3fd5cb67939de288af00ecbJames Dong    // Has the media time adjustment for video started?
154872a481558350634a3fd5cb67939de288af00ecbJames Dong    bool    mIsMediaTimeAdjustmentOn;
155872a481558350634a3fd5cb67939de288af00ecbJames Dong    // The time stamp when previous media time adjustment period starts
156872a481558350634a3fd5cb67939de288af00ecbJames Dong    int64_t mPrevMediaTimeAdjustTimestampUs;
157872a481558350634a3fd5cb67939de288af00ecbJames Dong    // Number of vidoe frames whose time stamp may be adjusted
158872a481558350634a3fd5cb67939de288af00ecbJames Dong    int64_t mMediaTimeAdjustNumFrames;
159872a481558350634a3fd5cb67939de288af00ecbJames Dong    // The sample number when previous meida time adjustmnet period starts
160872a481558350634a3fd5cb67939de288af00ecbJames Dong    int64_t mPrevMediaTimeAdjustSample;
161872a481558350634a3fd5cb67939de288af00ecbJames Dong    // The total accumulated drift time within a period of
162872a481558350634a3fd5cb67939de288af00ecbJames Dong    // kVideoMediaTimeAdjustPeriodTimeUs.
163872a481558350634a3fd5cb67939de288af00ecbJames Dong    int64_t mTotalDriftTimeToAdjustUs;
164872a481558350634a3fd5cb67939de288af00ecbJames Dong    // The total accumalated drift time since the start of the recording
165872a481558350634a3fd5cb67939de288af00ecbJames Dong    // excluding the current time adjustment period
166872a481558350634a3fd5cb67939de288af00ecbJames Dong    int64_t mPrevTotalAccumDriftTimeUs;
167872a481558350634a3fd5cb67939de288af00ecbJames Dong
168872a481558350634a3fd5cb67939de288af00ecbJames Dong    // Update the audio track's drift information.
169872a481558350634a3fd5cb67939de288af00ecbJames Dong    void updateDriftTime(const sp<MetaData>& meta);
170872a481558350634a3fd5cb67939de288af00ecbJames Dong
171872a481558350634a3fd5cb67939de288af00ecbJames Dong    // Adjust the time stamp of the video track according to
172872a481558350634a3fd5cb67939de288af00ecbJames Dong    // the drift time information from the audio track.
173872a481558350634a3fd5cb67939de288af00ecbJames Dong    void adjustMediaTime(int64_t *timestampUs);
174872a481558350634a3fd5cb67939de288af00ecbJames Dong
17520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    static void *ThreadWrapper(void *me);
17637187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t threadEntry();
17720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *parseParamSet(
1793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen);
1803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
18103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    status_t makeAVCCodecSpecificData(
18203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            const uint8_t *data, size_t size);
1833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    status_t copyAVCCodecSpecificData(
1843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            const uint8_t *data, size_t size);
1853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    status_t parseAVCCodecSpecificData(
1863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            const uint8_t *data, size_t size);
187215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong
188215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    // Track authoring progress status
189faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    void trackProgressStatus(int64_t timeUs, status_t err = OK);
19093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    void initTrackingProgressStatus(MetaData *params);
19103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
19219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    void getCodecSpecificDataFromInputFormatIfPossible();
19319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
194c059860c73678a202bfa33062723e8f82fb779d9James Dong    // Determine the track time scale
195c059860c73678a202bfa33062723e8f82fb779d9James Dong    // If it is an audio track, try to use the sampling rate as
196c059860c73678a202bfa33062723e8f82fb779d9James Dong    // the time scale; however, if user chooses the overwrite
197c059860c73678a202bfa33062723e8f82fb779d9James Dong    // value, the user-supplied time scale will be used.
198c059860c73678a202bfa33062723e8f82fb779d9James Dong    void setTimeScale();
199c059860c73678a202bfa33062723e8f82fb779d9James Dong
200690f546b0ee548dbfe997df36418e5302ec2d786James Dong    // Simple validation on the codec specific data
201690f546b0ee548dbfe997df36418e5302ec2d786James Dong    status_t checkCodecSpecificData() const;
202690f546b0ee548dbfe997df36418e5302ec2d786James Dong
2031f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void updateTrackSizeEstimate();
2041f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void addOneStscTableEntry(size_t chunkId, size_t sampleId);
2051f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void addOneStssTableEntry(size_t sampleId);
2061f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void addOneSttsTableEntry(size_t sampleCount, int64_t durationUs);
2071f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
20820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track(const Track &);
20920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track &operator=(const Track &);
21020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
21120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
21220111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::MPEG4Writer(const char *filename)
21320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mFile(fopen(filename, "wb")),
214b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong      mUse4ByteNalLength(true),
2151acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong      mUse32BitOffset(true),
216a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong      mIsFileSizeLimitExplicitlyRequested(false),
217a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
218a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mStarted(false),
21920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOffset(0),
22013aec890216948b0c364f8f92792129d0335f506James Dong      mMdatOffset(0),
2217837c17063a4c50bc856ba59418516fdab731de7James Dong      mEstimatedMoovBoxSize(0),
222f01528f435e6b1f02d118fcd8305a148c27a89f1James Dong      mInterleaveDurationUs(1000000) {
2230c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(mFile != NULL);
22420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
22520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
22630ab66297501757d745b9ae10da61adcd891f497Andreas HuberMPEG4Writer::MPEG4Writer(int fd)
22730ab66297501757d745b9ae10da61adcd891f497Andreas Huber    : mFile(fdopen(fd, "wb")),
228b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong      mUse4ByteNalLength(true),
2291acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong      mUse32BitOffset(true),
230a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong      mIsFileSizeLimitExplicitlyRequested(false),
231a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
232a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mStarted(false),
23330ab66297501757d745b9ae10da61adcd891f497Andreas Huber      mOffset(0),
23413aec890216948b0c364f8f92792129d0335f506James Dong      mMdatOffset(0),
2357837c17063a4c50bc856ba59418516fdab731de7James Dong      mEstimatedMoovBoxSize(0),
236f01528f435e6b1f02d118fcd8305a148c27a89f1James Dong      mInterleaveDurationUs(1000000) {
23730ab66297501757d745b9ae10da61adcd891f497Andreas Huber    CHECK(mFile != NULL);
23830ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
23930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
24020111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() {
24120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    stop();
24220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2431f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    while (!mTracks.empty()) {
2441f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        List<Track *>::iterator it = mTracks.begin();
24520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        delete *it;
2461f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        (*it) = NULL;
2471f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mTracks.erase(it);
24820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
24920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.clear();
25020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
25120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
252dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::dump(
253dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        int fd, const Vector<String16>& args) {
254dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    const size_t SIZE = 256;
255dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    char buffer[SIZE];
256dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    String8 result;
257dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "   MPEG4Writer %p\n", this);
258dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
259dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "     mStarted: %s\n", mStarted? "true": "false");
260dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
261dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    ::write(fd, result.string(), result.size());
262dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    for (List<Track *>::iterator it = mTracks.begin();
263dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong         it != mTracks.end(); ++it) {
264dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        (*it)->dump(fd, args);
265dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    }
266dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    return OK;
267dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong}
268dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong
269dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::Track::dump(
270dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        int fd, const Vector<String16>& args) const {
271dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    const size_t SIZE = 256;
272dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    char buffer[SIZE];
273dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    String8 result;
274dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "     %s track\n", mIsAudio? "Audio": "Video");
275dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
276dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "       reached EOS: %s\n",
277dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong            mReachedEOS? "true": "false");
278dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
279dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    ::write(fd, result.string(), result.size());
280dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    return OK;
281dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong}
282dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong
2832dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huberstatus_t MPEG4Writer::addSource(const sp<MediaSource> &source) {
28425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    Track *track = new Track(this, source);
28520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.push_back(track);
2862dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
2872dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    return OK;
28820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
28920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
29093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::startTracks(MetaData *params) {
291a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
292a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
29393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        status_t err = (*it)->start(params);
294a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
295a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (err != OK) {
296a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            for (List<Track *>::iterator it2 = mTracks.begin();
297a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                 it2 != it; ++it2) {
298a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                (*it2)->stop();
299a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            }
300a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
301a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            return err;
302a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
303a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
304a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    return OK;
305a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
306a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
3072dec2b5be2056c6d9428897dc672185872d30d17James Dongint64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) {
3082dec2b5be2056c6d9428897dc672185872d30d17James Dong    // This implementation is highly experimental/heurisitic.
3092dec2b5be2056c6d9428897dc672185872d30d17James Dong    //
3102dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Statistical analysis shows that metadata usually accounts
3112dec2b5be2056c6d9428897dc672185872d30d17James Dong    // for a small portion of the total file size, usually < 0.6%.
3122dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Currently, lets set to 0.4% for now.
3132dec2b5be2056c6d9428897dc672185872d30d17James Dong
3142dec2b5be2056c6d9428897dc672185872d30d17James Dong    // The default MIN_MOOV_BOX_SIZE is set to 0.4% x 1MB,
3152dec2b5be2056c6d9428897dc672185872d30d17James Dong    // where 1MB is the common file size limit for MMS application.
3162dec2b5be2056c6d9428897dc672185872d30d17James Dong    // The default MAX _MOOV_BOX_SIZE value is based on about 4
3172dec2b5be2056c6d9428897dc672185872d30d17James Dong    // minute video recording with a bit rate about 3 Mbps, because
3182dec2b5be2056c6d9428897dc672185872d30d17James Dong    // statistics also show that most of the video captured are going
3192dec2b5be2056c6d9428897dc672185872d30d17James Dong    // to be less than 3 minutes.
3202dec2b5be2056c6d9428897dc672185872d30d17James Dong
3212dec2b5be2056c6d9428897dc672185872d30d17James Dong    // If the estimation is wrong, we will pay the price of wasting
3222dec2b5be2056c6d9428897dc672185872d30d17James Dong    // some reserved space. This should not happen so often statistically.
3232dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int32_t factor = mUse32BitOffset? 1: 2;
3242dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int64_t MIN_MOOV_BOX_SIZE = 4 * 1024;  // 4 KB
3252dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000);
3262dec2b5be2056c6d9428897dc672185872d30d17James Dong    int64_t size = MIN_MOOV_BOX_SIZE;
3272dec2b5be2056c6d9428897dc672185872d30d17James Dong
328a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
3292dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = mMaxFileSizeLimitBytes * 4 / 1000;
3302dec2b5be2056c6d9428897dc672185872d30d17James Dong    } else if (mMaxFileDurationLimitUs != 0) {
3312dec2b5be2056c6d9428897dc672185872d30d17James Dong        if (bitRate <= 0) {
3322dec2b5be2056c6d9428897dc672185872d30d17James Dong            // We could not estimate the file size since bitRate is not set.
3332dec2b5be2056c6d9428897dc672185872d30d17James Dong            size = MIN_MOOV_BOX_SIZE;
3342dec2b5be2056c6d9428897dc672185872d30d17James Dong        } else {
3352dec2b5be2056c6d9428897dc672185872d30d17James Dong            size = ((mMaxFileDurationLimitUs * bitRate * 4) / 1000 / 8000000);
3362dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
3372dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
3382dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size < MIN_MOOV_BOX_SIZE) {
3392dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MIN_MOOV_BOX_SIZE;
3402dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
3412dec2b5be2056c6d9428897dc672185872d30d17James Dong
3422dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Any long duration recording will be probably end up with
3432dec2b5be2056c6d9428897dc672185872d30d17James Dong    // non-streamable mp4 file.
3442dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size > MAX_MOOV_BOX_SIZE) {
3452dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MAX_MOOV_BOX_SIZE;
3462dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
3472dec2b5be2056c6d9428897dc672185872d30d17James Dong
348a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    LOGI("limits: %lld/%lld bytes/us, bit rate: %d bps and the estimated"
3492dec2b5be2056c6d9428897dc672185872d30d17James Dong         " moov size %lld bytes",
3502dec2b5be2056c6d9428897dc672185872d30d17James Dong         mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size);
3512dec2b5be2056c6d9428897dc672185872d30d17James Dong    return factor * size;
3522dec2b5be2056c6d9428897dc672185872d30d17James Dong}
3532dec2b5be2056c6d9428897dc672185872d30d17James Dong
3542dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t MPEG4Writer::start(MetaData *param) {
35520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mFile == NULL) {
35625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return UNKNOWN_ERROR;
35720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
35820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
359a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    /*
360a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * Check mMaxFileSizeLimitBytes at the beginning
361a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * since mMaxFileSizeLimitBytes may be implicitly
362a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * changed later for 32-bit file offset even if
363a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * user does not ask to set it explicitly.
364a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     */
365a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    if (mMaxFileSizeLimitBytes != 0) {
366a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong        mIsFileSizeLimitExplicitlyRequested = true;
367a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    }
368a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong
3692dec2b5be2056c6d9428897dc672185872d30d17James Dong    int32_t use64BitOffset;
3702dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (param &&
3712dec2b5be2056c6d9428897dc672185872d30d17James Dong        param->findInt32(kKey64BitFileOffset, &use64BitOffset) &&
3722dec2b5be2056c6d9428897dc672185872d30d17James Dong        use64BitOffset) {
3732dec2b5be2056c6d9428897dc672185872d30d17James Dong        mUse32BitOffset = false;
3742dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
3752dec2b5be2056c6d9428897dc672185872d30d17James Dong
3761f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    if (mUse32BitOffset) {
3771f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // Implicit 32 bit file size limit
3781f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        if (mMaxFileSizeLimitBytes == 0) {
3791f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            mMaxFileSizeLimitBytes = kMax32BitFileSize;
3801f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        }
3811f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
3821f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // If file size is set to be larger than the 32 bit file
3831f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // size limit, treat it as an error.
3841f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        if (mMaxFileSizeLimitBytes > kMax32BitFileSize) {
385872a481558350634a3fd5cb67939de288af00ecbJames Dong            LOGW("32-bit file size limit (%lld bytes) too big. "
386d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong                 "It is changed to %lld bytes",
387d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong                mMaxFileSizeLimitBytes, kMax32BitFileSize);
388d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong            mMaxFileSizeLimitBytes = kMax32BitFileSize;
3891f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        }
3901f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    }
3911f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
392b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    int32_t use2ByteNalLength;
393b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (param &&
394b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        param->findInt32(kKey2ByteNalLength, &use2ByteNalLength) &&
395b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        use2ByteNalLength) {
396b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mUse4ByteNalLength = false;
3972dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
3982dec2b5be2056c6d9428897dc672185872d30d17James Dong
399065d1aff96818df54456053f1574aec8a234d0deJames Dong    mStartTimestampUs = -1;
40093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
401a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (mStarted) {
402a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused) {
403a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mPaused = false;
40493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            return startTracks(param);
405a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
406a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
407a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
408a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
4098f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    if (!param ||
4108f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        !param->findInt32(kKeyTimeScale, &mTimeScale)) {
4118f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        mTimeScale = 1000;
4128f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    }
4138f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    CHECK(mTimeScale > 0);
4148f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    LOGV("movie time scale: %d", mTimeScale);
4158f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
4167837c17063a4c50bc856ba59418516fdab731de7James Dong    mStreamableFile = true;
4177837c17063a4c50bc856ba59418516fdab731de7James Dong    mWriteMoovBoxToMemory = false;
4187837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBuffer = NULL;
4197837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
4207837c17063a4c50bc856ba59418516fdab731de7James Dong
42120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    beginBox("ftyp");
42293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong      {
42393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        int32_t fileType;
42493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (param && param->findInt32(kKeyFileType, &fileType) &&
42593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            fileType != OUTPUT_FORMAT_MPEG_4) {
42693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            writeFourcc("3gp4");
42793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        } else {
42893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            writeFourcc("isom");
42993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
43093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong      }
43120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      writeInt32(0);
43220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      writeFourcc("isom");
43393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong      writeFourcc("3gp4");
43420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    endBox();
43520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4367837c17063a4c50bc856ba59418516fdab731de7James Dong    mFreeBoxOffset = mOffset;
43720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4387837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mEstimatedMoovBoxSize == 0) {
4392dec2b5be2056c6d9428897dc672185872d30d17James Dong        int32_t bitRate = -1;
4402dec2b5be2056c6d9428897dc672185872d30d17James Dong        if (param) {
4412dec2b5be2056c6d9428897dc672185872d30d17James Dong            param->findInt32(kKeyBitRate, &bitRate);
4422dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
4432dec2b5be2056c6d9428897dc672185872d30d17James Dong        mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate);
4447837c17063a4c50bc856ba59418516fdab731de7James Dong    }
4457837c17063a4c50bc856ba59418516fdab731de7James Dong    CHECK(mEstimatedMoovBoxSize >= 8);
4467837c17063a4c50bc856ba59418516fdab731de7James Dong    fseeko(mFile, mFreeBoxOffset, SEEK_SET);
4477837c17063a4c50bc856ba59418516fdab731de7James Dong    writeInt32(mEstimatedMoovBoxSize);
4487837c17063a4c50bc856ba59418516fdab731de7James Dong    write("free", 4);
4497837c17063a4c50bc856ba59418516fdab731de7James Dong
4507837c17063a4c50bc856ba59418516fdab731de7James Dong    mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize;
4517837c17063a4c50bc856ba59418516fdab731de7James Dong    mOffset = mMdatOffset;
4527837c17063a4c50bc856ba59418516fdab731de7James Dong    fseeko(mFile, mMdatOffset, SEEK_SET);
4531acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
4541acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("????mdat", 8);
4551acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
4561acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("\x00\x00\x00\x01mdat????????", 16);
4571acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
4581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
4591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    status_t err = startWriterThread();
4601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (err != OK) {
4611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        return err;
4621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
4631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
4641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    err = startTracks(param);
465a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (err != OK) {
466a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return err;
46720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
4681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
469a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mStarted = true;
47025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
47120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
47220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4731f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongbool MPEG4Writer::use32BitFileOffset() const {
4741f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    return mUse32BitOffset;
4751f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
4761f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
47737187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::pause() {
478a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (mFile == NULL) {
47937187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
480a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
481a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
48237187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = OK;
483a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
484a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
48537187916a486504acaf83bea30147eb5fbf46ae5James Dong        status_t status = (*it)->pause();
48637187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (status != OK) {
48737187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
48837187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
489a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
49037187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
491a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
492a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
4931c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::stopWriterThread() {
4941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("stopWriterThread");
4951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
4961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    {
4971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        Mutex::Autolock autolock(mLock);
4981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
4991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mDone = true;
5001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkReadyCondition.signal();
5011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
5021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
5031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void *dummy;
5041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_join(mThread, &dummy);
5051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
5061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
50737187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::stop() {
50820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mFile == NULL) {
50937187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
51020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
51120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
51237187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = OK;
5138f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t maxDurationUs = 0;
51420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
51520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber         it != mTracks.end(); ++it) {
51637187916a486504acaf83bea30147eb5fbf46ae5James Dong        status_t status = (*it)->stop();
51737187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (err == OK && status != OK) {
51837187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
51937187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
52020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5218f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int64_t durationUs = (*it)->getDurationUs();
5228f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        if (durationUs > maxDurationUs) {
5238f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            maxDurationUs = durationUs;
52420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
52520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
52620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    stopWriterThread();
5287837c17063a4c50bc856ba59418516fdab731de7James Dong
52937187916a486504acaf83bea30147eb5fbf46ae5James Dong    // Do not write out movie header on error.
53037187916a486504acaf83bea30147eb5fbf46ae5James Dong    if (err != OK) {
53137187916a486504acaf83bea30147eb5fbf46ae5James Dong        fflush(mFile);
53237187916a486504acaf83bea30147eb5fbf46ae5James Dong        fclose(mFile);
53337187916a486504acaf83bea30147eb5fbf46ae5James Dong        mFile = NULL;
53437187916a486504acaf83bea30147eb5fbf46ae5James Dong        mStarted = false;
53537187916a486504acaf83bea30147eb5fbf46ae5James Dong        return err;
53637187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
53737187916a486504acaf83bea30147eb5fbf46ae5James Dong
53820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // Fix up the size of the 'mdat' chunk.
5391acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
5401acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        fseeko(mFile, mMdatOffset, SEEK_SET);
5411acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        int32_t size = htonl(static_cast<int32_t>(mOffset - mMdatOffset));
5421acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        fwrite(&size, 1, 4, mFile);
5431acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
5441acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        fseeko(mFile, mMdatOffset + 8, SEEK_SET);
5451acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        int64_t size = mOffset - mMdatOffset;
5461acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        size = hton64(size);
5471acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        fwrite(&size, 1, 8, mFile);
5481acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
5497837c17063a4c50bc856ba59418516fdab731de7James Dong    fseeko(mFile, mOffset, SEEK_SET);
55020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
55120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    time_t now = time(NULL);
5527837c17063a4c50bc856ba59418516fdab731de7James Dong    const off_t moovOffset = mOffset;
5537837c17063a4c50bc856ba59418516fdab731de7James Dong    mWriteMoovBoxToMemory = true;
5547837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize);
5557837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
5567837c17063a4c50bc856ba59418516fdab731de7James Dong    CHECK(mMoovBoxBuffer != NULL);
557c059860c73678a202bfa33062723e8f82fb779d9James Dong    int32_t duration = (maxDurationUs * mTimeScale + 5E5) / 1E6;
55820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
55920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    beginBox("moov");
56020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
56120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      beginBox("mvhd");
56220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // version=0, flags=0
56320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(now);           // creation time
56420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(now);           // modification time
5658f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        writeInt32(mTimeScale);    // mvhd timescale
5661acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        writeInt32(duration);
5671acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        writeInt32(0x10000);       // rate: 1.0
56820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt16(0x100);         // volume
56920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt16(0);             // reserved
57020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // reserved
57120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // reserved
57220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0x10000);       // matrix
57320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
57420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
57520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
57620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0x10000);
57720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
57820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
57920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
58020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0x40000000);
58120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
58220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
58320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
58420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
58520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
58620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
58720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(mTracks.size() + 1);  // nextTrackID
58820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      endBox();  // mvhd
58920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
59020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      int32_t id = 1;
59120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      for (List<Track *>::iterator it = mTracks.begin();
59220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber           it != mTracks.end(); ++it, ++id) {
5931acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          (*it)->writeTrackHeader(id, mUse32BitOffset);
59420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      }
59520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    endBox();  // moov
59620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5977837c17063a4c50bc856ba59418516fdab731de7James Dong    mWriteMoovBoxToMemory = false;
5987837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mStreamableFile) {
5997837c17063a4c50bc856ba59418516fdab731de7James Dong        CHECK(mMoovBoxBufferOffset + 8 <= mEstimatedMoovBoxSize);
6007837c17063a4c50bc856ba59418516fdab731de7James Dong
6017837c17063a4c50bc856ba59418516fdab731de7James Dong        // Moov box
6027837c17063a4c50bc856ba59418516fdab731de7James Dong        fseeko(mFile, mFreeBoxOffset, SEEK_SET);
6037837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset = mFreeBoxOffset;
6047837c17063a4c50bc856ba59418516fdab731de7James Dong        write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, mFile);
6057837c17063a4c50bc856ba59418516fdab731de7James Dong
6067837c17063a4c50bc856ba59418516fdab731de7James Dong        // Free box
6072dec2b5be2056c6d9428897dc672185872d30d17James Dong        fseeko(mFile, mOffset, SEEK_SET);
6087837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset);
6097837c17063a4c50bc856ba59418516fdab731de7James Dong        write("free", 4);
6107837c17063a4c50bc856ba59418516fdab731de7James Dong
6117837c17063a4c50bc856ba59418516fdab731de7James Dong        // Free temp memory
6127837c17063a4c50bc856ba59418516fdab731de7James Dong        free(mMoovBoxBuffer);
6137837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBuffer = NULL;
6147837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBufferOffset = 0;
6152dec2b5be2056c6d9428897dc672185872d30d17James Dong    } else {
6162dec2b5be2056c6d9428897dc672185872d30d17James Dong        LOGI("The mp4 file will not be streamable.");
6177837c17063a4c50bc856ba59418516fdab731de7James Dong    }
6187837c17063a4c50bc856ba59418516fdab731de7James Dong
6190c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(mBoxes.empty());
62020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6217837c17063a4c50bc856ba59418516fdab731de7James Dong    fflush(mFile);
62220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fclose(mFile);
62320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mFile = NULL;
624a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mStarted = false;
62537187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
62620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
62720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
62813aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) {
62913aec890216948b0c364f8f92792129d0335f506James Dong    mInterleaveDurationUs = durationUs;
63013aec890216948b0c364f8f92792129d0335f506James Dong    return OK;
63113aec890216948b0c364f8f92792129d0335f506James Dong}
63213aec890216948b0c364f8f92792129d0335f506James Dong
63313aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() {
63413aec890216948b0c364f8f92792129d0335f506James Dong    mLock.lock();
63513aec890216948b0c364f8f92792129d0335f506James Dong}
63613aec890216948b0c364f8f92792129d0335f506James Dong
63713aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() {
63813aec890216948b0c364f8f92792129d0335f506James Dong    mLock.unlock();
63913aec890216948b0c364f8f92792129d0335f506James Dong}
64020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
64113aec890216948b0c364f8f92792129d0335f506James Dongoff_t MPEG4Writer::addSample_l(MediaBuffer *buffer) {
64220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    off_t old_offset = mOffset;
64320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
64420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fwrite((const uint8_t *)buffer->data() + buffer->range_offset(),
64520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber           1, buffer->range_length(), mFile);
64620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
64720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += buffer->range_length();
64820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
64920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return old_offset;
65020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
65120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
65203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) {
65303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (buffer->range_length() < 4) {
65403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return;
65503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
65603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
65703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    const uint8_t *ptr =
65803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        (const uint8_t *)buffer->data() + buffer->range_offset();
65903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
66003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) {
66103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        buffer->set_range(
66203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                buffer->range_offset() + 4, buffer->range_length() - 4);
66303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
66403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
66503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
66613aec890216948b0c364f8f92792129d0335f506James Dongoff_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) {
66730ab66297501757d745b9ae10da61adcd891f497Andreas Huber    off_t old_offset = mOffset;
66830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
66930ab66297501757d745b9ae10da61adcd891f497Andreas Huber    size_t length = buffer->range_length();
67003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
671b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (mUse4ByteNalLength) {
672b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        uint8_t x = length >> 24;
673b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        fwrite(&x, 1, 1, mFile);
674b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = (length >> 16) & 0xff;
675b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        fwrite(&x, 1, 1, mFile);
676b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = (length >> 8) & 0xff;
677b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        fwrite(&x, 1, 1, mFile);
678b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = length & 0xff;
679b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        fwrite(&x, 1, 1, mFile);
680b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong
681b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        fwrite((const uint8_t *)buffer->data() + buffer->range_offset(),
682b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                1, length, mFile);
683b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mOffset += length + 4;
684b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    } else {
685b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        CHECK(length < 65536);
68630ab66297501757d745b9ae10da61adcd891f497Andreas Huber
687b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        uint8_t x = length >> 8;
688b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        fwrite(&x, 1, 1, mFile);
689b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = length & 0xff;
690b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        fwrite(&x, 1, 1, mFile);
691b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        fwrite((const uint8_t *)buffer->data() + buffer->range_offset(),
692b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                1, length, mFile);
693b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mOffset += length + 2;
694b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    }
69530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
69630ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return old_offset;
69730ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
69830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
6997837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write(
7007837c17063a4c50bc856ba59418516fdab731de7James Dong        const void *ptr, size_t size, size_t nmemb, FILE *stream) {
7017837c17063a4c50bc856ba59418516fdab731de7James Dong
7027837c17063a4c50bc856ba59418516fdab731de7James Dong    const size_t bytes = size * nmemb;
7037837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
7041acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        off_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes;
7051acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        if (moovBoxSize > mEstimatedMoovBoxSize) {
7067837c17063a4c50bc856ba59418516fdab731de7James Dong            for (List<off_t>::iterator it = mBoxes.begin();
7077837c17063a4c50bc856ba59418516fdab731de7James Dong                 it != mBoxes.end(); ++it) {
7087837c17063a4c50bc856ba59418516fdab731de7James Dong                (*it) += mOffset;
7097837c17063a4c50bc856ba59418516fdab731de7James Dong            }
7107837c17063a4c50bc856ba59418516fdab731de7James Dong            fseeko(mFile, mOffset, SEEK_SET);
7117837c17063a4c50bc856ba59418516fdab731de7James Dong            fwrite(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, stream);
7127837c17063a4c50bc856ba59418516fdab731de7James Dong            fwrite(ptr, size, nmemb, stream);
7137837c17063a4c50bc856ba59418516fdab731de7James Dong            mOffset += (bytes + mMoovBoxBufferOffset);
7147837c17063a4c50bc856ba59418516fdab731de7James Dong            free(mMoovBoxBuffer);
7157837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBuffer = NULL;
7167837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset = 0;
7177837c17063a4c50bc856ba59418516fdab731de7James Dong            mWriteMoovBoxToMemory = false;
7187837c17063a4c50bc856ba59418516fdab731de7James Dong            mStreamableFile = false;
7197837c17063a4c50bc856ba59418516fdab731de7James Dong        } else {
7207837c17063a4c50bc856ba59418516fdab731de7James Dong            memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes);
7217837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset += bytes;
7227837c17063a4c50bc856ba59418516fdab731de7James Dong        }
7237837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
7247837c17063a4c50bc856ba59418516fdab731de7James Dong        fwrite(ptr, size, nmemb, stream);
7257837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset += bytes;
7267837c17063a4c50bc856ba59418516fdab731de7James Dong    }
7277837c17063a4c50bc856ba59418516fdab731de7James Dong    return bytes;
7287837c17063a4c50bc856ba59418516fdab731de7James Dong}
7297837c17063a4c50bc856ba59418516fdab731de7James Dong
73020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) {
7310c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(fourcc), 4);
73220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7337837c17063a4c50bc856ba59418516fdab731de7James Dong    mBoxes.push_back(mWriteMoovBoxToMemory?
7347837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset: mOffset);
73520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
73620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeInt32(0);
73720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeFourcc(fourcc);
73820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
73920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
74020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() {
7410c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(!mBoxes.empty());
74220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
74320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    off_t offset = *--mBoxes.end();
74420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mBoxes.erase(--mBoxes.end());
74520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7467837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
7477837c17063a4c50bc856ba59418516fdab731de7James Dong       int32_t x = htonl(mMoovBoxBufferOffset - offset);
7487837c17063a4c50bc856ba59418516fdab731de7James Dong       memcpy(mMoovBoxBuffer + offset, &x, 4);
7497837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
7507837c17063a4c50bc856ba59418516fdab731de7James Dong        fseeko(mFile, offset, SEEK_SET);
7517837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mOffset - offset);
7527837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset -= 4;
7537837c17063a4c50bc856ba59418516fdab731de7James Dong        fseeko(mFile, mOffset, SEEK_SET);
7547837c17063a4c50bc856ba59418516fdab731de7James Dong    }
75520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
75620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
75720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) {
7587837c17063a4c50bc856ba59418516fdab731de7James Dong    write(&x, 1, 1, mFile);
75920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
76020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
76120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) {
76220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htons(x);
7637837c17063a4c50bc856ba59418516fdab731de7James Dong    write(&x, 1, 2, mFile);
76420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
76520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
76620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) {
76720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htonl(x);
7687837c17063a4c50bc856ba59418516fdab731de7James Dong    write(&x, 1, 4, mFile);
76920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
77020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
77120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) {
77220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = hton64(x);
7737837c17063a4c50bc856ba59418516fdab731de7James Dong    write(&x, 1, 8, mFile);
77420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
77520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
77620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) {
77720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t n = strlen(s);
7787837c17063a4c50bc856ba59418516fdab731de7James Dong    write(s, 1, n + 1, mFile);
77920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
78020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
78120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) {
7820c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(s), 4);
7837837c17063a4c50bc856ba59418516fdab731de7James Dong    write(s, 1, 4, mFile);
78420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
78520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
78620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) {
7877837c17063a4c50bc856ba59418516fdab731de7James Dong    write(data, 1, size, mFile);
78820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
78920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
790d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() {
791d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
792d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileSizeLimitBytes == 0) {
793d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
794d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
795d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
796956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize);
797d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
798d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
799d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes();
800d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
8011f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
8021f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    return (nTotalBytesEstimate  + 1024 >= mMaxFileSizeLimitBytes);
803d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
804d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
805d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() {
806d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
807d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileDurationLimitUs == 0) {
808d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
809d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
810d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
811d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
812d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
813d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) {
814d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            return true;
815d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
816d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
817d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return false;
818d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
819d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
82025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() {
82125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool allDone = true;
82225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
82325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber         it != mTracks.end(); ++it) {
82425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        if (!(*it)->reachedEOS()) {
82525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            allDone = false;
82625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            break;
82725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        }
82825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
82925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
83025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return allDone;
83125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
83225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
833f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) {
834f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    LOGI("setStartTimestampUs: %lld", timeUs);
835f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    CHECK(timeUs >= 0);
8363c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
837065d1aff96818df54456053f1574aec8a234d0deJames Dong    if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) {
838f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mStartTimestampUs = timeUs;
839f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        LOGI("Earliest track starting time: %lld", mStartTimestampUs);
8403c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    }
8413c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
8423c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
843f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() {
8443c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
8453c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    return mStartTimestampUs;
8463c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
8473c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
84858ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() {
84958ae9c530247668f8af36e30d228c716c226b3d4James Dong    Mutex::Autolock autolock(mLock);
85058ae9c530247668f8af36e30d228c716c226b3d4James Dong    return mTracks.size();
85158ae9c530247668f8af36e30d228c716c226b3d4James Dong}
85258ae9c530247668f8af36e30d228c716c226b3d4James Dong
85320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
85420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
85520111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track(
85625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        MPEG4Writer *owner, const sp<MediaSource> &source)
85720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mOwner(owner),
85825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mMeta(source->getFormat()),
85920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSource(source),
86020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDone(false),
861a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
862a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mResumed(false),
863c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong      mTrackDurationUs(0),
864956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      mEstimatedTrackSizeBytes(0),
865be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong      mSamplesHaveSameSize(true),
86620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCodecSpecificData(NULL),
86725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mCodecSpecificDataSize(0),
868548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber      mGotAllCodecSpecificData(false),
86925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mReachedEOS(false) {
87019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    getCodecSpecificDataFromInputFormatIfPossible();
8718f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
8721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    const char *mime;
8731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mMeta->findCString(kKeyMIMEType, &mime);
8741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
8751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAudio = !strncasecmp(mime, "audio/", 6);
8761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
8771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong               !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC);
8781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
879c059860c73678a202bfa33062723e8f82fb779d9James Dong    setTimeScale();
880c059860c73678a202bfa33062723e8f82fb779d9James Dong}
881c059860c73678a202bfa33062723e8f82fb779d9James Dong
8821f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::updateTrackSizeEstimate() {
8831f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
8841f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    int64_t stcoBoxSizeBytes = mOwner->use32BitFileOffset()
8851f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                                ? mNumStcoTableEntries * 4
8861f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                                : mNumStcoTableEntries * 8;
8871f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
8881f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mNumSamples * 4);
8891f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
8901f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mEstimatedTrackSizeBytes = mMdatSizeBytes +             // media data size
8911f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                               mNumStscTableEntries * 12 +  // stsc box size
8921f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                               mNumStssTableEntries * 4 +   // stss box size
8931f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                               mNumSttsTableEntries * 8 +   // stts box size
8941f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                               stcoBoxSizeBytes +           // stco box size
8951f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                               stszBoxSizeBytes;            // stsz box size
8961f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
8971f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
8981f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStscTableEntry(
8991f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        size_t chunkId, size_t sampleId) {
9001f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
9011f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        StscTableEntry stscEntry(chunkId, sampleId, 1);
9021f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mStscTableEntries.push_back(stscEntry);
9031f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        ++mNumStscTableEntries;
9041f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
9051f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
9061f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) {
9071f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mStssTableEntries.push_back(sampleId);
9081f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    ++mNumStssTableEntries;
9091f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
9101f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
9111f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneSttsTableEntry(
9121f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        size_t sampleCount, int64_t durationUs) {
9131f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
9141f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    SttsTableEntry sttsEntry(sampleCount, durationUs);
9151f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mSttsTableEntries.push_back(sttsEntry);
9161f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    ++mNumSttsTableEntries;
9171f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
9181f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
9191f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addChunkOffset(off_t offset) {
9201f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    ++mNumStcoTableEntries;
9211f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mChunkOffsets.push_back(offset);
9221f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
9231f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
924c059860c73678a202bfa33062723e8f82fb779d9James Dongvoid MPEG4Writer::Track::setTimeScale() {
925c059860c73678a202bfa33062723e8f82fb779d9James Dong    LOGV("setTimeScale");
926c059860c73678a202bfa33062723e8f82fb779d9James Dong    // Default time scale
927c059860c73678a202bfa33062723e8f82fb779d9James Dong    mTimeScale = 90000;
928c059860c73678a202bfa33062723e8f82fb779d9James Dong
929c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mIsAudio) {
930c059860c73678a202bfa33062723e8f82fb779d9James Dong        // Use the sampling rate as the default time scale for audio track.
931c059860c73678a202bfa33062723e8f82fb779d9James Dong        int32_t sampleRate;
932c059860c73678a202bfa33062723e8f82fb779d9James Dong        bool success = mMeta->findInt32(kKeySampleRate, &sampleRate);
933c059860c73678a202bfa33062723e8f82fb779d9James Dong        CHECK(success);
934c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = sampleRate;
935c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
936c059860c73678a202bfa33062723e8f82fb779d9James Dong
937c059860c73678a202bfa33062723e8f82fb779d9James Dong    // If someone would like to overwrite the timescale, use user-supplied value.
938c059860c73678a202bfa33062723e8f82fb779d9James Dong    int32_t timeScale;
939c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mMeta->findInt32(kKeyTimeScale, &timeScale)) {
940c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = timeScale;
941c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
942c059860c73678a202bfa33062723e8f82fb779d9James Dong
9438f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    CHECK(mTimeScale > 0);
94419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber}
94519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
94619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Hubervoid MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() {
94719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    const char *mime;
94819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
94919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
95019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
95119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        uint32_t type;
95219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        const void *data;
95319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        size_t size;
95419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        if (mMeta->findData(kKeyAVCC, &type, &data, &size)) {
95519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mCodecSpecificData = malloc(size);
95619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mCodecSpecificDataSize = size;
95719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            memcpy(mCodecSpecificData, data, size);
95819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mGotAllCodecSpecificData = true;
95919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        }
96019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
96119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
96219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        uint32_t type;
96319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        const void *data;
96419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        size_t size;
96519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        if (mMeta->findData(kKeyESDS, &type, &data, &size)) {
96619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            ESDS esds(data, size);
96719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            if (esds.getCodecSpecificInfo(&data, &size) == OK) {
96819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mCodecSpecificData = malloc(size);
96919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mCodecSpecificDataSize = size;
97019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                memcpy(mCodecSpecificData, data, size);
97119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mGotAllCodecSpecificData = true;
97219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            }
97319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        }
97419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
97520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
97620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
97720111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() {
97820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    stop();
97920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
98020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mCodecSpecificData != NULL) {
98120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        free(mCodecSpecificData);
98220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mCodecSpecificData = NULL;
98320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
98420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
98520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
98693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) {
98793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    LOGV("initTrackingProgressStatus");
98893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mPreviousTrackTimeUs = -1;
98993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackingProgressStatus = false;
99093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackEveryTimeDurationUs = 0;
99193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    {
99293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        int64_t timeUs;
99393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) {
99493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            LOGV("Receive request to track progress status for every %lld us", timeUs);
99593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackEveryTimeDurationUs = timeUs;
99693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackingProgressStatus = true;
99793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
99893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
99993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
100093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
10011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong// static
10021c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid *MPEG4Writer::ThreadWrapper(void *me) {
10031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("ThreadWrapper: %p", me);
10041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    MPEG4Writer *writer = static_cast<MPEG4Writer *>(me);
10051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    writer->threadFunc();
10061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return NULL;
10071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
10081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
10091c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::bufferChunk(const Chunk& chunk) {
10101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("bufferChunk: %p", chunk.mTrack);
10111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Mutex::Autolock autolock(mLock);
10121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    CHECK_EQ(mDone, false);
10131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
10141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
10151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
10161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
10171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (chunk.mTrack == it->mTrack) {  // Found owner
10181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            it->mChunks.push_back(chunk);
10191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.signal();
10201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            return;
10211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
10221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
10231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
10241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    CHECK("Received a chunk for a unknown track" == 0);
10251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
10261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
10271c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::writeFirstChunk(ChunkInfo* info) {
10281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("writeFirstChunk: %p", info->mTrack);
10291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
10301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    List<Chunk>::iterator chunkIt = info->mChunks.begin();
10311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<MediaBuffer *>::iterator it = chunkIt->mSamples.begin();
10321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != chunkIt->mSamples.end(); ++it) {
10331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
10341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        off_t offset = info->mTrack->isAvc()
10351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                            ? addLengthPrefixedSample_l(*it)
10361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                            : addSample_l(*it);
10371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (it == chunkIt->mSamples.begin()) {
10381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            info->mTrack->addChunkOffset(offset);
10391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
10401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
10411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
10421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    // Done with the current chunk.
10431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    // Release all the samples in this chunk.
10441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    while (!chunkIt->mSamples.empty()) {
10451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        List<MediaBuffer *>::iterator it = chunkIt->mSamples.begin();
10461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it)->release();
10471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it) = NULL;
10481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        chunkIt->mSamples.erase(it);
10491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
10501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    chunkIt->mSamples.clear();
10511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    info->mChunks.erase(chunkIt);
10521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
10531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
10541c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::writeChunks() {
10551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("writeChunks");
10561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    size_t outstandingChunks = 0;
10571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    while (!mChunkInfos.empty()) {
10581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        List<ChunkInfo>::iterator it = mChunkInfos.begin();
10591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        while (!it->mChunks.empty()) {
10601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            CHECK_EQ(OK, writeOneChunk());
10611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            ++outstandingChunks;
10621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
10631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        it->mTrack = NULL;
10641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkInfos.erase(it);
10651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
10661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mChunkInfos.clear();
10671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGD("%d chunks are written in the last batch", outstandingChunks);
10681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
10691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
10701c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::writeOneChunk() {
10711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("writeOneChunk");
10721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
10731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    // Find the smallest timestamp, and write that chunk out
10741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    // XXX: What if some track is just too slow?
10751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL;
10761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Track *track = NULL;
10771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
10781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
10791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (!it->mChunks.empty()) {
10801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            List<Chunk>::iterator chunkIt = it->mChunks.begin();
10811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (chunkIt->mTimeStampUs < minTimestampUs) {
10821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                minTimestampUs = chunkIt->mTimeStampUs;
10831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                track = it->mTrack;
10841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            }
10851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
10861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
10871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
10881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (track == NULL) {
10891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        LOGV("Nothing to be written after all");
10901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        return OK;
10911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
10921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
10931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (mIsFirstChunk) {
10941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsFirstChunk = false;
10951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
10961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
10971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
10981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (it->mTrack == track) {
10991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            writeFirstChunk(&(*it));
11001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
11011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
11021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return OK;
11031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
11041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
11051c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::threadFunc() {
11061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("threadFunc");
11071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1108a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    prctl(PR_SET_NAME, (unsigned long)"MPEG4Writer", 0, 0, 0);
11091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    while (!mDone) {
11101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        {
11111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            Mutex::Autolock autolock(mLock);
11121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.wait(mLock);
11131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            CHECK_EQ(writeOneChunk(), OK);
11141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
11151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
11161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
11171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    {
11181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        // Write ALL samples
11191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        Mutex::Autolock autolock(mLock);
11201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        writeChunks();
11211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
11221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
11231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
11241c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::startWriterThread() {
11251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("startWriterThread");
11261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
11271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mDone = false;
11281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsFirstChunk = true;
1129e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    mDriftTimeUs = 0;
11301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<Track *>::iterator it = mTracks.begin();
11311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mTracks.end(); ++it) {
11321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        ChunkInfo info;
11331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        info.mTrack = *it;
11341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkInfos.push_back(info);
11351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
11361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
11371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_t attr;
11381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_init(&attr);
11391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
11401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_create(&mThread, &attr, ThreadWrapper, this);
11411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_destroy(&attr);
11421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return OK;
11431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
11441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
11451f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
114693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) {
1147a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (!mDone && mPaused) {
1148a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mPaused = false;
1149a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mResumed = true;
1150a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
1151a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
115225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
115393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t startTimeUs;
115419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) {
115519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        startTimeUs = 0;
115619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
115719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
1158d0ea545d8357e7d86ad5f19cb2c6499c91786473James Dong    mIsRealTimeRecording = false;
1159e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    {
1160e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        int32_t isNotRealTime;
1161e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        if (params && params->findInt32(kKeyNotRealTime, &isNotRealTime)) {
1162e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            mIsRealTimeRecording = (isNotRealTime == 0);
1163e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        }
1164e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    }
1165e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
116693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    initTrackingProgressStatus(params);
116793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
1168f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    sp<MetaData> meta = new MetaData;
1169f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    meta->setInt64(kKeyTime, startTimeUs);
1170f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    status_t err = mSource->start(meta.get());
117125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    if (err != OK) {
117225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        mDone = mReachedEOS = true;
117325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return err;
117425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
117520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
117620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_t attr;
117720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_init(&attr);
117820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
117920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
118020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = false;
1181c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs = 0;
118225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = false;
1183956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    mEstimatedTrackSizeBytes = 0;
11841f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mNumStcoTableEntries = 0;
11851f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mNumStssTableEntries = 0;
11861f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mNumStscTableEntries = 0;
11871f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mNumSttsTableEntries = 0;
11881f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mMdatSizeBytes = 0;
1189872a481558350634a3fd5cb67939de288af00ecbJames Dong    mIsMediaTimeAdjustmentOn = false;
1190872a481558350634a3fd5cb67939de288af00ecbJames Dong    mPrevMediaTimeAdjustTimestampUs = 0;
1191872a481558350634a3fd5cb67939de288af00ecbJames Dong    mMediaTimeAdjustNumFrames = 0;
1192872a481558350634a3fd5cb67939de288af00ecbJames Dong    mPrevMediaTimeAdjustSample = 0;
1193872a481558350634a3fd5cb67939de288af00ecbJames Dong    mTotalDriftTimeToAdjustUs = 0;
1194872a481558350634a3fd5cb67939de288af00ecbJames Dong    mPrevTotalAccumDriftTimeUs = 0;
119520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
119625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    pthread_create(&mThread, &attr, ThreadWrapper, this);
119720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_destroy(&attr);
119825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
119925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
120020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
120120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
120237187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::pause() {
1203a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
120437187916a486504acaf83bea30147eb5fbf46ae5James Dong    return OK;
1205a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
1206a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
120737187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::stop() {
120820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mDone) {
120937187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
121020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
121120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
121220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = true;
121320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
121420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *dummy;
121520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_join(mThread, &dummy);
121620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
121737187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = (status_t) dummy;
121837187916a486504acaf83bea30147eb5fbf46ae5James Dong
121937187916a486504acaf83bea30147eb5fbf46ae5James Dong    {
122037187916a486504acaf83bea30147eb5fbf46ae5James Dong        status_t status = mSource->stop();
122137187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (err == OK && status != OK && status != ERROR_END_OF_STREAM) {
122237187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
122337187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
122437187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
122537187916a486504acaf83bea30147eb5fbf46ae5James Dong
122637187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
122720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
122820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
122925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() {
123025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return mReachedEOS;
123125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
123225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
123320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static
123420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) {
123520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = static_cast<Track *>(me);
123620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
123737187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = track->threadEntry();
123837187916a486504acaf83bea30147eb5fbf46ae5James Dong    return (void *) err;
123920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
124020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic void getNalUnitType(uint8_t byte, uint8_t* type) {
12423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    LOGV("getNalUnitType: %d", byte);
12433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
12443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // nal_unit_type: 5-bit unsigned integer
12453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *type = (byte & 0x1F);
12463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
12473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
12483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t *findNextStartCode(
12493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length) {
12503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
12513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    LOGV("findNextStartCode: %p %d", data, length);
12523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
12533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t bytesLeft = length;
12543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    while (bytesLeft > 4  &&
12553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            memcmp("\x00\x00\x00\x01", &data[length - bytesLeft], 4)) {
12563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        --bytesLeft;
12573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
12583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (bytesLeft <= 4) {
12593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        bytesLeft = 0; // Last parameter set
12603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
12613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return &data[length - bytesLeft];
12623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
12633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
12643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongconst uint8_t *MPEG4Writer::Track::parseParamSet(
12653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen) {
12663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
12673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    LOGV("parseParamSet");
12683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    CHECK(type == kNalUnitTypeSeqParamSet ||
12693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong          type == kNalUnitTypePicParamSet);
12703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
12713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *nextStartCode = findNextStartCode(data, length);
12723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *paramSetLen = nextStartCode - data;
12733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (*paramSetLen == 0) {
12743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        LOGE("Param set is malformed, since its length is 0");
12753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return NULL;
12763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
12773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
12783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    AVCParamSet paramSet(*paramSetLen, data);
12793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (type == kNalUnitTypeSeqParamSet) {
12803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (*paramSetLen < 4) {
12813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Seq parameter set malformed");
12823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return NULL;
12833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
12843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mSeqParamSets.empty()) {
12853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc = data[1];
12863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileCompatible = data[2];
12873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mLevelIdc = data[3];
12883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
12893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (mProfileIdc != data[1] ||
12903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mProfileCompatible != data[2] ||
12913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mLevelIdc != data[3]) {
12923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                LOGE("Inconsistent profile/level found in seq parameter sets");
12933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return NULL;
12943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
12953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
12963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mSeqParamSets.push_back(paramSet);
12973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    } else {
12983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mPicParamSets.push_back(paramSet);
12993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
13003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return nextStartCode;
13013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
13023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::copyAVCCodecSpecificData(
13043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
13053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    LOGV("copyAVCCodecSpecificData");
13063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 2 bytes for each of the parameter set length field
13083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // plus the 7 bytes for the header
13093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (size < 4 + 7) {
13103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        LOGE("Codec specific data length too short: %d", size);
13113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return ERROR_MALFORMED;
13123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
13133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize = size;
13153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificData = malloc(size);
13163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    memcpy(mCodecSpecificData, data, size);
13173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
13183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
13193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::parseAVCCodecSpecificData(
13213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
13223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    LOGV("parseAVCCodecSpecificData");
13243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data starts with a start code.
13253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // SPS and PPS are separated with start codes.
13263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Also, SPS must come before PPS
13273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t type = kNalUnitTypeSeqParamSet;
13283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotSps = false;
13293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotPps = false;
13303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *tmp = data;
13313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *nextStartCode = data;
13323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t bytesLeft = size;
13333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t paramSetLen = 0;
13343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize = 0;
13353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) {
13363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        getNalUnitType(*(tmp + 4), &type);
13373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (type == kNalUnitTypeSeqParamSet) {
13383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (gotPps) {
13393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                LOGE("SPS must come before PPS");
13403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
13413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
13423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
13433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotSps = true;
13443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
13453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
13463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else if (type == kNalUnitTypePicParamSet) {
13473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
13483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                LOGE("SPS must come before PPS");
13493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
13503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
13513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotPps) {
13523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotPps = true;
13533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
13543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
13553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
13563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Only SPS and PPS Nal units are expected");
13573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
13583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
13593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nextStartCode == NULL) {
13613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
13623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
13633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Move on to find the next parameter set
13653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        bytesLeft -= nextStartCode - tmp;
13663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        tmp = nextStartCode;
13673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mCodecSpecificDataSize += (2 + paramSetLen);
13683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
13693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
13713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of seq parameter sets
13723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nSeqParamSets = mSeqParamSets.size();
13733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets == 0) {
13743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Cound not find sequence parameter set");
13753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
13763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
13773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets > 0x1F) {
13793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Too many seq parameter sets (%d) found", nSeqParamSets);
13803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
13813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
13823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
13833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
13853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of pic parameter sets
13863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nPicParamSets = mPicParamSets.size();
13873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets == 0) {
13883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Cound not find picture parameter set");
13893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
13903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
13913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets > 0xFF) {
13923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Too many pic parameter sets (%d) found", nPicParamSets);
13933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
13943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
13953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
13963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
13983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the profiles
13993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // These profiles requires additional parameter set extensions
14003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mProfileIdc == 100 || mProfileIdc == 110 ||
14013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc == 122 || mProfileIdc == 144) {
14023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Sorry, no support for profile_idc: %d!", mProfileIdc);
14033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return BAD_VALUE;
14043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
14053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
14063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
14073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
14083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
1409548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
141003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData(
141103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        const uint8_t *data, size_t size) {
1412548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
141303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (mCodecSpecificData != NULL) {
1414548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        LOGE("Already have codec specific data");
141503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
141603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
141703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
14183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (size < 4) {
14193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        LOGE("Codec specific data length too short: %d", size);
142003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
142103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
142203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
14233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data is in the form of AVCCodecSpecificData
14243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (memcmp("\x00\x00\x00\x01", data, 4)) {
14253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return copyAVCCodecSpecificData(data, size);
142603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
142703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
14283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (parseAVCCodecSpecificData(data, size) != OK) {
142903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
143003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
143103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
14323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // ISO 14496-15: AVC file format
14333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize += 7;  // 7 more bytes in the header
143403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    mCodecSpecificData = malloc(mCodecSpecificDataSize);
143503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    uint8_t *header = (uint8_t *)mCodecSpecificData;
14363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = 1;                     // version
14373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[1] = mProfileIdc;           // profile indication
14383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[2] = mProfileCompatible;    // profile compatibility
14393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[3] = mLevelIdc;
144003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
14413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne
1442b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (mOwner->useNalLengthFour()) {
1443b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        header[4] = 0xfc | 3;  // length size == 4 bytes
1444b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    } else {
1445b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        header[4] = 0xfc | 1;  // length size == 2 bytes
1446b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    }
144703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
14483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 3-bit '111' followed by 5-bit numSequenceParameterSets
14493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nSequenceParamSets = mSeqParamSets.size();
14503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[5] = 0xe0 | nSequenceParamSets;
14513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 6;
14523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mSeqParamSets.begin();
14533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mSeqParamSets.end(); ++it) {
14543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit sequence parameter set length
14553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t seqParamSetLength = it->mLength;
14563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = seqParamSetLength >> 8;
14573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = seqParamSetLength & 0xff;
14583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
14593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // SPS NAL unit (sequence parameter length bytes)
14603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, seqParamSetLength);
14613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + seqParamSetLength);
14623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
14633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
14643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 8-bit nPictureParameterSets
14653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nPictureParamSets = mPicParamSets.size();
14663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = nPictureParamSets;
14673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 1;
14683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mPicParamSets.begin();
14693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mPicParamSets.end(); ++it) {
14703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit picture parameter set length
14713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t picParamSetLength = it->mLength;
14723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = picParamSetLength >> 8;
14733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = picParamSetLength & 0xff;
14743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
14753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // PPS Nal unit (picture parameter set length bytes)
14763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, picParamSetLength);
14773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + picParamSetLength);
14783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
147903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
148003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    return OK;
148103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
148203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
1483872a481558350634a3fd5cb67939de288af00ecbJames Dong/*
1484872a481558350634a3fd5cb67939de288af00ecbJames Dong* The video track's media time adjustment for real-time applications
1485872a481558350634a3fd5cb67939de288af00ecbJames Dong* is described as follows:
1486872a481558350634a3fd5cb67939de288af00ecbJames Dong*
1487872a481558350634a3fd5cb67939de288af00ecbJames Dong* First, the media time adjustment is done for every period of
1488872a481558350634a3fd5cb67939de288af00ecbJames Dong* kVideoMediaTimeAdjustPeriodTimeUs. kVideoMediaTimeAdjustPeriodTimeUs
1489872a481558350634a3fd5cb67939de288af00ecbJames Dong* is currently a fixed value chosen heuristically. The value of
1490872a481558350634a3fd5cb67939de288af00ecbJames Dong* kVideoMediaTimeAdjustPeriodTimeUs should not be very large or very small
1491872a481558350634a3fd5cb67939de288af00ecbJames Dong* for two considerations: on one hand, a relatively large value
1492872a481558350634a3fd5cb67939de288af00ecbJames Dong* helps reduce large fluctuation of drift time in the audio encoding
1493872a481558350634a3fd5cb67939de288af00ecbJames Dong* path; while on the other hand, a relatively small value helps keep
1494872a481558350634a3fd5cb67939de288af00ecbJames Dong* restoring synchronization in audio/video more frequently. Note for the
1495872a481558350634a3fd5cb67939de288af00ecbJames Dong* very first period of kVideoMediaTimeAdjustPeriodTimeUs, there is
1496872a481558350634a3fd5cb67939de288af00ecbJames Dong* no media time adjustment for the video track.
1497872a481558350634a3fd5cb67939de288af00ecbJames Dong*
1498872a481558350634a3fd5cb67939de288af00ecbJames Dong* Second, the total accumulated audio track time drift found
1499872a481558350634a3fd5cb67939de288af00ecbJames Dong* in a period of kVideoMediaTimeAdjustPeriodTimeUs is distributed
1500872a481558350634a3fd5cb67939de288af00ecbJames Dong* over a stream of incoming video frames. The number of video frames
1501872a481558350634a3fd5cb67939de288af00ecbJames Dong* affected is determined based on the number of recorded video frames
1502872a481558350634a3fd5cb67939de288af00ecbJames Dong* within the past kVideoMediaTimeAdjustPeriodTimeUs period.
1503872a481558350634a3fd5cb67939de288af00ecbJames Dong* We choose to distribute the drift time over only a portion
1504872a481558350634a3fd5cb67939de288af00ecbJames Dong* (rather than all) of the total number of recorded video frames
1505872a481558350634a3fd5cb67939de288af00ecbJames Dong* in order to make sure that the video track media time adjustment is
1506872a481558350634a3fd5cb67939de288af00ecbJames Dong* completed for the current period before the next video track media
1507872a481558350634a3fd5cb67939de288af00ecbJames Dong* time adjustment period starts. Currently, the portion chosen is a
1508872a481558350634a3fd5cb67939de288af00ecbJames Dong* half (0.5).
1509872a481558350634a3fd5cb67939de288af00ecbJames Dong*
1510872a481558350634a3fd5cb67939de288af00ecbJames Dong* Last, various additional checks are performed to ensure that
1511872a481558350634a3fd5cb67939de288af00ecbJames Dong* the actual audio encoding path does not have too much drift.
1512872a481558350634a3fd5cb67939de288af00ecbJames Dong* In particular, 1) we want to limit the average incremental time
1513872a481558350634a3fd5cb67939de288af00ecbJames Dong* adjustment for each video frame to be less than a threshold
1514872a481558350634a3fd5cb67939de288af00ecbJames Dong* for a single period of kVideoMediaTimeAdjustPeriodTimeUs.
1515872a481558350634a3fd5cb67939de288af00ecbJames Dong* Currently, the threshold is set to 5 ms. If the average incremental
1516872a481558350634a3fd5cb67939de288af00ecbJames Dong* media time adjustment for a video frame is larger than the
1517872a481558350634a3fd5cb67939de288af00ecbJames Dong* threshold, the audio encoding path has too much time drift.
1518872a481558350634a3fd5cb67939de288af00ecbJames Dong* 2) We also want to limit the total time drift in the audio
1519872a481558350634a3fd5cb67939de288af00ecbJames Dong* encoding path to be less than a threshold for a period of
1520872a481558350634a3fd5cb67939de288af00ecbJames Dong* kVideoMediaTimeAdjustPeriodTimeUs. Currently, the threshold
1521872a481558350634a3fd5cb67939de288af00ecbJames Dong* is 0.5% of kVideoMediaTimeAdjustPeriodTimeUs. If the time drift of
1522872a481558350634a3fd5cb67939de288af00ecbJames Dong* the audio encoding path is larger than the threshold, the audio
1523872a481558350634a3fd5cb67939de288af00ecbJames Dong* encoding path has too much time drift. We treat the large time
1524872a481558350634a3fd5cb67939de288af00ecbJames Dong* drift of the audio encoding path as errors, since there is no
1525872a481558350634a3fd5cb67939de288af00ecbJames Dong* way to keep audio/video in synchronization for real-time
1526872a481558350634a3fd5cb67939de288af00ecbJames Dong* applications if the time drift is too large unless we drop some
1527872a481558350634a3fd5cb67939de288af00ecbJames Dong* video frames, which has its own problems that we don't want
1528872a481558350634a3fd5cb67939de288af00ecbJames Dong* to get into for the time being.
1529872a481558350634a3fd5cb67939de288af00ecbJames Dong*/
1530872a481558350634a3fd5cb67939de288af00ecbJames Dongvoid MPEG4Writer::Track::adjustMediaTime(int64_t *timestampUs) {
1531872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (*timestampUs - mPrevMediaTimeAdjustTimestampUs >=
1532872a481558350634a3fd5cb67939de288af00ecbJames Dong        kVideoMediaTimeAdjustPeriodTimeUs) {
1533872a481558350634a3fd5cb67939de288af00ecbJames Dong
1534872a481558350634a3fd5cb67939de288af00ecbJames Dong        LOGV("New media time adjustment period at %lld us", *timestampUs);
1535872a481558350634a3fd5cb67939de288af00ecbJames Dong        mIsMediaTimeAdjustmentOn = true;
1536872a481558350634a3fd5cb67939de288af00ecbJames Dong        mMediaTimeAdjustNumFrames =
1537872a481558350634a3fd5cb67939de288af00ecbJames Dong                (mNumSamples - mPrevMediaTimeAdjustSample) >> 1;
1538872a481558350634a3fd5cb67939de288af00ecbJames Dong
1539872a481558350634a3fd5cb67939de288af00ecbJames Dong        mPrevMediaTimeAdjustTimestampUs = *timestampUs;
1540872a481558350634a3fd5cb67939de288af00ecbJames Dong        mPrevMediaTimeAdjustSample = mNumSamples;
1541872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t totalAccumDriftTimeUs = mOwner->getDriftTimeUs();
1542872a481558350634a3fd5cb67939de288af00ecbJames Dong        mTotalDriftTimeToAdjustUs =
1543872a481558350634a3fd5cb67939de288af00ecbJames Dong                totalAccumDriftTimeUs - mPrevTotalAccumDriftTimeUs;
1544872a481558350634a3fd5cb67939de288af00ecbJames Dong
1545872a481558350634a3fd5cb67939de288af00ecbJames Dong        mPrevTotalAccumDriftTimeUs = totalAccumDriftTimeUs;
1546872a481558350634a3fd5cb67939de288af00ecbJames Dong
1547872a481558350634a3fd5cb67939de288af00ecbJames Dong        // Check on incremental adjusted time per frame
1548872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t adjustTimePerFrameUs =
1549872a481558350634a3fd5cb67939de288af00ecbJames Dong                mTotalDriftTimeToAdjustUs / mMediaTimeAdjustNumFrames;
1550872a481558350634a3fd5cb67939de288af00ecbJames Dong
1551872a481558350634a3fd5cb67939de288af00ecbJames Dong        if (adjustTimePerFrameUs < 0) {
1552872a481558350634a3fd5cb67939de288af00ecbJames Dong            adjustTimePerFrameUs = -adjustTimePerFrameUs;
1553872a481558350634a3fd5cb67939de288af00ecbJames Dong        }
1554872a481558350634a3fd5cb67939de288af00ecbJames Dong        if (adjustTimePerFrameUs >= 5000) {
1555872a481558350634a3fd5cb67939de288af00ecbJames Dong            LOGE("Adjusted time per video frame is %lld us",
1556872a481558350634a3fd5cb67939de288af00ecbJames Dong                adjustTimePerFrameUs);
1557872a481558350634a3fd5cb67939de288af00ecbJames Dong            CHECK(!"Video frame time adjustment is too large!");
1558872a481558350634a3fd5cb67939de288af00ecbJames Dong        }
1559872a481558350634a3fd5cb67939de288af00ecbJames Dong
1560872a481558350634a3fd5cb67939de288af00ecbJames Dong        // Check on total accumulated time drift within a period of
1561872a481558350634a3fd5cb67939de288af00ecbJames Dong        // kVideoMediaTimeAdjustPeriodTimeUs.
1562872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t driftPercentage = (mTotalDriftTimeToAdjustUs * 1000)
1563872a481558350634a3fd5cb67939de288af00ecbJames Dong                / kVideoMediaTimeAdjustPeriodTimeUs;
1564872a481558350634a3fd5cb67939de288af00ecbJames Dong
1565872a481558350634a3fd5cb67939de288af00ecbJames Dong        if (driftPercentage < 0) {
1566872a481558350634a3fd5cb67939de288af00ecbJames Dong            driftPercentage = -driftPercentage;
1567872a481558350634a3fd5cb67939de288af00ecbJames Dong        }
1568872a481558350634a3fd5cb67939de288af00ecbJames Dong        if (driftPercentage > 5) {
1569872a481558350634a3fd5cb67939de288af00ecbJames Dong            LOGE("Audio track has time drift %lld us over %lld us",
1570872a481558350634a3fd5cb67939de288af00ecbJames Dong                mTotalDriftTimeToAdjustUs,
1571872a481558350634a3fd5cb67939de288af00ecbJames Dong                kVideoMediaTimeAdjustPeriodTimeUs);
1572872a481558350634a3fd5cb67939de288af00ecbJames Dong
1573872a481558350634a3fd5cb67939de288af00ecbJames Dong            CHECK(!"The audio track media time drifts too much!");
1574872a481558350634a3fd5cb67939de288af00ecbJames Dong        }
1575872a481558350634a3fd5cb67939de288af00ecbJames Dong
1576872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
1577872a481558350634a3fd5cb67939de288af00ecbJames Dong
1578872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (mIsMediaTimeAdjustmentOn) {
1579872a481558350634a3fd5cb67939de288af00ecbJames Dong        if (mNumSamples - mPrevMediaTimeAdjustSample <=
1580872a481558350634a3fd5cb67939de288af00ecbJames Dong            mMediaTimeAdjustNumFrames) {
1581872a481558350634a3fd5cb67939de288af00ecbJames Dong
1582872a481558350634a3fd5cb67939de288af00ecbJames Dong            // Do media time incremental adjustment
1583872a481558350634a3fd5cb67939de288af00ecbJames Dong            int64_t incrementalAdjustTimeUs =
1584872a481558350634a3fd5cb67939de288af00ecbJames Dong                        (mTotalDriftTimeToAdjustUs *
1585872a481558350634a3fd5cb67939de288af00ecbJames Dong                            (mNumSamples - mPrevMediaTimeAdjustSample))
1586872a481558350634a3fd5cb67939de288af00ecbJames Dong                                / mMediaTimeAdjustNumFrames;
1587872a481558350634a3fd5cb67939de288af00ecbJames Dong
1588872a481558350634a3fd5cb67939de288af00ecbJames Dong            *timestampUs +=
1589872a481558350634a3fd5cb67939de288af00ecbJames Dong                (incrementalAdjustTimeUs + mPrevTotalAccumDriftTimeUs);
1590872a481558350634a3fd5cb67939de288af00ecbJames Dong
1591872a481558350634a3fd5cb67939de288af00ecbJames Dong            LOGV("Incremental video frame media time adjustment: %lld us",
1592872a481558350634a3fd5cb67939de288af00ecbJames Dong                (incrementalAdjustTimeUs + mPrevTotalAccumDriftTimeUs));
1593872a481558350634a3fd5cb67939de288af00ecbJames Dong        } else {
1594872a481558350634a3fd5cb67939de288af00ecbJames Dong            // Within the remaining adjustment period,
1595872a481558350634a3fd5cb67939de288af00ecbJames Dong            // no incremental adjustment is needed.
1596872a481558350634a3fd5cb67939de288af00ecbJames Dong            *timestampUs +=
1597872a481558350634a3fd5cb67939de288af00ecbJames Dong                (mTotalDriftTimeToAdjustUs + mPrevTotalAccumDriftTimeUs);
1598872a481558350634a3fd5cb67939de288af00ecbJames Dong
1599872a481558350634a3fd5cb67939de288af00ecbJames Dong            LOGV("Fixed video frame media time adjustment: %lld us",
1600872a481558350634a3fd5cb67939de288af00ecbJames Dong                (mTotalDriftTimeToAdjustUs + mPrevTotalAccumDriftTimeUs));
1601872a481558350634a3fd5cb67939de288af00ecbJames Dong        }
1602872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
1603872a481558350634a3fd5cb67939de288af00ecbJames Dong}
1604872a481558350634a3fd5cb67939de288af00ecbJames Dong
1605872a481558350634a3fd5cb67939de288af00ecbJames Dong/*
1606872a481558350634a3fd5cb67939de288af00ecbJames Dong * Updates the drift time from the audio track so that
1607872a481558350634a3fd5cb67939de288af00ecbJames Dong * the video track can get the updated drift time information
1608872a481558350634a3fd5cb67939de288af00ecbJames Dong * from the file writer. The fluctuation of the drift time of the audio
1609872a481558350634a3fd5cb67939de288af00ecbJames Dong * encoding path is smoothed out with a simple filter by giving a larger
1610872a481558350634a3fd5cb67939de288af00ecbJames Dong * weight to more recently drift time. The filter coefficients, 0.5 and 0.5,
1611872a481558350634a3fd5cb67939de288af00ecbJames Dong * are heuristically determined.
1612872a481558350634a3fd5cb67939de288af00ecbJames Dong */
1613872a481558350634a3fd5cb67939de288af00ecbJames Dongvoid MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) {
1614872a481558350634a3fd5cb67939de288af00ecbJames Dong    int64_t driftTimeUs = 0;
1615872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) {
1616872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t prevDriftTimeUs = mOwner->getDriftTimeUs();
1617872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1;
1618872a481558350634a3fd5cb67939de288af00ecbJames Dong        mOwner->setDriftTimeUs(timeUs);
1619872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
1620872a481558350634a3fd5cb67939de288af00ecbJames Dong}
1621872a481558350634a3fd5cb67939de288af00ecbJames Dong
162237187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::threadEntry() {
162330ab66297501757d745b9ae10da61adcd891f497Andreas Huber    int32_t count = 0;
162413aec890216948b0c364f8f92792129d0335f506James Dong    const int64_t interleaveDurationUs = mOwner->interleaveDuration();
162513aec890216948b0c364f8f92792129d0335f506James Dong    int64_t chunkTimestampUs = 0;
162613aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nChunks = 0;
162713aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nZeroLengthFrames = 0;
16288f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t lastTimestampUs = 0;  // Previous sample time stamp in ms
16298f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t lastDurationUs = 0;   // Between the previous two samples in ms
1630c059860c73678a202bfa33062723e8f82fb779d9James Dong    int64_t currDurationTicks = 0;  // Timescale based ticks
1631c059860c73678a202bfa33062723e8f82fb779d9James Dong    int64_t lastDurationTicks = 0;  // Timescale based ticks
16328f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int32_t sampleCount = 1;      // Sample count in the current stts table entry
1633be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    uint32_t previousSampleSize = 0;  // Size of the previous sample
1634a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    int64_t previousPausedDurationUs = 0;
16351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    int64_t timestampUs;
1636e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
1637a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    if (mIsAudio) {
1638a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong        prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0);
1639a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    } else {
1640a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong        prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0);
1641a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    }
1642d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong    sp<MetaData> meta_data;
164320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1644ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    mNumSamples = 0;
164593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t err = OK;
164620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBuffer *buffer;
164793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    while (!mDone && (err = mSource->read(&buffer)) == OK) {
164820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (buffer->range_length() == 0) {
164920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer->release();
165020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer = NULL;
165113aec890216948b0c364f8f92792129d0335f506James Dong            ++nZeroLengthFrames;
165220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            continue;
165320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
165420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1655a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // If the codec specific data has not been received yet, delay pause.
1656a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // After the codec specific data is received, discard what we received
1657a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // when the track is to be paused.
1658a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused && !mResumed) {
1659a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer->release();
1660a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer = NULL;
1661a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            continue;
1662a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
1663a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
166430ab66297501757d745b9ae10da61adcd891f497Andreas Huber        ++count;
166530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
166603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        int32_t isCodecConfig;
166703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig)
166803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                && isCodecConfig) {
1669548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            CHECK(!mGotAllCodecSpecificData);
1670548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
16711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (mIsAvc) {
167203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                status_t err = makeAVCCodecSpecificData(
167303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        (const uint8_t *)buffer->data()
167403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                            + buffer->range_offset(),
167503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        buffer->range_length());
1676be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                CHECK_EQ(OK, err);
16771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            } else if (mIsMPEG4) {
167803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificDataSize = buffer->range_length();
167903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificData = malloc(mCodecSpecificDataSize);
168003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                memcpy(mCodecSpecificData,
168103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        (const uint8_t *)buffer->data()
168203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                            + buffer->range_offset(),
168303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                       buffer->range_length());
168430ab66297501757d745b9ae10da61adcd891f497Andreas Huber            }
168530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
168630ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer->release();
168730ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer = NULL;
168830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
1689548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            mGotAllCodecSpecificData = true;
169030ab66297501757d745b9ae10da61adcd891f497Andreas Huber            continue;
1691a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
1692a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
1693d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // Make a deep copy of the MediaBuffer and Metadata and release
1694d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // the original as soon as we can
1695d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        MediaBuffer *copy = new MediaBuffer(buffer->range_length());
1696d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(),
1697d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong                buffer->range_length());
1698d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        copy->set_range(0, buffer->range_length());
1699d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data = new MetaData(*buffer->meta_data().get());
1700d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer->release();
1701d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer = NULL;
1702d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
17031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (mIsAvc) StripStartcode(copy);
1704e136c3bb38e88315bf8797a464ebf2c788296b22James Dong
1705b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        size_t sampleSize = copy->range_length();
1706b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        if (mIsAvc) {
1707b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            if (mOwner->useNalLengthFour()) {
1708b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                sampleSize += 4;
1709b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            } else {
1710b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                sampleSize += 2;
1711b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            }
1712b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        }
1713050b28a593350047845a45a14cc5026221ac1620James Dong
1714d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        // Max file size or duration handling
17151f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mMdatSizeBytes += sampleSize;
17161f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        updateTrackSizeEstimate();
17171f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1718d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileSizeLimit()) {
1719d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
1720d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
1721d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
1722d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileDurationLimit()) {
1723d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
1724d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
1725d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
1726d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1727050b28a593350047845a45a14cc5026221ac1620James Dong
1728d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        int32_t isSync = false;
1729d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data->findInt32(kKeyIsSyncFrame, &isSync);
1730d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
17318428af5381e835cc783b7ecb0d71cb60961c99c2James Dong        /*
17328428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * The original timestamp found in the data buffer will be modified as below:
17338428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         *
17348428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * There is a playback offset into this track if the track's start time
17358428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * is not the same as the movie start time, which will be recorded in edst
17368428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * box of the output file. The playback offset is to make sure that the
17378428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * starting time of the audio/video tracks are synchronized. Although the
17388428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * track's media timestamp may be subject to various modifications
17398428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * as outlined below, the track's playback offset time remains unchanged
17408428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * once the first data buffer of the track is received.
17418428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         *
17428428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * The media time stamp will be calculated by subtracting the playback offset
17438428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * (and potential pause durations) from the original timestamp in the buffer.
17448428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         *
17458428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * If this track is a video track for a real-time recording application with
17468428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * both audio and video tracks, its media timestamp will subject to further
17478428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * modification based on the media clock of the audio track. This modification
17488428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * is needed for the purpose of maintaining good audio/video synchronization.
17498428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         *
17508428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * If the recording session is paused and resumed multiple times, the track
17518428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * media timestamp will be modified as if the  recording session had never been
17528428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * paused at all during playback of the recorded output file. In other words,
17538428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * the output file will have no memory of pause/resume durations.
17548428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         *
17558428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         */
1756d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        CHECK(meta_data->findInt64(kKeyTime, &timestampUs));
17578428af5381e835cc783b7ecb0d71cb60961c99c2James Dong        LOGV("%s timestampUs: %lld", mIsAudio? "Audio": "Video", timestampUs);
1758d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
1759d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong////////////////////////////////////////////////////////////////////////////////
17608644c14618d30d9e57a69df40ed939986ebf02c4James Dong        if (mSampleSizes.empty()) {
1761f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mStartTimestampUs = timestampUs;
1762f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mOwner->setStartTimestampUs(mStartTimestampUs);
17638428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            previousPausedDurationUs = mStartTimestampUs;
17643c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        }
176548c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber
1766a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mResumed) {
17678428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs;
17688428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            CHECK(durExcludingEarlierPausesUs >= 0);
17698428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs;
17708428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            CHECK(pausedDurationUs >= lastDurationUs);
17718428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            previousPausedDurationUs += pausedDurationUs - lastDurationUs;
1772a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mResumed = false;
1773a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
1774a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
1775a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        timestampUs -= previousPausedDurationUs;
17768428af5381e835cc783b7ecb0d71cb60961c99c2James Dong        CHECK(timestampUs >= 0);
1777872a481558350634a3fd5cb67939de288af00ecbJames Dong
1778872a481558350634a3fd5cb67939de288af00ecbJames Dong        // Media time adjustment for real-time applications
1779872a481558350634a3fd5cb67939de288af00ecbJames Dong        if (mIsRealTimeRecording) {
1780872a481558350634a3fd5cb67939de288af00ecbJames Dong            if (mIsAudio) {
1781872a481558350634a3fd5cb67939de288af00ecbJames Dong                updateDriftTime(meta_data);
1782872a481558350634a3fd5cb67939de288af00ecbJames Dong            } else {
1783872a481558350634a3fd5cb67939de288af00ecbJames Dong                adjustMediaTime(&timestampUs);
1784e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            }
1785e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        }
1786872a481558350634a3fd5cb67939de288af00ecbJames Dong
1787e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        CHECK(timestampUs >= 0);
1788e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        if (mNumSamples > 1) {
1789e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            if (timestampUs <= lastTimestampUs) {
17904f86a980fee1880dca61b828599fa6d76755a485James Dong                LOGW("Frame arrives too late!");
17914f86a980fee1880dca61b828599fa6d76755a485James Dong                // Don't drop the late frame, since dropping a frame may cause
17924f86a980fee1880dca61b828599fa6d76755a485James Dong                // problems later during playback
17934f86a980fee1880dca61b828599fa6d76755a485James Dong
17944f86a980fee1880dca61b828599fa6d76755a485James Dong                // The idea here is to avoid having two or more samples with the
17954f86a980fee1880dca61b828599fa6d76755a485James Dong                // same timestamp in the output file.
17964f86a980fee1880dca61b828599fa6d76755a485James Dong                if (mTimeScale >= 1000000LL) {
179740e9940fadf22daa64c1e766fa8a855c7b149c17James Dong                    timestampUs = lastTimestampUs + 1;
17984f86a980fee1880dca61b828599fa6d76755a485James Dong                } else {
179940e9940fadf22daa64c1e766fa8a855c7b149c17James Dong                    timestampUs = lastTimestampUs + (1000000LL + (mTimeScale >> 1)) / mTimeScale;
18004f86a980fee1880dca61b828599fa6d76755a485James Dong                }
1801e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            }
1802e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        }
1803e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
18048428af5381e835cc783b7ecb0d71cb60961c99c2James Dong        LOGV("%s media time stamp: %lld and previous paused duration %lld",
18058428af5381e835cc783b7ecb0d71cb60961c99c2James Dong                mIsAudio? "Audio": "Video", timestampUs, previousPausedDurationUs);
1806c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong        if (timestampUs > mTrackDurationUs) {
1807c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong            mTrackDurationUs = timestampUs;
18083b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber        }
18093b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber
18108644c14618d30d9e57a69df40ed939986ebf02c4James Dong        mSampleSizes.push_back(sampleSize);
1811ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong        ++mNumSamples;
1812ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong        if (mNumSamples > 2) {
1813c059860c73678a202bfa33062723e8f82fb779d9James Dong            // We need to use the time scale based ticks, rather than the
1814c059860c73678a202bfa33062723e8f82fb779d9James Dong            // timestamp itself to determine whether we have to use a new
1815c059860c73678a202bfa33062723e8f82fb779d9James Dong            // stts entry, since we may have rounding errors.
1816c059860c73678a202bfa33062723e8f82fb779d9James Dong            // The calculation is intended to reduce the accumulated
1817c059860c73678a202bfa33062723e8f82fb779d9James Dong            // rounding errors.
1818c059860c73678a202bfa33062723e8f82fb779d9James Dong            currDurationTicks =
1819c059860c73678a202bfa33062723e8f82fb779d9James Dong                     ((timestampUs * mTimeScale + 500000LL) / 1000000LL -
1820c059860c73678a202bfa33062723e8f82fb779d9James Dong                     (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL);
1821c059860c73678a202bfa33062723e8f82fb779d9James Dong
1822c059860c73678a202bfa33062723e8f82fb779d9James Dong            if (currDurationTicks != lastDurationTicks) {
18231f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                addOneSttsTableEntry(sampleCount, lastDurationUs);
1824be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                sampleCount = 1;
1825be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            } else {
1826be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                ++sampleCount;
1827be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
1828be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
1829be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        if (mSamplesHaveSameSize) {
1830ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong            if (mNumSamples >= 2 && previousSampleSize != sampleSize) {
1831be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mSamplesHaveSameSize = false;
1832be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
18338644c14618d30d9e57a69df40ed939986ebf02c4James Dong            previousSampleSize = sampleSize;
1834be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
18358644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastDurationUs = timestampUs - lastTimestampUs;
1836c059860c73678a202bfa33062723e8f82fb779d9James Dong        lastDurationTicks = currDurationTicks;
18378644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastTimestampUs = timestampUs;
183820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1839d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        if (isSync != 0) {
18401f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            addOneStssTableEntry(mNumSamples);
1841d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        }
1842d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
184393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (mTrackingProgressStatus) {
184493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            if (mPreviousTrackTimeUs <= 0) {
184593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong                mPreviousTrackTimeUs = mStartTimestampUs;
184693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            }
1847faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong            trackProgressStatus(timestampUs);
184893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
184958ae9c530247668f8af36e30d228c716c226b3d4James Dong        if (mOwner->numTracks() == 1) {
18501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            off_t offset = mIsAvc? mOwner->addLengthPrefixedSample_l(copy)
185158ae9c530247668f8af36e30d228c716c226b3d4James Dong                                 : mOwner->addSample_l(copy);
185258ae9c530247668f8af36e30d228c716c226b3d4James Dong            if (mChunkOffsets.empty()) {
18531f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                addChunkOffset(offset);
185458ae9c530247668f8af36e30d228c716c226b3d4James Dong            }
185558ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy->release();
185658ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy = NULL;
185758ae9c530247668f8af36e30d228c716c226b3d4James Dong            continue;
185858ae9c530247668f8af36e30d228c716c226b3d4James Dong        }
185913aec890216948b0c364f8f92792129d0335f506James Dong
186013aec890216948b0c364f8f92792129d0335f506James Dong        mChunkSamples.push_back(copy);
186113aec890216948b0c364f8f92792129d0335f506James Dong        if (interleaveDurationUs == 0) {
18621f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            addOneStscTableEntry(++nChunks, 1);
18631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            bufferChunk(timestampUs);
186413aec890216948b0c364f8f92792129d0335f506James Dong        } else {
186513aec890216948b0c364f8f92792129d0335f506James Dong            if (chunkTimestampUs == 0) {
186613aec890216948b0c364f8f92792129d0335f506James Dong                chunkTimestampUs = timestampUs;
186713aec890216948b0c364f8f92792129d0335f506James Dong            } else {
186813aec890216948b0c364f8f92792129d0335f506James Dong                if (timestampUs - chunkTimestampUs > interleaveDurationUs) {
186913aec890216948b0c364f8f92792129d0335f506James Dong                    ++nChunks;
187013aec890216948b0c364f8f92792129d0335f506James Dong                    if (nChunks == 1 ||  // First chunk
187113aec890216948b0c364f8f92792129d0335f506James Dong                        (--(mStscTableEntries.end()))->samplesPerChunk !=
187213aec890216948b0c364f8f92792129d0335f506James Dong                         mChunkSamples.size()) {
18731f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                        addOneStscTableEntry(nChunks, mChunkSamples.size());
187413aec890216948b0c364f8f92792129d0335f506James Dong                    }
18751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                    bufferChunk(timestampUs);
187613aec890216948b0c364f8f92792129d0335f506James Dong                    chunkTimestampUs = timestampUs;
187713aec890216948b0c364f8f92792129d0335f506James Dong                }
187813aec890216948b0c364f8f92792129d0335f506James Dong            }
187913aec890216948b0c364f8f92792129d0335f506James Dong        }
188013aec890216948b0c364f8f92792129d0335f506James Dong
188120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
188225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
1883a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong    if (mSampleSizes.empty() ||                      // no samples written
1884a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong        (!mIsAudio && mNumStssTableEntries == 0) ||  // no sync frames for video
1885a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong        (OK != checkCodecSpecificData())) {          // no codec specific data
1886690f546b0ee548dbfe997df36418e5302ec2d786James Dong        err = ERROR_MALFORMED;
1887f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong    }
1888faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    mOwner->trackProgressStatus(this, -1, err);
1889be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
189013aec890216948b0c364f8f92792129d0335f506James Dong    // Last chunk
189158ae9c530247668f8af36e30d228c716c226b3d4James Dong    if (mOwner->numTracks() == 1) {
18921f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        addOneStscTableEntry(1, mNumSamples);
189358ae9c530247668f8af36e30d228c716c226b3d4James Dong    } else if (!mChunkSamples.empty()) {
18941f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        addOneStscTableEntry(++nChunks, mChunkSamples.size());
18951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        bufferChunk(timestampUs);
189613aec890216948b0c364f8f92792129d0335f506James Dong    }
189713aec890216948b0c364f8f92792129d0335f506James Dong
1898be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // We don't really know how long the last frame lasts, since
1899be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // there is no frame time after it, just repeat the previous
1900be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // frame's duration.
1901ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    if (mNumSamples == 1) {
19028f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        lastDurationUs = 0;  // A single sample's duration
1903be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    } else {
1904be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        ++sampleCount;  // Count for the last sample
1905be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    }
19061f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    addOneSttsTableEntry(sampleCount, lastDurationUs);
1907c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs += lastDurationUs;
190825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = true;
19091f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    LOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s",
19101f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            count, nZeroLengthFrames, mNumSamples, mIsAudio? "audio": "video");
1911872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (mIsAudio) {
1912872a481558350634a3fd5cb67939de288af00ecbJames Dong        LOGI("Audio track drift time: %lld us", mOwner->getDriftTimeUs());
1913872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
1914365a963142093a1cd8efdcea76b5f65096a5b115James Dong
191537187916a486504acaf83bea30147eb5fbf46ae5James Dong    if (err == ERROR_END_OF_STREAM) {
191637187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
191737187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
191837187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
1919365a963142093a1cd8efdcea76b5f65096a5b115James Dong}
1920365a963142093a1cd8efdcea76b5f65096a5b115James Dong
1921faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) {
1922faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    LOGV("trackProgressStatus: %lld us", timeUs);
1923215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    if (mTrackEveryTimeDurationUs > 0 &&
1924215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) {
192593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        LOGV("Fire time tracking progress status at %lld us", timeUs);
1926faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        mOwner->trackProgressStatus(this, timeUs - mPreviousTrackTimeUs, err);
192793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        mPreviousTrackTimeUs = timeUs;
192893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
192993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
193093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
1931faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::trackProgressStatus(
1932faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        const MPEG4Writer::Track* track, int64_t timeUs, status_t err) {
1933faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    Mutex::Autolock lock(mLock);
1934faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    int32_t nTracks = mTracks.size();
1935faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    CHECK(nTracks >= 1);
1936faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    CHECK(nTracks < 64);  // Arbitrary number
1937faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
1938faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    int32_t trackNum = 0;
1939faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    CHECK(trackNum < nTracks);
1940faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    trackNum <<= 16;
1941faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
1942faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Error notification
1943faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Do not consider ERROR_END_OF_STREAM an error
1944faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (err != OK && err != ERROR_END_OF_STREAM) {
1945faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        notify(MEDIA_RECORDER_EVENT_ERROR,
1946faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               trackNum | MEDIA_RECORDER_ERROR_UNKNOWN,
1947faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
1948faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        return;
1949faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
1950faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
1951faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (timeUs == -1) {
1952faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send completion notification
1953faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        notify(MEDIA_RECORDER_EVENT_INFO,
1954faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               trackNum | MEDIA_RECORDER_INFO_COMPLETION_STATUS,
1955faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
1956faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        return;
1957faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    } else {
1958faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send progress status
1959faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        notify(MEDIA_RECORDER_EVENT_INFO,
1960faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               trackNum | MEDIA_RECORDER_INFO_PROGRESS_TIME_STATUS,
1961faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               timeUs / 1000);
1962faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
1963faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong}
1964faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
1965d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dongvoid MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) {
1966d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong    LOGV("setDriftTimeUs: %lld us", driftTimeUs);
1967e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
1968d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong    mDriftTimeUs = driftTimeUs;
1969e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
1970e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
1971e259531ce59ab1f31de5a23124b22536f6a5a767James Dongint64_t MPEG4Writer::getDriftTimeUs() {
1972e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    LOGV("getDriftTimeUs: %lld us", mDriftTimeUs);
1973e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
1974e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    return mDriftTimeUs;
1975e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
1976e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
1977b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dongbool MPEG4Writer::useNalLengthFour() {
1978b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    return mUse4ByteNalLength;
1979b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong}
1980b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong
19811c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::Track::bufferChunk(int64_t timestampUs) {
19821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("bufferChunk");
19831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
19841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Chunk chunk(this, timestampUs, mChunkSamples);
19851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mOwner->bufferChunk(chunk);
198613aec890216948b0c364f8f92792129d0335f506James Dong    mChunkSamples.clear();
198720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
198820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
19893b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const {
1990c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    return mTrackDurationUs;
199120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
199220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1993d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const {
1994d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return mEstimatedTrackSizeBytes;
1995d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
1996d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1997690f546b0ee548dbfe997df36418e5302ec2d786James Dongstatus_t MPEG4Writer::Track::checkCodecSpecificData() const {
1998690f546b0ee548dbfe997df36418e5302ec2d786James Dong    const char *mime;
1999690f546b0ee548dbfe997df36418e5302ec2d786James Dong    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
2000690f546b0ee548dbfe997df36418e5302ec2d786James Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) ||
2001690f546b0ee548dbfe997df36418e5302ec2d786James Dong        !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) ||
2002690f546b0ee548dbfe997df36418e5302ec2d786James Dong        !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
2003690f546b0ee548dbfe997df36418e5302ec2d786James Dong        if (!mCodecSpecificData ||
2004690f546b0ee548dbfe997df36418e5302ec2d786James Dong            mCodecSpecificDataSize <= 0) {
2005a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong            LOGE("Missing codec specific data");
2006690f546b0ee548dbfe997df36418e5302ec2d786James Dong            return ERROR_MALFORMED;
2007690f546b0ee548dbfe997df36418e5302ec2d786James Dong        }
2008690f546b0ee548dbfe997df36418e5302ec2d786James Dong    } else {
2009690f546b0ee548dbfe997df36418e5302ec2d786James Dong        if (mCodecSpecificData ||
2010690f546b0ee548dbfe997df36418e5302ec2d786James Dong            mCodecSpecificDataSize > 0) {
2011a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong            LOGE("Unexepected codec specific data found");
2012690f546b0ee548dbfe997df36418e5302ec2d786James Dong            return ERROR_MALFORMED;
2013690f546b0ee548dbfe997df36418e5302ec2d786James Dong        }
2014690f546b0ee548dbfe997df36418e5302ec2d786James Dong    }
2015690f546b0ee548dbfe997df36418e5302ec2d786James Dong    return OK;
2016690f546b0ee548dbfe997df36418e5302ec2d786James Dong}
2017690f546b0ee548dbfe997df36418e5302ec2d786James Dong
20181acfe8649f8169caf2ff098c2dc2de880d9a3760James Dongvoid MPEG4Writer::Track::writeTrackHeader(
20191acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        int32_t trackID, bool use32BitOffset) {
202020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const char *mime;
202120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool success = mMeta->findCString(kKeyMIMEType, &mime);
20220c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(success);
202320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
20248f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    LOGV("%s track time scale: %d",
20251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsAudio? "Audio": "Video", mTimeScale);
20268f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
202720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    time_t now = time(NULL);
20288f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int32_t mvhdTimeScale = mOwner->getTimeScale();
20298f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t trakDurationUs = getDurationUs();
203020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
203120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOwner->beginBox("trak");
203220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
203320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->beginBox("tkhd");
20341acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        // Flags = 7 to indicate that the track is enabled, and
20351acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        // part of the presentation
20361acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        mOwner->writeInt32(0x07);          // version=0, flags=7
203720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(now);           // creation time
203820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(now);           // modification time
203920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(trackID);
204020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);             // reserved
20418f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int32_t tkhdDuration =
20428f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
20438f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        mOwner->writeInt32(tkhdDuration);  // in mvhd timescale
204420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);             // reserved
204520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);             // reserved
204620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt16(0);             // layer
204720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt16(0);             // alternate group
20481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mOwner->writeInt16(mIsAudio ? 0x100 : 0);  // volume
204920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt16(0);             // reserved
205020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
205120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0x10000);       // matrix
205220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
205320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
205420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
205520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0x10000);
205620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
205720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
205820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
205920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0x40000000);
206020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
20611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (mIsAudio) {
206220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);
206320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);
206420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        } else {
206520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            int32_t width, height;
206620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            bool success = mMeta->findInt32(kKeyWidth, &width);
206720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            success = success && mMeta->findInt32(kKeyHeight, &height);
20680c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber            CHECK(success);
206920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2070050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->writeInt32(width << 16);   // 32-bit fixed-point value
2071050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->writeInt32(height << 16);  // 32-bit fixed-point value
207220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
207320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->endBox();  // tkhd
207420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2075f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong      int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
2076f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong      if (mStartTimestampUs != moovStartTimeUs) {
20773c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        mOwner->beginBox("edts");
20783c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong          mOwner->beginBox("elst");
20791acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong            mOwner->writeInt32(0);           // version=0, flags=0: 32-bit time
20801acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong            mOwner->writeInt32(2);           // never ends with an empty list
20818f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
20828f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            // First elst entry: specify the starting time offset
20838f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            int64_t offsetUs = mStartTimestampUs - moovStartTimeUs;
20848428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            LOGV("OffsetUs: %lld", offsetUs);
20858f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            int32_t seg = (offsetUs * mvhdTimeScale + 5E5) / 1E6;
20868f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            mOwner->writeInt32(seg);         // in mvhd timecale
20878f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            mOwner->writeInt32(-1);          // starting time offset
20888f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            mOwner->writeInt32(1 << 16);     // rate = 1.0
20898f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
20908f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            // Second elst entry: specify the track duration
20918f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            seg = (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
20928f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            mOwner->writeInt32(seg);         // in mvhd timescale
20931acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong            mOwner->writeInt32(0);
20941acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong            mOwner->writeInt32(1 << 16);
20953c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong          mOwner->endBox();
20963c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        mOwner->endBox();
20973c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong      }
20983c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
209920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->beginBox("mdia");
210020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
210120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("mdhd");
210220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // version=0, flags=0
210320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(now);           // creation time
210420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(now);           // modification time
21058f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong          mOwner->writeInt32(mTimeScale);    // media timescale
21068f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong          int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6;
21078f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong          mOwner->writeInt32(mdhdDuration);  // use media timescale
21081acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // Language follows the three letter standard ISO-639-2/T
21091acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // 'e', 'n', 'g' for "English", for instance.
21101acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // Each character is packed as the difference between its ASCII value and 0x60.
21111acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // For "English", these are 00101, 01110, 00111.
21121acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // XXX: Where is the padding bit located: 0x15C7?
21131acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          mOwner->writeInt16(0);             // language code
211420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt16(0);             // predefined
211520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->endBox();
211620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
211720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("hdlr");
211820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // version=0, flags=0
2119050b28a593350047845a45a14cc5026221ac1620James Dong          mOwner->writeInt32(0);             // component type: should be mhlr
21201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong          mOwner->writeFourcc(mIsAudio ? "soun" : "vide");  // component subtype
212120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // reserved
212220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // reserved
212320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // reserved
21241acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // Removing "r" for the name string just makes the string 4 byte aligned
21251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong          mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle");  // name
212620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->endBox();
212720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
212820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("minf");
21291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong          if (mIsAudio) {
213020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->beginBox("smhd");
213120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt32(0);           // version=0, flags=0
213220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // balance
213320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // reserved
213420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->endBox();
213520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          } else {
213620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->beginBox("vmhd");
21371acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong              mOwner->writeInt32(0x01);        // version=0, flags=1
213820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // graphics mode
213920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // opcolor
214020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);
214120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);
214220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->endBox();
214320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          }
2144050b28a593350047845a45a14cc5026221ac1620James Dong
2145050b28a593350047845a45a14cc5026221ac1620James Dong          mOwner->beginBox("dinf");
2146050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->beginBox("dref");
2147050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->writeInt32(0);  // version=0, flags=0
21481acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong              mOwner->writeInt32(1);  // entry count (either url or urn)
21491acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong              // The table index here refers to the sample description index
21501acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong              // in the sample table entries.
2151050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->beginBox("url ");
21521acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                mOwner->writeInt32(1);  // version=0, flags=1 (self-contained)
2153050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->endBox();  // url
2154050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->endBox();  // dref
2155050b28a593350047845a45a14cc5026221ac1620James Dong          mOwner->endBox();  // dinf
2156050b28a593350047845a45a14cc5026221ac1620James Dong
215720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("stbl");
215820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
215920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stsd");
216020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);               // version=0, flags=0
216120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(1);               // entry count
21621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (mIsAudio) {
216325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                const char *fourcc = NULL;
216418291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) {
216525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    fourcc = "samr";
216618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
216725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    fourcc = "sawb";
2168050b28a593350047845a45a14cc5026221ac1620James Dong                } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
2169050b28a593350047845a45a14cc5026221ac1620James Dong                    fourcc = "mp4a";
217025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                } else {
217125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    LOGE("Unknown mime type '%s'.", mime);
217225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    CHECK(!"should not be here, unknown mime type.");
217325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                }
217425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
217525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                mOwner->beginBox(fourcc);          // audio format
217620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
217720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
2178050b28a593350047845a45a14cc5026221ac1620James Dong                  mOwner->writeInt16(0x1);         // data ref index
217920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
218020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
2181050b28a593350047845a45a14cc5026221ac1620James Dong                  int32_t nChannels;
2182050b28a593350047845a45a14cc5026221ac1620James Dong                  CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels));
2183050b28a593350047845a45a14cc5026221ac1620James Dong                  mOwner->writeInt16(nChannels);   // channel count
218420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(16);          // sample size
218520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // predefined
218620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
218720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
218820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  int32_t samplerate;
218920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  bool success = mMeta->findInt32(kKeySampleRate, &samplerate);
21900c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                  CHECK(success);
219120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(samplerate << 16);
2192050b28a593350047845a45a14cc5026221ac1620James Dong                  if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
2193050b28a593350047845a45a14cc5026221ac1620James Dong                    mOwner->beginBox("esds");
219451dfe6d646ddcc5fc252aa4c19c9936d32af8ad7James Dong                        CHECK(mCodecSpecificData);
219551dfe6d646ddcc5fc252aa4c19c9936d32af8ad7James Dong                        CHECK(mCodecSpecificDataSize > 0);
2196050b28a593350047845a45a14cc5026221ac1620James Dong
21975f995b0e72ed6f186cb0ab2a525c4cfce614f3a9Andreas Huber                        // Make sure all sizes encode to a single byte.
21985f995b0e72ed6f186cb0ab2a525c4cfce614f3a9Andreas Huber                        CHECK(mCodecSpecificDataSize + 23 < 128);
21995f995b0e72ed6f186cb0ab2a525c4cfce614f3a9Andreas Huber
2200050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt32(0);     // version=0, flags=0
2201050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x03);   // ES_DescrTag
2202050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(23 + mCodecSpecificDataSize);
2203050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt16(0x0000);// ES_ID
2204050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x00);
2205050b28a593350047845a45a14cc5026221ac1620James Dong
2206050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x04);   // DecoderConfigDescrTag
2207050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(15 + mCodecSpecificDataSize);
2208050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x40);   // objectTypeIndication ISO/IEC 14492-2
2209050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x15);   // streamType AudioStream
2210050b28a593350047845a45a14cc5026221ac1620James Dong
2211050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt16(0x03);  // XXX
2212050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x00);   // buffer size 24-bit
2213050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt32(96000); // max bit rate
2214050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt32(96000); // avg bit rate
2215050b28a593350047845a45a14cc5026221ac1620James Dong
2216050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x05);   // DecoderSpecificInfoTag
2217050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(mCodecSpecificDataSize);
2218050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
2219050b28a593350047845a45a14cc5026221ac1620James Dong
2220050b28a593350047845a45a14cc5026221ac1620James Dong                        static const uint8_t kData2[] = {
2221050b28a593350047845a45a14cc5026221ac1620James Dong                            0x06,  // SLConfigDescriptorTag
2222050b28a593350047845a45a14cc5026221ac1620James Dong                            0x01,
2223050b28a593350047845a45a14cc5026221ac1620James Dong                            0x02
2224050b28a593350047845a45a14cc5026221ac1620James Dong                        };
2225050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->write(kData2, sizeof(kData2));
2226050b28a593350047845a45a14cc5026221ac1620James Dong
2227050b28a593350047845a45a14cc5026221ac1620James Dong                    mOwner->endBox();  // esds
22285aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                  } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) ||
22295aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                             !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
22305aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                    // 3gpp2 Spec AMRSampleEntry fields
22315aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                    mOwner->beginBox("damr");
22325aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                      mOwner->writeCString("   ");  // vendor: 4 bytes
22335aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                      mOwner->writeInt8(0);         // decoder version
22345aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                      mOwner->writeInt16(0x83FF);   // mode set: all enabled
22355aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                      mOwner->writeInt8(0);         // mode change period
22365aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                      mOwner->writeInt8(1);         // frames per sample
22375aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                    mOwner->endBox();
2238050b28a593350047845a45a14cc5026221ac1620James Dong                  }
223920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mOwner->endBox();
224020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
224118291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
224220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    mOwner->beginBox("mp4v");
224318291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
224420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    mOwner->beginBox("s263");
224530ab66297501757d745b9ae10da61adcd891f497Andreas Huber                } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
224630ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    mOwner->beginBox("avc1");
224720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                } else {
224825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    LOGE("Unknown mime type '%s'.", mime);
22490c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                    CHECK(!"should not be here, unknown mime type.");
225020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
225120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
225220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
225320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
22541acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                  mOwner->writeInt16(1);           // data ref index
225520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // predefined
225620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
225720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // predefined
225820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // predefined
225920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // predefined
226020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
226120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  int32_t width, height;
226220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  bool success = mMeta->findInt32(kKeyWidth, &width);
226320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  success = success && mMeta->findInt32(kKeyHeight, &height);
22640c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                  CHECK(success);
226520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
226620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(width);
226720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(height);
226820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0x480000);    // horiz resolution
226920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0x480000);    // vert resolution
227020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
227120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(1);           // frame count
227220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->write("                                ", 32);
227320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0x18);        // depth
227420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(-1);          // predefined
227520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
22760c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                  CHECK(23 + mCodecSpecificDataSize < 128);
227720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
227818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                  if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
2279a37923e9a57d489e7bed2129369219039fa5f12cJames Dong                      CHECK(mCodecSpecificData);
2280a37923e9a57d489e7bed2129369219039fa5f12cJames Dong                      CHECK(mCodecSpecificDataSize > 0);
228120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->beginBox("esds");
228220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
228320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt32(0);           // version=0, flags=0
228420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
228520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x03);  // ES_DescrTag
228620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(23 + mCodecSpecificDataSize);
228720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt16(0x0000);  // ES_ID
228820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x1f);
228920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
229020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x04);  // DecoderConfigDescrTag
229120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(15 + mCodecSpecificDataSize);
229220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x20);  // objectTypeIndication ISO/IEC 14492-2
229320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x11);  // streamType VisualStream
229420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
229520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        static const uint8_t kData[] = {
229620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x01, 0x77, 0x00,
229720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x00, 0x03, 0xe8, 0x00,
229820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x00, 0x03, 0xe8, 0x00
229920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        };
230020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->write(kData, sizeof(kData));
2301050b28a593350047845a45a14cc5026221ac1620James Dong
230220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x05);  // DecoderSpecificInfoTag
230320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
230420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(mCodecSpecificDataSize);
230520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
230620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
230720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        static const uint8_t kData2[] = {
230820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x06,  // SLConfigDescriptorTag
230920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x01,
231020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x02
231120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        };
231220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->write(kData2, sizeof(kData2));
231320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
231420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->endBox();  // esds
231518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                  } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
231620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->beginBox("d263");
231720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
231820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt32(0);  // vendor
231920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt8(0);   // decoder version
232020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt8(10);  // level: 10
232120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt8(0);   // profile: 0
232220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
232320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->endBox();  // d263
232430ab66297501757d745b9ae10da61adcd891f497Andreas Huber                  } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
232551dfe6d646ddcc5fc252aa4c19c9936d32af8ad7James Dong                      CHECK(mCodecSpecificData);
232695fcef25b48e35b625899288971ab628efbf8584Andreas Huber                      CHECK(mCodecSpecificDataSize >= 5);
232795fcef25b48e35b625899288971ab628efbf8584Andreas Huber
232895fcef25b48e35b625899288971ab628efbf8584Andreas Huber                      // Patch avcc's lengthSize field to match the number
232995fcef25b48e35b625899288971ab628efbf8584Andreas Huber                      // of bytes we use to indicate the size of a nal unit.
233095fcef25b48e35b625899288971ab628efbf8584Andreas Huber                      uint8_t *ptr = (uint8_t *)mCodecSpecificData;
233195fcef25b48e35b625899288971ab628efbf8584Andreas Huber                      ptr[4] =
233295fcef25b48e35b625899288971ab628efbf8584Andreas Huber                          (ptr[4] & 0xfc)
233395fcef25b48e35b625899288971ab628efbf8584Andreas Huber                            | (mOwner->useNalLengthFour() ? 3 : 1);
233495fcef25b48e35b625899288971ab628efbf8584Andreas Huber
233530ab66297501757d745b9ae10da61adcd891f497Andreas Huber                      mOwner->beginBox("avcC");
233630ab66297501757d745b9ae10da61adcd891f497Andreas Huber                        mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
233730ab66297501757d745b9ae10da61adcd891f497Andreas Huber                      mOwner->endBox();  // avcC
233820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  }
233930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
23401acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                  mOwner->beginBox("pasp");
23411acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                    // This is useful if the pixel is not square
23421acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                    mOwner->writeInt32(1 << 16);  // hspacing
23431acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                    mOwner->writeInt32(1 << 16);  // vspacing
23441acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                  mOwner->endBox();  // pasp
234530ab66297501757d745b9ae10da61adcd891f497Andreas Huber                mOwner->endBox();  // mp4v, s263 or avc1
234620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
234720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stsd
234820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
234920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stts");
235020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
23511f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            mOwner->writeInt32(mNumSttsTableEntries);
2352c059860c73678a202bfa33062723e8f82fb779d9James Dong            int64_t prevTimestampUs = 0;
2353be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin();
2354be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                 it != mSttsTableEntries.end(); ++it) {
2355be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mOwner->writeInt32(it->sampleCount);
2356c059860c73678a202bfa33062723e8f82fb779d9James Dong
2357c059860c73678a202bfa33062723e8f82fb779d9James Dong                // Make sure that we are calculating the sample duration the exactly
2358c059860c73678a202bfa33062723e8f82fb779d9James Dong                // same way as we made decision on how to create stts entries.
2359c059860c73678a202bfa33062723e8f82fb779d9James Dong                int64_t currTimestampUs = prevTimestampUs + it->sampleDurationUs;
2360c059860c73678a202bfa33062723e8f82fb779d9James Dong                int32_t dur = ((currTimestampUs * mTimeScale + 500000LL) / 1000000LL -
2361c059860c73678a202bfa33062723e8f82fb779d9James Dong                               (prevTimestampUs * mTimeScale + 500000LL) / 1000000LL);
2362c059860c73678a202bfa33062723e8f82fb779d9James Dong                prevTimestampUs += (it->sampleCount * it->sampleDurationUs);
2363c059860c73678a202bfa33062723e8f82fb779d9James Dong
23648f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong                mOwner->writeInt32(dur);
236520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
236620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stts
236720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
23681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong          if (!mIsAudio) {
2369050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->beginBox("stss");
2370050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->writeInt32(0);  // version=0, flags=0
23711f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong              mOwner->writeInt32(mNumStssTableEntries);  // number of sync frames
2372050b28a593350047845a45a14cc5026221ac1620James Dong              for (List<int32_t>::iterator it = mStssTableEntries.begin();
2373050b28a593350047845a45a14cc5026221ac1620James Dong                   it != mStssTableEntries.end(); ++it) {
2374050b28a593350047845a45a14cc5026221ac1620James Dong                  mOwner->writeInt32(*it);
2375050b28a593350047845a45a14cc5026221ac1620James Dong              }
2376050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->endBox();  // stss
2377050b28a593350047845a45a14cc5026221ac1620James Dong          }
2378050b28a593350047845a45a14cc5026221ac1620James Dong
237920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stsz");
238020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
2381be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            if (mSamplesHaveSameSize) {
23828644c14618d30d9e57a69df40ed939986ebf02c4James Dong                List<size_t>::iterator it = mSampleSizes.begin();
23838644c14618d30d9e57a69df40ed939986ebf02c4James Dong                mOwner->writeInt32(*it);  // default sample size
2384be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            } else {
2385be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mOwner->writeInt32(0);
2386be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
2387ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong            mOwner->writeInt32(mNumSamples);
2388be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            if (!mSamplesHaveSameSize) {
23898644c14618d30d9e57a69df40ed939986ebf02c4James Dong                for (List<size_t>::iterator it = mSampleSizes.begin();
23908644c14618d30d9e57a69df40ed939986ebf02c4James Dong                     it != mSampleSizes.end(); ++it) {
23918644c14618d30d9e57a69df40ed939986ebf02c4James Dong                    mOwner->writeInt32(*it);
2392be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                }
239320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
239420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stsz
239520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
239620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stsc");
239720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
23981f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            mOwner->writeInt32(mNumStscTableEntries);
239913aec890216948b0c364f8f92792129d0335f506James Dong            for (List<StscTableEntry>::iterator it = mStscTableEntries.begin();
240013aec890216948b0c364f8f92792129d0335f506James Dong                 it != mStscTableEntries.end(); ++it) {
240113aec890216948b0c364f8f92792129d0335f506James Dong                mOwner->writeInt32(it->firstChunk);
240213aec890216948b0c364f8f92792129d0335f506James Dong                mOwner->writeInt32(it->samplesPerChunk);
240313aec890216948b0c364f8f92792129d0335f506James Dong                mOwner->writeInt32(it->sampleDescriptionId);
240420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
240520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stsc
24061acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          mOwner->beginBox(use32BitOffset? "stco": "co64");
240720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
24081f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            mOwner->writeInt32(mNumStcoTableEntries);
240913aec890216948b0c364f8f92792129d0335f506James Dong            for (List<off_t>::iterator it = mChunkOffsets.begin();
241013aec890216948b0c364f8f92792129d0335f506James Dong                 it != mChunkOffsets.end(); ++it) {
24111acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                if (use32BitOffset) {
24121acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                    mOwner->writeInt32(static_cast<int32_t>(*it));
24131acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                } else {
24141acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                    mOwner->writeInt64((*it));
24151acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                }
241620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
24178f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong          mOwner->endBox();  // stco or co64
241820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
241920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->endBox();  // stbl
24201acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong       mOwner->endBox();  // minf
242120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->endBox();  // mdia
242220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOwner->endBox();  // trak
242320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
242420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
242520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
2426