MPEG4Writer.cpp revision 872a481558350634a3fd5cb67939de288af00ecb
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 <ctype.h>
2420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <pthread.h>
2520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MPEG4Writer.h>
2720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBuffer.h>
2820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h>
290c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber#include <media/stagefright/MediaDebug.h>
3018291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h>
3103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#include <media/stagefright/MediaErrors.h>
3220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaSource.h>
3320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/Utils.h>
34d599cd4573b5a2d5914c5040e0565ef866749b77James Dong#include <media/mediarecorder.h>
3520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber#include "include/ESDS.h"
3719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
3820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android {
3920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
401f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongstatic const int64_t kMax32BitFileSize = 0x007fffffffLL;
413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypeSeqParamSet = 0x07;
423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypePicParamSet = 0x08;
43872a481558350634a3fd5cb67939de288af00ecbJames Dongstatic const int64_t kVideoMediaTimeAdjustPeriodTimeUs = 10000000LL;  // 10s
443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
4520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Writer::Track {
4620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic:
4725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    Track(MPEG4Writer *owner, const sp<MediaSource> &source);
488f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
4920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    ~Track();
5020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t start(MetaData *params);
5237187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t stop();
5337187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t pause();
5425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool reachedEOS();
5520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
563b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber    int64_t getDurationUs() const;
57d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t getEstimatedTrackSizeBytes() const;
581acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    void writeTrackHeader(int32_t trackID, bool use32BitOffset = true);
591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void bufferChunk(int64_t timestampUs);
601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isAvc() const { return mIsAvc; }
611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isAudio() const { return mIsAudio; }
621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isMPEG4() const { return mIsMPEG4; }
631f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void addChunkOffset(off_t offset);
64dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    status_t dump(int fd, const Vector<String16>& args) const;
6520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate:
6720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Writer *mOwner;
6820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MetaData> mMeta;
69693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    sp<MediaSource> mSource;
7020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    volatile bool mDone;
71a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mPaused;
72a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mResumed;
731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAvc;
741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAudio;
751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsMPEG4;
76c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    int64_t mTrackDurationUs;
77e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
78e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    // For realtime applications, we need to adjust the media clock
79e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    // for video track based on the audio media clock
80e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    bool mIsRealTimeRecording;
81e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    int64_t mMaxTimeStampUs;
82d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t mEstimatedTrackSizeBytes;
831f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    int64_t mMdatSizeBytes;
848f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int32_t mTimeScale;
8520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_t mThread;
8720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
88ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    // mNumSamples is used to track how many samples in mSampleSizes List.
89ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    // This is to reduce the cost associated with mSampleSizes.size() call,
90ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    // since it is O(n). Ideally, the fix should be in List class.
91ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    size_t              mNumSamples;
928644c14618d30d9e57a69df40ed939986ebf02c4James Dong    List<size_t>        mSampleSizes;
93be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    bool                mSamplesHaveSameSize;
94be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
9513aec890216948b0c364f8f92792129d0335f506James Dong    List<MediaBuffer *> mChunkSamples;
961f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
971f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    size_t              mNumStcoTableEntries;
9813aec890216948b0c364f8f92792129d0335f506James Dong    List<off_t>         mChunkOffsets;
9913aec890216948b0c364f8f92792129d0335f506James Dong
1001f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    size_t              mNumStscTableEntries;
10113aec890216948b0c364f8f92792129d0335f506James Dong    struct StscTableEntry {
10213aec890216948b0c364f8f92792129d0335f506James Dong
10313aec890216948b0c364f8f92792129d0335f506James Dong        StscTableEntry(uint32_t chunk, uint32_t samples, uint32_t id)
10413aec890216948b0c364f8f92792129d0335f506James Dong            : firstChunk(chunk),
10513aec890216948b0c364f8f92792129d0335f506James Dong              samplesPerChunk(samples),
10613aec890216948b0c364f8f92792129d0335f506James Dong              sampleDescriptionId(id) {}
10713aec890216948b0c364f8f92792129d0335f506James Dong
10813aec890216948b0c364f8f92792129d0335f506James Dong        uint32_t firstChunk;
10913aec890216948b0c364f8f92792129d0335f506James Dong        uint32_t samplesPerChunk;
11013aec890216948b0c364f8f92792129d0335f506James Dong        uint32_t sampleDescriptionId;
11113aec890216948b0c364f8f92792129d0335f506James Dong    };
11213aec890216948b0c364f8f92792129d0335f506James Dong    List<StscTableEntry> mStscTableEntries;
11320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1141f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    size_t        mNumStssTableEntries;
115050b28a593350047845a45a14cc5026221ac1620James Dong    List<int32_t> mStssTableEntries;
116050b28a593350047845a45a14cc5026221ac1620James Dong
1171f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    size_t        mNumSttsTableEntries;
118be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    struct SttsTableEntry {
119be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
1208f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        SttsTableEntry(uint32_t count, uint32_t durationUs)
1218f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            : sampleCount(count), sampleDurationUs(durationUs) {}
122be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
123be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        uint32_t sampleCount;
1248f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        uint32_t sampleDurationUs;
125be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    };
126be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    List<SttsTableEntry> mSttsTableEntries;
127be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
1283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Sequence parameter set or picture parameter set
1293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    struct AVCParamSet {
1303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        AVCParamSet(uint16_t length, const uint8_t *data)
1313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            : mLength(length), mData(data) {}
1323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
1333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t mLength;
1343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *mData;
1353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    };
1363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    List<AVCParamSet> mSeqParamSets;
1373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    List<AVCParamSet> mPicParamSets;
1383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mProfileIdc;
1393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mProfileCompatible;
1403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mLevelIdc;
1413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
14220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *mCodecSpecificData;
14320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t mCodecSpecificDataSize;
144548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    bool mGotAllCodecSpecificData;
14593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    bool mTrackingProgressStatus;
14620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool mReachedEOS;
1483c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    int64_t mStartTimestampUs;
14993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mPreviousTrackTimeUs;
15093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mTrackEveryTimeDurationUs;
15125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
152872a481558350634a3fd5cb67939de288af00ecbJames Dong    // Has the media time adjustment for video started?
153872a481558350634a3fd5cb67939de288af00ecbJames Dong    bool    mIsMediaTimeAdjustmentOn;
154872a481558350634a3fd5cb67939de288af00ecbJames Dong    // The time stamp when previous media time adjustment period starts
155872a481558350634a3fd5cb67939de288af00ecbJames Dong    int64_t mPrevMediaTimeAdjustTimestampUs;
156872a481558350634a3fd5cb67939de288af00ecbJames Dong    // Number of vidoe frames whose time stamp may be adjusted
157872a481558350634a3fd5cb67939de288af00ecbJames Dong    int64_t mMediaTimeAdjustNumFrames;
158872a481558350634a3fd5cb67939de288af00ecbJames Dong    // The sample number when previous meida time adjustmnet period starts
159872a481558350634a3fd5cb67939de288af00ecbJames Dong    int64_t mPrevMediaTimeAdjustSample;
160872a481558350634a3fd5cb67939de288af00ecbJames Dong    // The total accumulated drift time within a period of
161872a481558350634a3fd5cb67939de288af00ecbJames Dong    // kVideoMediaTimeAdjustPeriodTimeUs.
162872a481558350634a3fd5cb67939de288af00ecbJames Dong    int64_t mTotalDriftTimeToAdjustUs;
163872a481558350634a3fd5cb67939de288af00ecbJames Dong    // The total accumalated drift time since the start of the recording
164872a481558350634a3fd5cb67939de288af00ecbJames Dong    // excluding the current time adjustment period
165872a481558350634a3fd5cb67939de288af00ecbJames Dong    int64_t mPrevTotalAccumDriftTimeUs;
166872a481558350634a3fd5cb67939de288af00ecbJames Dong
167872a481558350634a3fd5cb67939de288af00ecbJames Dong    // Update the audio track's drift information.
168872a481558350634a3fd5cb67939de288af00ecbJames Dong    void updateDriftTime(const sp<MetaData>& meta);
169872a481558350634a3fd5cb67939de288af00ecbJames Dong
170872a481558350634a3fd5cb67939de288af00ecbJames Dong    // Adjust the time stamp of the video track according to
171872a481558350634a3fd5cb67939de288af00ecbJames Dong    // the drift time information from the audio track.
172872a481558350634a3fd5cb67939de288af00ecbJames Dong    void adjustMediaTime(int64_t *timestampUs);
173872a481558350634a3fd5cb67939de288af00ecbJames Dong
17420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    static void *ThreadWrapper(void *me);
17537187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t threadEntry();
17620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *parseParamSet(
1783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen);
1793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
18003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    status_t makeAVCCodecSpecificData(
18103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            const uint8_t *data, size_t size);
1823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    status_t copyAVCCodecSpecificData(
1833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            const uint8_t *data, size_t size);
1843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    status_t parseAVCCodecSpecificData(
1853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            const uint8_t *data, size_t size);
186215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong
187215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    // Track authoring progress status
188faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    void trackProgressStatus(int64_t timeUs, status_t err = OK);
18993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    void initTrackingProgressStatus(MetaData *params);
19003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
19119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    void getCodecSpecificDataFromInputFormatIfPossible();
19219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
193c059860c73678a202bfa33062723e8f82fb779d9James Dong    // Determine the track time scale
194c059860c73678a202bfa33062723e8f82fb779d9James Dong    // If it is an audio track, try to use the sampling rate as
195c059860c73678a202bfa33062723e8f82fb779d9James Dong    // the time scale; however, if user chooses the overwrite
196c059860c73678a202bfa33062723e8f82fb779d9James Dong    // value, the user-supplied time scale will be used.
197c059860c73678a202bfa33062723e8f82fb779d9James Dong    void setTimeScale();
198c059860c73678a202bfa33062723e8f82fb779d9James Dong
199690f546b0ee548dbfe997df36418e5302ec2d786James Dong    // Simple validation on the codec specific data
200690f546b0ee548dbfe997df36418e5302ec2d786James Dong    status_t checkCodecSpecificData() const;
201690f546b0ee548dbfe997df36418e5302ec2d786James Dong
2021f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void updateTrackSizeEstimate();
2031f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void addOneStscTableEntry(size_t chunkId, size_t sampleId);
2041f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void addOneStssTableEntry(size_t sampleId);
2051f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void addOneSttsTableEntry(size_t sampleCount, int64_t durationUs);
2061f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
20720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track(const Track &);
20820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track &operator=(const Track &);
20920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
21020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
21120111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::MPEG4Writer(const char *filename)
21220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mFile(fopen(filename, "wb")),
213b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong      mUse4ByteNalLength(true),
2141acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong      mUse32BitOffset(true),
215a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
216a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mStarted(false),
21720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOffset(0),
21813aec890216948b0c364f8f92792129d0335f506James Dong      mMdatOffset(0),
2197837c17063a4c50bc856ba59418516fdab731de7James Dong      mEstimatedMoovBoxSize(0),
220f01528f435e6b1f02d118fcd8305a148c27a89f1James Dong      mInterleaveDurationUs(1000000) {
2210c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(mFile != NULL);
22220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
22320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
22430ab66297501757d745b9ae10da61adcd891f497Andreas HuberMPEG4Writer::MPEG4Writer(int fd)
22530ab66297501757d745b9ae10da61adcd891f497Andreas Huber    : mFile(fdopen(fd, "wb")),
226b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong      mUse4ByteNalLength(true),
2271acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong      mUse32BitOffset(true),
228a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
229a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mStarted(false),
23030ab66297501757d745b9ae10da61adcd891f497Andreas Huber      mOffset(0),
23113aec890216948b0c364f8f92792129d0335f506James Dong      mMdatOffset(0),
2327837c17063a4c50bc856ba59418516fdab731de7James Dong      mEstimatedMoovBoxSize(0),
233f01528f435e6b1f02d118fcd8305a148c27a89f1James Dong      mInterleaveDurationUs(1000000) {
23430ab66297501757d745b9ae10da61adcd891f497Andreas Huber    CHECK(mFile != NULL);
23530ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
23630ab66297501757d745b9ae10da61adcd891f497Andreas Huber
23720111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() {
23820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    stop();
23920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2401f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    while (!mTracks.empty()) {
2411f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        List<Track *>::iterator it = mTracks.begin();
24220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        delete *it;
2431f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        (*it) = NULL;
2441f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mTracks.erase(it);
24520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
24620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.clear();
24720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
24820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
249dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::dump(
250dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        int fd, const Vector<String16>& args) {
251dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    const size_t SIZE = 256;
252dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    char buffer[SIZE];
253dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    String8 result;
254dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "   MPEG4Writer %p\n", this);
255dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
256dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "     mStarted: %s\n", mStarted? "true": "false");
257dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
258dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    ::write(fd, result.string(), result.size());
259dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    for (List<Track *>::iterator it = mTracks.begin();
260dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong         it != mTracks.end(); ++it) {
261dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        (*it)->dump(fd, args);
262dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    }
263dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    return OK;
264dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong}
265dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong
266dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::Track::dump(
267dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        int fd, const Vector<String16>& args) const {
268dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    const size_t SIZE = 256;
269dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    char buffer[SIZE];
270dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    String8 result;
271dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "     %s track\n", mIsAudio? "Audio": "Video");
272dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
273dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "       reached EOS: %s\n",
274dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong            mReachedEOS? "true": "false");
275dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
276dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    ::write(fd, result.string(), result.size());
277dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    return OK;
278dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong}
279dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong
2802dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huberstatus_t MPEG4Writer::addSource(const sp<MediaSource> &source) {
28125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    Track *track = new Track(this, source);
28220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.push_back(track);
2832dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
2842dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    return OK;
28520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
28620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
28793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::startTracks(MetaData *params) {
288a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
289a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
29093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        status_t err = (*it)->start(params);
291a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
292a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (err != OK) {
293a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            for (List<Track *>::iterator it2 = mTracks.begin();
294a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                 it2 != it; ++it2) {
295a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                (*it2)->stop();
296a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            }
297a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
298a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            return err;
299a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
300a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
301a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    return OK;
302a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
303a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
3042dec2b5be2056c6d9428897dc672185872d30d17James Dongint64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) {
3052dec2b5be2056c6d9428897dc672185872d30d17James Dong    // This implementation is highly experimental/heurisitic.
3062dec2b5be2056c6d9428897dc672185872d30d17James Dong    //
3072dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Statistical analysis shows that metadata usually accounts
3082dec2b5be2056c6d9428897dc672185872d30d17James Dong    // for a small portion of the total file size, usually < 0.6%.
3092dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Currently, lets set to 0.4% for now.
3102dec2b5be2056c6d9428897dc672185872d30d17James Dong
3112dec2b5be2056c6d9428897dc672185872d30d17James Dong    // The default MIN_MOOV_BOX_SIZE is set to 0.4% x 1MB,
3122dec2b5be2056c6d9428897dc672185872d30d17James Dong    // where 1MB is the common file size limit for MMS application.
3132dec2b5be2056c6d9428897dc672185872d30d17James Dong    // The default MAX _MOOV_BOX_SIZE value is based on about 4
3142dec2b5be2056c6d9428897dc672185872d30d17James Dong    // minute video recording with a bit rate about 3 Mbps, because
3152dec2b5be2056c6d9428897dc672185872d30d17James Dong    // statistics also show that most of the video captured are going
3162dec2b5be2056c6d9428897dc672185872d30d17James Dong    // to be less than 3 minutes.
3172dec2b5be2056c6d9428897dc672185872d30d17James Dong
3182dec2b5be2056c6d9428897dc672185872d30d17James Dong    // If the estimation is wrong, we will pay the price of wasting
3192dec2b5be2056c6d9428897dc672185872d30d17James Dong    // some reserved space. This should not happen so often statistically.
3202dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int32_t factor = mUse32BitOffset? 1: 2;
3212dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int64_t MIN_MOOV_BOX_SIZE = 4 * 1024;  // 4 KB
3222dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000);
3232dec2b5be2056c6d9428897dc672185872d30d17James Dong    int64_t size = MIN_MOOV_BOX_SIZE;
3242dec2b5be2056c6d9428897dc672185872d30d17James Dong
3252dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (mMaxFileSizeLimitBytes != 0) {
3262dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = mMaxFileSizeLimitBytes * 4 / 1000;
3272dec2b5be2056c6d9428897dc672185872d30d17James Dong    } else if (mMaxFileDurationLimitUs != 0) {
3282dec2b5be2056c6d9428897dc672185872d30d17James Dong        if (bitRate <= 0) {
3292dec2b5be2056c6d9428897dc672185872d30d17James Dong            // We could not estimate the file size since bitRate is not set.
3302dec2b5be2056c6d9428897dc672185872d30d17James Dong            size = MIN_MOOV_BOX_SIZE;
3312dec2b5be2056c6d9428897dc672185872d30d17James Dong        } else {
3322dec2b5be2056c6d9428897dc672185872d30d17James Dong            size = ((mMaxFileDurationLimitUs * bitRate * 4) / 1000 / 8000000);
3332dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
3342dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
3352dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size < MIN_MOOV_BOX_SIZE) {
3362dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MIN_MOOV_BOX_SIZE;
3372dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
3382dec2b5be2056c6d9428897dc672185872d30d17James Dong
3392dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Any long duration recording will be probably end up with
3402dec2b5be2056c6d9428897dc672185872d30d17James Dong    // non-streamable mp4 file.
3412dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size > MAX_MOOV_BOX_SIZE) {
3422dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MAX_MOOV_BOX_SIZE;
3432dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
3442dec2b5be2056c6d9428897dc672185872d30d17James Dong
345872a481558350634a3fd5cb67939de288af00ecbJames Dong    LOGV("limits: %lld/%lld bytes/us, bit rate: %d bps and the estimated"
3462dec2b5be2056c6d9428897dc672185872d30d17James Dong         " moov size %lld bytes",
3472dec2b5be2056c6d9428897dc672185872d30d17James Dong         mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size);
3482dec2b5be2056c6d9428897dc672185872d30d17James Dong    return factor * size;
3492dec2b5be2056c6d9428897dc672185872d30d17James Dong}
3502dec2b5be2056c6d9428897dc672185872d30d17James Dong
3512dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t MPEG4Writer::start(MetaData *param) {
35220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mFile == NULL) {
35325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return UNKNOWN_ERROR;
35420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
35520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3562dec2b5be2056c6d9428897dc672185872d30d17James Dong    int32_t use64BitOffset;
3572dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (param &&
3582dec2b5be2056c6d9428897dc672185872d30d17James Dong        param->findInt32(kKey64BitFileOffset, &use64BitOffset) &&
3592dec2b5be2056c6d9428897dc672185872d30d17James Dong        use64BitOffset) {
3602dec2b5be2056c6d9428897dc672185872d30d17James Dong        mUse32BitOffset = false;
3612dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
3622dec2b5be2056c6d9428897dc672185872d30d17James Dong
3631f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    if (mUse32BitOffset) {
3641f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // Implicit 32 bit file size limit
3651f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        if (mMaxFileSizeLimitBytes == 0) {
3661f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            mMaxFileSizeLimitBytes = kMax32BitFileSize;
3671f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        }
3681f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
3691f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // If file size is set to be larger than the 32 bit file
3701f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // size limit, treat it as an error.
3711f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        if (mMaxFileSizeLimitBytes > kMax32BitFileSize) {
372872a481558350634a3fd5cb67939de288af00ecbJames Dong            LOGW("32-bit file size limit (%lld bytes) too big. "
373d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong                 "It is changed to %lld bytes",
374d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong                mMaxFileSizeLimitBytes, kMax32BitFileSize);
375d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong            mMaxFileSizeLimitBytes = kMax32BitFileSize;
3761f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        }
3771f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    }
3781f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
379b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    int32_t use2ByteNalLength;
380b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (param &&
381b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        param->findInt32(kKey2ByteNalLength, &use2ByteNalLength) &&
382b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        use2ByteNalLength) {
383b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mUse4ByteNalLength = false;
3842dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
3852dec2b5be2056c6d9428897dc672185872d30d17James Dong
386065d1aff96818df54456053f1574aec8a234d0deJames Dong    mStartTimestampUs = -1;
38793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
388a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (mStarted) {
389a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused) {
390a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mPaused = false;
39193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            return startTracks(param);
392a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
393a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
394a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
395a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
3968f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    if (!param ||
3978f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        !param->findInt32(kKeyTimeScale, &mTimeScale)) {
3988f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        mTimeScale = 1000;
3998f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    }
4008f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    CHECK(mTimeScale > 0);
4018f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    LOGV("movie time scale: %d", mTimeScale);
4028f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
4037837c17063a4c50bc856ba59418516fdab731de7James Dong    mStreamableFile = true;
4047837c17063a4c50bc856ba59418516fdab731de7James Dong    mWriteMoovBoxToMemory = false;
4057837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBuffer = NULL;
4067837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
4077837c17063a4c50bc856ba59418516fdab731de7James Dong
40820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    beginBox("ftyp");
40993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong      {
41093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        int32_t fileType;
41193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (param && param->findInt32(kKeyFileType, &fileType) &&
41293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            fileType != OUTPUT_FORMAT_MPEG_4) {
41393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            writeFourcc("3gp4");
41493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        } else {
41593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            writeFourcc("isom");
41693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
41793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong      }
41820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      writeInt32(0);
41920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      writeFourcc("isom");
42093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong      writeFourcc("3gp4");
42120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    endBox();
42220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4237837c17063a4c50bc856ba59418516fdab731de7James Dong    mFreeBoxOffset = mOffset;
42420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4257837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mEstimatedMoovBoxSize == 0) {
4262dec2b5be2056c6d9428897dc672185872d30d17James Dong        int32_t bitRate = -1;
4272dec2b5be2056c6d9428897dc672185872d30d17James Dong        if (param) {
4282dec2b5be2056c6d9428897dc672185872d30d17James Dong            param->findInt32(kKeyBitRate, &bitRate);
4292dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
4302dec2b5be2056c6d9428897dc672185872d30d17James Dong        mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate);
4317837c17063a4c50bc856ba59418516fdab731de7James Dong    }
4327837c17063a4c50bc856ba59418516fdab731de7James Dong    CHECK(mEstimatedMoovBoxSize >= 8);
4337837c17063a4c50bc856ba59418516fdab731de7James Dong    fseeko(mFile, mFreeBoxOffset, SEEK_SET);
4347837c17063a4c50bc856ba59418516fdab731de7James Dong    writeInt32(mEstimatedMoovBoxSize);
4357837c17063a4c50bc856ba59418516fdab731de7James Dong    write("free", 4);
4367837c17063a4c50bc856ba59418516fdab731de7James Dong
4377837c17063a4c50bc856ba59418516fdab731de7James Dong    mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize;
4387837c17063a4c50bc856ba59418516fdab731de7James Dong    mOffset = mMdatOffset;
4397837c17063a4c50bc856ba59418516fdab731de7James Dong    fseeko(mFile, mMdatOffset, SEEK_SET);
4401acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
4411acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("????mdat", 8);
4421acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
4431acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("\x00\x00\x00\x01mdat????????", 16);
4441acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
4451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
4461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    status_t err = startWriterThread();
4471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (err != OK) {
4481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        return err;
4491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
4501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
4511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    err = startTracks(param);
452a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (err != OK) {
453a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return err;
45420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
4551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
456a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mStarted = true;
45725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
45820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
45920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4601f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongbool MPEG4Writer::use32BitFileOffset() const {
4611f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    return mUse32BitOffset;
4621f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
4631f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
46437187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::pause() {
465a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (mFile == NULL) {
46637187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
467a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
468a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
46937187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = OK;
470a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
471a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
47237187916a486504acaf83bea30147eb5fbf46ae5James Dong        status_t status = (*it)->pause();
47337187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (status != OK) {
47437187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
47537187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
476a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
47737187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
478a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
479a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
4801c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::stopWriterThread() {
4811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("stopWriterThread");
4821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
4831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    {
4841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        Mutex::Autolock autolock(mLock);
4851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
4861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mDone = true;
4871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkReadyCondition.signal();
4881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
4891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
4901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void *dummy;
4911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_join(mThread, &dummy);
4921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
4931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
49437187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::stop() {
49520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mFile == NULL) {
49637187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
49720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
49820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
49937187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = OK;
5008f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t maxDurationUs = 0;
50120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
50220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber         it != mTracks.end(); ++it) {
50337187916a486504acaf83bea30147eb5fbf46ae5James Dong        status_t status = (*it)->stop();
50437187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (err == OK && status != OK) {
50537187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
50637187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
50720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5088f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int64_t durationUs = (*it)->getDurationUs();
5098f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        if (durationUs > maxDurationUs) {
5108f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            maxDurationUs = durationUs;
51120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
51220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
51320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    stopWriterThread();
5157837c17063a4c50bc856ba59418516fdab731de7James Dong
51637187916a486504acaf83bea30147eb5fbf46ae5James Dong    // Do not write out movie header on error.
51737187916a486504acaf83bea30147eb5fbf46ae5James Dong    if (err != OK) {
51837187916a486504acaf83bea30147eb5fbf46ae5James Dong        fflush(mFile);
51937187916a486504acaf83bea30147eb5fbf46ae5James Dong        fclose(mFile);
52037187916a486504acaf83bea30147eb5fbf46ae5James Dong        mFile = NULL;
52137187916a486504acaf83bea30147eb5fbf46ae5James Dong        mStarted = false;
52237187916a486504acaf83bea30147eb5fbf46ae5James Dong        return err;
52337187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
52437187916a486504acaf83bea30147eb5fbf46ae5James Dong
52520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // Fix up the size of the 'mdat' chunk.
5261acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
5271acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        fseeko(mFile, mMdatOffset, SEEK_SET);
5281acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        int32_t size = htonl(static_cast<int32_t>(mOffset - mMdatOffset));
5291acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        fwrite(&size, 1, 4, mFile);
5301acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
5311acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        fseeko(mFile, mMdatOffset + 8, SEEK_SET);
5321acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        int64_t size = mOffset - mMdatOffset;
5331acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        size = hton64(size);
5341acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        fwrite(&size, 1, 8, mFile);
5351acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
5367837c17063a4c50bc856ba59418516fdab731de7James Dong    fseeko(mFile, mOffset, SEEK_SET);
53720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
53820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    time_t now = time(NULL);
5397837c17063a4c50bc856ba59418516fdab731de7James Dong    const off_t moovOffset = mOffset;
5407837c17063a4c50bc856ba59418516fdab731de7James Dong    mWriteMoovBoxToMemory = true;
5417837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize);
5427837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
5437837c17063a4c50bc856ba59418516fdab731de7James Dong    CHECK(mMoovBoxBuffer != NULL);
544c059860c73678a202bfa33062723e8f82fb779d9James Dong    int32_t duration = (maxDurationUs * mTimeScale + 5E5) / 1E6;
54520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
54620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    beginBox("moov");
54720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
54820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      beginBox("mvhd");
54920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // version=0, flags=0
55020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(now);           // creation time
55120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(now);           // modification time
5528f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        writeInt32(mTimeScale);    // mvhd timescale
5531acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        writeInt32(duration);
5541acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        writeInt32(0x10000);       // rate: 1.0
55520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt16(0x100);         // volume
55620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt16(0);             // reserved
55720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // reserved
55820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // reserved
55920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0x10000);       // matrix
56020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
56120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
56220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
56320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0x10000);
56420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
56520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
56620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
56720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0x40000000);
56820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
56920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
57020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
57120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
57220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
57320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
57420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(mTracks.size() + 1);  // nextTrackID
57520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      endBox();  // mvhd
57620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
57720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      int32_t id = 1;
57820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      for (List<Track *>::iterator it = mTracks.begin();
57920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber           it != mTracks.end(); ++it, ++id) {
5801acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          (*it)->writeTrackHeader(id, mUse32BitOffset);
58120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      }
58220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    endBox();  // moov
58320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5847837c17063a4c50bc856ba59418516fdab731de7James Dong    mWriteMoovBoxToMemory = false;
5857837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mStreamableFile) {
5867837c17063a4c50bc856ba59418516fdab731de7James Dong        CHECK(mMoovBoxBufferOffset + 8 <= mEstimatedMoovBoxSize);
5877837c17063a4c50bc856ba59418516fdab731de7James Dong
5887837c17063a4c50bc856ba59418516fdab731de7James Dong        // Moov box
5897837c17063a4c50bc856ba59418516fdab731de7James Dong        fseeko(mFile, mFreeBoxOffset, SEEK_SET);
5907837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset = mFreeBoxOffset;
5917837c17063a4c50bc856ba59418516fdab731de7James Dong        write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, mFile);
5927837c17063a4c50bc856ba59418516fdab731de7James Dong
5937837c17063a4c50bc856ba59418516fdab731de7James Dong        // Free box
5942dec2b5be2056c6d9428897dc672185872d30d17James Dong        fseeko(mFile, mOffset, SEEK_SET);
5957837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset);
5967837c17063a4c50bc856ba59418516fdab731de7James Dong        write("free", 4);
5977837c17063a4c50bc856ba59418516fdab731de7James Dong
5987837c17063a4c50bc856ba59418516fdab731de7James Dong        // Free temp memory
5997837c17063a4c50bc856ba59418516fdab731de7James Dong        free(mMoovBoxBuffer);
6007837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBuffer = NULL;
6017837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBufferOffset = 0;
6022dec2b5be2056c6d9428897dc672185872d30d17James Dong    } else {
6032dec2b5be2056c6d9428897dc672185872d30d17James Dong        LOGI("The mp4 file will not be streamable.");
6047837c17063a4c50bc856ba59418516fdab731de7James Dong    }
6057837c17063a4c50bc856ba59418516fdab731de7James Dong
6060c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(mBoxes.empty());
60720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6087837c17063a4c50bc856ba59418516fdab731de7James Dong    fflush(mFile);
60920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fclose(mFile);
61020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mFile = NULL;
611a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mStarted = false;
61237187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
61320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
61420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
61513aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) {
61613aec890216948b0c364f8f92792129d0335f506James Dong    mInterleaveDurationUs = durationUs;
61713aec890216948b0c364f8f92792129d0335f506James Dong    return OK;
61813aec890216948b0c364f8f92792129d0335f506James Dong}
61913aec890216948b0c364f8f92792129d0335f506James Dong
62013aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() {
62113aec890216948b0c364f8f92792129d0335f506James Dong    mLock.lock();
62213aec890216948b0c364f8f92792129d0335f506James Dong}
62313aec890216948b0c364f8f92792129d0335f506James Dong
62413aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() {
62513aec890216948b0c364f8f92792129d0335f506James Dong    mLock.unlock();
62613aec890216948b0c364f8f92792129d0335f506James Dong}
62720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
62813aec890216948b0c364f8f92792129d0335f506James Dongoff_t MPEG4Writer::addSample_l(MediaBuffer *buffer) {
62920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    off_t old_offset = mOffset;
63020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
63120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fwrite((const uint8_t *)buffer->data() + buffer->range_offset(),
63220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber           1, buffer->range_length(), mFile);
63320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
63420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += buffer->range_length();
63520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
63620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return old_offset;
63720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
63820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
63903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) {
64003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (buffer->range_length() < 4) {
64103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return;
64203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
64303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
64403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    const uint8_t *ptr =
64503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        (const uint8_t *)buffer->data() + buffer->range_offset();
64603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
64703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) {
64803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        buffer->set_range(
64903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                buffer->range_offset() + 4, buffer->range_length() - 4);
65003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
65103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
65203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
65313aec890216948b0c364f8f92792129d0335f506James Dongoff_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) {
65430ab66297501757d745b9ae10da61adcd891f497Andreas Huber    off_t old_offset = mOffset;
65530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
65630ab66297501757d745b9ae10da61adcd891f497Andreas Huber    size_t length = buffer->range_length();
65703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
658b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (mUse4ByteNalLength) {
659b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        uint8_t x = length >> 24;
660b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        fwrite(&x, 1, 1, mFile);
661b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = (length >> 16) & 0xff;
662b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        fwrite(&x, 1, 1, mFile);
663b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = (length >> 8) & 0xff;
664b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        fwrite(&x, 1, 1, mFile);
665b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = length & 0xff;
666b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        fwrite(&x, 1, 1, mFile);
667b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong
668b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        fwrite((const uint8_t *)buffer->data() + buffer->range_offset(),
669b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                1, length, mFile);
670b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mOffset += length + 4;
671b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    } else {
672b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        CHECK(length < 65536);
67330ab66297501757d745b9ae10da61adcd891f497Andreas Huber
674b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        uint8_t x = length >> 8;
675b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        fwrite(&x, 1, 1, mFile);
676b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = length & 0xff;
677b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        fwrite(&x, 1, 1, mFile);
678b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        fwrite((const uint8_t *)buffer->data() + buffer->range_offset(),
679b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                1, length, mFile);
680b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mOffset += length + 2;
681b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    }
68230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
68330ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return old_offset;
68430ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
68530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
6867837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write(
6877837c17063a4c50bc856ba59418516fdab731de7James Dong        const void *ptr, size_t size, size_t nmemb, FILE *stream) {
6887837c17063a4c50bc856ba59418516fdab731de7James Dong
6897837c17063a4c50bc856ba59418516fdab731de7James Dong    const size_t bytes = size * nmemb;
6907837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
6911acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        off_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes;
6921acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        if (moovBoxSize > mEstimatedMoovBoxSize) {
6937837c17063a4c50bc856ba59418516fdab731de7James Dong            for (List<off_t>::iterator it = mBoxes.begin();
6947837c17063a4c50bc856ba59418516fdab731de7James Dong                 it != mBoxes.end(); ++it) {
6957837c17063a4c50bc856ba59418516fdab731de7James Dong                (*it) += mOffset;
6967837c17063a4c50bc856ba59418516fdab731de7James Dong            }
6977837c17063a4c50bc856ba59418516fdab731de7James Dong            fseeko(mFile, mOffset, SEEK_SET);
6987837c17063a4c50bc856ba59418516fdab731de7James Dong            fwrite(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, stream);
6997837c17063a4c50bc856ba59418516fdab731de7James Dong            fwrite(ptr, size, nmemb, stream);
7007837c17063a4c50bc856ba59418516fdab731de7James Dong            mOffset += (bytes + mMoovBoxBufferOffset);
7017837c17063a4c50bc856ba59418516fdab731de7James Dong            free(mMoovBoxBuffer);
7027837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBuffer = NULL;
7037837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset = 0;
7047837c17063a4c50bc856ba59418516fdab731de7James Dong            mWriteMoovBoxToMemory = false;
7057837c17063a4c50bc856ba59418516fdab731de7James Dong            mStreamableFile = false;
7067837c17063a4c50bc856ba59418516fdab731de7James Dong        } else {
7077837c17063a4c50bc856ba59418516fdab731de7James Dong            memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes);
7087837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset += bytes;
7097837c17063a4c50bc856ba59418516fdab731de7James Dong        }
7107837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
7117837c17063a4c50bc856ba59418516fdab731de7James Dong        fwrite(ptr, size, nmemb, stream);
7127837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset += bytes;
7137837c17063a4c50bc856ba59418516fdab731de7James Dong    }
7147837c17063a4c50bc856ba59418516fdab731de7James Dong    return bytes;
7157837c17063a4c50bc856ba59418516fdab731de7James Dong}
7167837c17063a4c50bc856ba59418516fdab731de7James Dong
71720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) {
7180c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(fourcc), 4);
71920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7207837c17063a4c50bc856ba59418516fdab731de7James Dong    mBoxes.push_back(mWriteMoovBoxToMemory?
7217837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset: mOffset);
72220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
72320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeInt32(0);
72420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeFourcc(fourcc);
72520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
72620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
72720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() {
7280c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(!mBoxes.empty());
72920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
73020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    off_t offset = *--mBoxes.end();
73120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mBoxes.erase(--mBoxes.end());
73220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7337837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
7347837c17063a4c50bc856ba59418516fdab731de7James Dong       int32_t x = htonl(mMoovBoxBufferOffset - offset);
7357837c17063a4c50bc856ba59418516fdab731de7James Dong       memcpy(mMoovBoxBuffer + offset, &x, 4);
7367837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
7377837c17063a4c50bc856ba59418516fdab731de7James Dong        fseeko(mFile, offset, SEEK_SET);
7387837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mOffset - offset);
7397837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset -= 4;
7407837c17063a4c50bc856ba59418516fdab731de7James Dong        fseeko(mFile, mOffset, SEEK_SET);
7417837c17063a4c50bc856ba59418516fdab731de7James Dong    }
74220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
74320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
74420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) {
7457837c17063a4c50bc856ba59418516fdab731de7James Dong    write(&x, 1, 1, mFile);
74620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
74720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
74820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) {
74920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htons(x);
7507837c17063a4c50bc856ba59418516fdab731de7James Dong    write(&x, 1, 2, mFile);
75120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
75220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
75320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) {
75420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htonl(x);
7557837c17063a4c50bc856ba59418516fdab731de7James Dong    write(&x, 1, 4, mFile);
75620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
75720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
75820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) {
75920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = hton64(x);
7607837c17063a4c50bc856ba59418516fdab731de7James Dong    write(&x, 1, 8, mFile);
76120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
76220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
76320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) {
76420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t n = strlen(s);
7657837c17063a4c50bc856ba59418516fdab731de7James Dong    write(s, 1, n + 1, mFile);
76620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
76720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
76820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) {
7690c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(s), 4);
7707837c17063a4c50bc856ba59418516fdab731de7James Dong    write(s, 1, 4, mFile);
77120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
77220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
77320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) {
7747837c17063a4c50bc856ba59418516fdab731de7James Dong    write(data, 1, size, mFile);
77520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
77620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
777d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() {
778d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
779d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileSizeLimitBytes == 0) {
780d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
781d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
782d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
783956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize);
784d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
785d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
786d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes();
787d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
7881f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
7891f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    return (nTotalBytesEstimate  + 1024 >= mMaxFileSizeLimitBytes);
790d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
791d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
792d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() {
793d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
794d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileDurationLimitUs == 0) {
795d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
796d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
797d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
798d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
799d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
800d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) {
801d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            return true;
802d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
803d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
804d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return false;
805d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
806d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
80725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() {
80825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool allDone = true;
80925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
81025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber         it != mTracks.end(); ++it) {
81125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        if (!(*it)->reachedEOS()) {
81225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            allDone = false;
81325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            break;
81425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        }
81525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
81625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
81725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return allDone;
81825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
81925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
820f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) {
821f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    LOGI("setStartTimestampUs: %lld", timeUs);
822f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    CHECK(timeUs >= 0);
8233c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
824065d1aff96818df54456053f1574aec8a234d0deJames Dong    if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) {
825f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mStartTimestampUs = timeUs;
826f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        LOGI("Earliest track starting time: %lld", mStartTimestampUs);
8273c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    }
8283c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
8293c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
830f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() {
8313c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
8323c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    return mStartTimestampUs;
8333c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
8343c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
83558ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() {
83658ae9c530247668f8af36e30d228c716c226b3d4James Dong    Mutex::Autolock autolock(mLock);
83758ae9c530247668f8af36e30d228c716c226b3d4James Dong    return mTracks.size();
83858ae9c530247668f8af36e30d228c716c226b3d4James Dong}
83958ae9c530247668f8af36e30d228c716c226b3d4James Dong
84020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
84120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
84220111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track(
84325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        MPEG4Writer *owner, const sp<MediaSource> &source)
84420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mOwner(owner),
84525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mMeta(source->getFormat()),
84620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSource(source),
84720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDone(false),
848a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
849a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mResumed(false),
850c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong      mTrackDurationUs(0),
851956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      mEstimatedTrackSizeBytes(0),
852be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong      mSamplesHaveSameSize(true),
85320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCodecSpecificData(NULL),
85425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mCodecSpecificDataSize(0),
855548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber      mGotAllCodecSpecificData(false),
85625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mReachedEOS(false) {
85719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    getCodecSpecificDataFromInputFormatIfPossible();
8588f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
8591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    const char *mime;
8601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mMeta->findCString(kKeyMIMEType, &mime);
8611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
8621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAudio = !strncasecmp(mime, "audio/", 6);
8631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
8641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong               !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC);
8651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
866c059860c73678a202bfa33062723e8f82fb779d9James Dong    setTimeScale();
867c059860c73678a202bfa33062723e8f82fb779d9James Dong}
868c059860c73678a202bfa33062723e8f82fb779d9James Dong
8691f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::updateTrackSizeEstimate() {
8701f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
8711f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    int64_t stcoBoxSizeBytes = mOwner->use32BitFileOffset()
8721f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                                ? mNumStcoTableEntries * 4
8731f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                                : mNumStcoTableEntries * 8;
8741f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
8751f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mNumSamples * 4);
8761f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
8771f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mEstimatedTrackSizeBytes = mMdatSizeBytes +             // media data size
8781f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                               mNumStscTableEntries * 12 +  // stsc box size
8791f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                               mNumStssTableEntries * 4 +   // stss box size
8801f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                               mNumSttsTableEntries * 8 +   // stts box size
8811f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                               stcoBoxSizeBytes +           // stco box size
8821f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                               stszBoxSizeBytes;            // stsz box size
8831f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
8841f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
8851f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStscTableEntry(
8861f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        size_t chunkId, size_t sampleId) {
8871f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
8881f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        StscTableEntry stscEntry(chunkId, sampleId, 1);
8891f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mStscTableEntries.push_back(stscEntry);
8901f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        ++mNumStscTableEntries;
8911f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
8921f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
8931f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) {
8941f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mStssTableEntries.push_back(sampleId);
8951f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    ++mNumStssTableEntries;
8961f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
8971f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
8981f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneSttsTableEntry(
8991f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        size_t sampleCount, int64_t durationUs) {
9001f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
9011f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    SttsTableEntry sttsEntry(sampleCount, durationUs);
9021f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mSttsTableEntries.push_back(sttsEntry);
9031f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    ++mNumSttsTableEntries;
9041f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
9051f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
9061f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addChunkOffset(off_t offset) {
9071f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    ++mNumStcoTableEntries;
9081f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mChunkOffsets.push_back(offset);
9091f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
9101f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
911c059860c73678a202bfa33062723e8f82fb779d9James Dongvoid MPEG4Writer::Track::setTimeScale() {
912c059860c73678a202bfa33062723e8f82fb779d9James Dong    LOGV("setTimeScale");
913c059860c73678a202bfa33062723e8f82fb779d9James Dong    // Default time scale
914c059860c73678a202bfa33062723e8f82fb779d9James Dong    mTimeScale = 90000;
915c059860c73678a202bfa33062723e8f82fb779d9James Dong
916c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mIsAudio) {
917c059860c73678a202bfa33062723e8f82fb779d9James Dong        // Use the sampling rate as the default time scale for audio track.
918c059860c73678a202bfa33062723e8f82fb779d9James Dong        int32_t sampleRate;
919c059860c73678a202bfa33062723e8f82fb779d9James Dong        bool success = mMeta->findInt32(kKeySampleRate, &sampleRate);
920c059860c73678a202bfa33062723e8f82fb779d9James Dong        CHECK(success);
921c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = sampleRate;
922c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
923c059860c73678a202bfa33062723e8f82fb779d9James Dong
924c059860c73678a202bfa33062723e8f82fb779d9James Dong    // If someone would like to overwrite the timescale, use user-supplied value.
925c059860c73678a202bfa33062723e8f82fb779d9James Dong    int32_t timeScale;
926c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mMeta->findInt32(kKeyTimeScale, &timeScale)) {
927c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = timeScale;
928c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
929c059860c73678a202bfa33062723e8f82fb779d9James Dong
9308f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    CHECK(mTimeScale > 0);
93119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber}
93219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
93319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Hubervoid MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() {
93419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    const char *mime;
93519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
93619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
93719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
93819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        uint32_t type;
93919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        const void *data;
94019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        size_t size;
94119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        if (mMeta->findData(kKeyAVCC, &type, &data, &size)) {
94219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mCodecSpecificData = malloc(size);
94319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mCodecSpecificDataSize = size;
94419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            memcpy(mCodecSpecificData, data, size);
94519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mGotAllCodecSpecificData = true;
94619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        }
94719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
94819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
94919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        uint32_t type;
95019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        const void *data;
95119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        size_t size;
95219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        if (mMeta->findData(kKeyESDS, &type, &data, &size)) {
95319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            ESDS esds(data, size);
95419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            if (esds.getCodecSpecificInfo(&data, &size) == OK) {
95519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mCodecSpecificData = malloc(size);
95619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mCodecSpecificDataSize = size;
95719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                memcpy(mCodecSpecificData, data, size);
95819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mGotAllCodecSpecificData = true;
95919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            }
96019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        }
96119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
96220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
96320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
96420111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() {
96520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    stop();
96620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
96720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mCodecSpecificData != NULL) {
96820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        free(mCodecSpecificData);
96920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mCodecSpecificData = NULL;
97020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
97120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
97220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
97393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) {
97493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    LOGV("initTrackingProgressStatus");
97593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mPreviousTrackTimeUs = -1;
97693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackingProgressStatus = false;
97793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackEveryTimeDurationUs = 0;
97893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    {
97993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        int64_t timeUs;
98093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) {
98193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            LOGV("Receive request to track progress status for every %lld us", timeUs);
98293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackEveryTimeDurationUs = timeUs;
98393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackingProgressStatus = true;
98493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
98593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
98693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
98793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
9881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong// static
9891c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid *MPEG4Writer::ThreadWrapper(void *me) {
9901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("ThreadWrapper: %p", me);
9911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    MPEG4Writer *writer = static_cast<MPEG4Writer *>(me);
9921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    writer->threadFunc();
9931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return NULL;
9941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
9951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
9961c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::bufferChunk(const Chunk& chunk) {
9971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("bufferChunk: %p", chunk.mTrack);
9981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Mutex::Autolock autolock(mLock);
9991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    CHECK_EQ(mDone, false);
10001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
10011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
10021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
10031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
10041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (chunk.mTrack == it->mTrack) {  // Found owner
10051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            it->mChunks.push_back(chunk);
10061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.signal();
10071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            return;
10081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
10091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
10101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
10111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    CHECK("Received a chunk for a unknown track" == 0);
10121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
10131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
10141c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::writeFirstChunk(ChunkInfo* info) {
10151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("writeFirstChunk: %p", info->mTrack);
10161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
10171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    List<Chunk>::iterator chunkIt = info->mChunks.begin();
10181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<MediaBuffer *>::iterator it = chunkIt->mSamples.begin();
10191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != chunkIt->mSamples.end(); ++it) {
10201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
10211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        off_t offset = info->mTrack->isAvc()
10221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                            ? addLengthPrefixedSample_l(*it)
10231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                            : addSample_l(*it);
10241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (it == chunkIt->mSamples.begin()) {
10251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            info->mTrack->addChunkOffset(offset);
10261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
10271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
10281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
10291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    // Done with the current chunk.
10301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    // Release all the samples in this chunk.
10311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    while (!chunkIt->mSamples.empty()) {
10321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        List<MediaBuffer *>::iterator it = chunkIt->mSamples.begin();
10331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it)->release();
10341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it) = NULL;
10351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        chunkIt->mSamples.erase(it);
10361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
10371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    chunkIt->mSamples.clear();
10381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    info->mChunks.erase(chunkIt);
10391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
10401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
10411c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::writeChunks() {
10421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("writeChunks");
10431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    size_t outstandingChunks = 0;
10441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    while (!mChunkInfos.empty()) {
10451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        List<ChunkInfo>::iterator it = mChunkInfos.begin();
10461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        while (!it->mChunks.empty()) {
10471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            CHECK_EQ(OK, writeOneChunk());
10481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            ++outstandingChunks;
10491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
10501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        it->mTrack = NULL;
10511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkInfos.erase(it);
10521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
10531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mChunkInfos.clear();
10541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGD("%d chunks are written in the last batch", outstandingChunks);
10551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
10561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
10571c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::writeOneChunk() {
10581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("writeOneChunk");
10591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
10601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    // Find the smallest timestamp, and write that chunk out
10611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    // XXX: What if some track is just too slow?
10621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL;
10631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Track *track = NULL;
10641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
10651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
10661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (!it->mChunks.empty()) {
10671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            List<Chunk>::iterator chunkIt = it->mChunks.begin();
10681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (chunkIt->mTimeStampUs < minTimestampUs) {
10691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                minTimestampUs = chunkIt->mTimeStampUs;
10701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                track = it->mTrack;
10711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            }
10721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
10731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
10741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
10751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (track == NULL) {
10761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        LOGV("Nothing to be written after all");
10771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        return OK;
10781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
10791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
10801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (mIsFirstChunk) {
10811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsFirstChunk = false;
10821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
10831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
10841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
10851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (it->mTrack == track) {
10861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            writeFirstChunk(&(*it));
10871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
10881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
10891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return OK;
10901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
10911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
10921c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::threadFunc() {
10931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("threadFunc");
10941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
10951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    while (!mDone) {
10961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        {
10971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            Mutex::Autolock autolock(mLock);
10981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.wait(mLock);
10991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            CHECK_EQ(writeOneChunk(), OK);
11001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
11011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
11021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
11031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    {
11041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        // Write ALL samples
11051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        Mutex::Autolock autolock(mLock);
11061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        writeChunks();
11071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
11081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
11091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
11101c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::startWriterThread() {
11111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("startWriterThread");
11121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
11131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mDone = false;
11141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsFirstChunk = true;
1115e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    mDriftTimeUs = 0;
11161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<Track *>::iterator it = mTracks.begin();
11171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mTracks.end(); ++it) {
11181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        ChunkInfo info;
11191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        info.mTrack = *it;
11201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkInfos.push_back(info);
11211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
11221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
11231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_t attr;
11241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_init(&attr);
11251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
11261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_create(&mThread, &attr, ThreadWrapper, this);
11271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_destroy(&attr);
11281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return OK;
11291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
11301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
11311f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
113293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) {
1133a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (!mDone && mPaused) {
1134a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mPaused = false;
1135a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mResumed = true;
1136a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
1137a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
113825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
113993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t startTimeUs;
114019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) {
114119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        startTimeUs = 0;
114219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
114319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
1144d0ea545d8357e7d86ad5f19cb2c6499c91786473James Dong    mIsRealTimeRecording = false;
1145e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    {
1146e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        int32_t isNotRealTime;
1147e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        if (params && params->findInt32(kKeyNotRealTime, &isNotRealTime)) {
1148e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            mIsRealTimeRecording = (isNotRealTime == 0);
1149e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        }
1150e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    }
1151e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
115293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    initTrackingProgressStatus(params);
115393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
1154f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    sp<MetaData> meta = new MetaData;
1155f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    meta->setInt64(kKeyTime, startTimeUs);
1156f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    status_t err = mSource->start(meta.get());
115725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    if (err != OK) {
115825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        mDone = mReachedEOS = true;
115925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return err;
116025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
116120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
116220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_t attr;
116320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_init(&attr);
116420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
116520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
116620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = false;
1167c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs = 0;
116825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = false;
1169956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    mEstimatedTrackSizeBytes = 0;
11701f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mNumStcoTableEntries = 0;
11711f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mNumStssTableEntries = 0;
11721f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mNumStscTableEntries = 0;
11731f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mNumSttsTableEntries = 0;
11741f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mMdatSizeBytes = 0;
1175872a481558350634a3fd5cb67939de288af00ecbJames Dong    mIsMediaTimeAdjustmentOn = false;
1176872a481558350634a3fd5cb67939de288af00ecbJames Dong    mPrevMediaTimeAdjustTimestampUs = 0;
1177872a481558350634a3fd5cb67939de288af00ecbJames Dong    mMediaTimeAdjustNumFrames = 0;
1178872a481558350634a3fd5cb67939de288af00ecbJames Dong    mPrevMediaTimeAdjustSample = 0;
1179872a481558350634a3fd5cb67939de288af00ecbJames Dong    mTotalDriftTimeToAdjustUs = 0;
1180872a481558350634a3fd5cb67939de288af00ecbJames Dong    mPrevTotalAccumDriftTimeUs = 0;
118120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
118225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    pthread_create(&mThread, &attr, ThreadWrapper, this);
118320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_destroy(&attr);
118425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
118525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
118620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
118720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
118837187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::pause() {
1189a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
119037187916a486504acaf83bea30147eb5fbf46ae5James Dong    return OK;
1191a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
1192a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
119337187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::stop() {
119420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mDone) {
119537187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
119620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
119720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
119820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = true;
119920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
120020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *dummy;
120120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_join(mThread, &dummy);
120220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
120337187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = (status_t) dummy;
120437187916a486504acaf83bea30147eb5fbf46ae5James Dong
120537187916a486504acaf83bea30147eb5fbf46ae5James Dong    {
120637187916a486504acaf83bea30147eb5fbf46ae5James Dong        status_t status = mSource->stop();
120737187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (err == OK && status != OK && status != ERROR_END_OF_STREAM) {
120837187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
120937187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
121037187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
121137187916a486504acaf83bea30147eb5fbf46ae5James Dong
121237187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
121320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
121420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
121525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() {
121625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return mReachedEOS;
121725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
121825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
121920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static
122020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) {
122120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = static_cast<Track *>(me);
122220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
122337187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = track->threadEntry();
122437187916a486504acaf83bea30147eb5fbf46ae5James Dong    return (void *) err;
122520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
122620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic void getNalUnitType(uint8_t byte, uint8_t* type) {
12283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    LOGV("getNalUnitType: %d", byte);
12293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
12303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // nal_unit_type: 5-bit unsigned integer
12313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *type = (byte & 0x1F);
12323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
12333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
12343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t *findNextStartCode(
12353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length) {
12363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
12373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    LOGV("findNextStartCode: %p %d", data, length);
12383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
12393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t bytesLeft = length;
12403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    while (bytesLeft > 4  &&
12413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            memcmp("\x00\x00\x00\x01", &data[length - bytesLeft], 4)) {
12423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        --bytesLeft;
12433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
12443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (bytesLeft <= 4) {
12453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        bytesLeft = 0; // Last parameter set
12463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
12473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return &data[length - bytesLeft];
12483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
12493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
12503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongconst uint8_t *MPEG4Writer::Track::parseParamSet(
12513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen) {
12523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
12533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    LOGV("parseParamSet");
12543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    CHECK(type == kNalUnitTypeSeqParamSet ||
12553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong          type == kNalUnitTypePicParamSet);
12563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
12573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *nextStartCode = findNextStartCode(data, length);
12583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *paramSetLen = nextStartCode - data;
12593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (*paramSetLen == 0) {
12603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        LOGE("Param set is malformed, since its length is 0");
12613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return NULL;
12623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
12633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
12643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    AVCParamSet paramSet(*paramSetLen, data);
12653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (type == kNalUnitTypeSeqParamSet) {
12663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (*paramSetLen < 4) {
12673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Seq parameter set malformed");
12683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return NULL;
12693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
12703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mSeqParamSets.empty()) {
12713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc = data[1];
12723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileCompatible = data[2];
12733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mLevelIdc = data[3];
12743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
12753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (mProfileIdc != data[1] ||
12763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mProfileCompatible != data[2] ||
12773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mLevelIdc != data[3]) {
12783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                LOGE("Inconsistent profile/level found in seq parameter sets");
12793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return NULL;
12803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
12813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
12823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mSeqParamSets.push_back(paramSet);
12833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    } else {
12843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mPicParamSets.push_back(paramSet);
12853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
12863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return nextStartCode;
12873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
12883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
12893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::copyAVCCodecSpecificData(
12903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
12913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    LOGV("copyAVCCodecSpecificData");
12923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
12933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 2 bytes for each of the parameter set length field
12943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // plus the 7 bytes for the header
12953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (size < 4 + 7) {
12963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        LOGE("Codec specific data length too short: %d", size);
12973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return ERROR_MALFORMED;
12983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
12993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize = size;
13013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificData = malloc(size);
13023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    memcpy(mCodecSpecificData, data, size);
13033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
13043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
13053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::parseAVCCodecSpecificData(
13073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
13083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    LOGV("parseAVCCodecSpecificData");
13103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data starts with a start code.
13113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // SPS and PPS are separated with start codes.
13123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Also, SPS must come before PPS
13133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t type = kNalUnitTypeSeqParamSet;
13143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotSps = false;
13153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotPps = false;
13163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *tmp = data;
13173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *nextStartCode = data;
13183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t bytesLeft = size;
13193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t paramSetLen = 0;
13203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize = 0;
13213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) {
13223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        getNalUnitType(*(tmp + 4), &type);
13233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (type == kNalUnitTypeSeqParamSet) {
13243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (gotPps) {
13253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                LOGE("SPS must come before PPS");
13263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
13273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
13283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
13293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotSps = true;
13303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
13313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
13323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else if (type == kNalUnitTypePicParamSet) {
13333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
13343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                LOGE("SPS must come before PPS");
13353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
13363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
13373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotPps) {
13383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotPps = true;
13393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
13403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
13413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
13423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Only SPS and PPS Nal units are expected");
13433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
13443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
13453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nextStartCode == NULL) {
13473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
13483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
13493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Move on to find the next parameter set
13513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        bytesLeft -= nextStartCode - tmp;
13523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        tmp = nextStartCode;
13533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mCodecSpecificDataSize += (2 + paramSetLen);
13543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
13553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
13573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of seq parameter sets
13583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nSeqParamSets = mSeqParamSets.size();
13593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets == 0) {
13603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Cound not find sequence parameter set");
13613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
13623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
13633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets > 0x1F) {
13653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Too many seq parameter sets (%d) found", nSeqParamSets);
13663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
13673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
13683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
13693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
13713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of pic parameter sets
13723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nPicParamSets = mPicParamSets.size();
13733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets == 0) {
13743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Cound not find picture parameter set");
13753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
13763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
13773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets > 0xFF) {
13783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Too many pic parameter sets (%d) found", nPicParamSets);
13793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
13803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
13813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
13823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
13843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the profiles
13853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // These profiles requires additional parameter set extensions
13863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mProfileIdc == 100 || mProfileIdc == 110 ||
13873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc == 122 || mProfileIdc == 144) {
13883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Sorry, no support for profile_idc: %d!", mProfileIdc);
13893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return BAD_VALUE;
13903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
13913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
13923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
13943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
1395548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
139603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData(
139703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        const uint8_t *data, size_t size) {
1398548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
139903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (mCodecSpecificData != NULL) {
1400548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        LOGE("Already have codec specific data");
140103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
140203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
140303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
14043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (size < 4) {
14053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        LOGE("Codec specific data length too short: %d", size);
140603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
140703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
140803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
14093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data is in the form of AVCCodecSpecificData
14103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (memcmp("\x00\x00\x00\x01", data, 4)) {
14113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return copyAVCCodecSpecificData(data, size);
141203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
141303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
14143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (parseAVCCodecSpecificData(data, size) != OK) {
141503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
141603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
141703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
14183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // ISO 14496-15: AVC file format
14193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize += 7;  // 7 more bytes in the header
142003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    mCodecSpecificData = malloc(mCodecSpecificDataSize);
142103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    uint8_t *header = (uint8_t *)mCodecSpecificData;
14223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = 1;                     // version
14233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[1] = mProfileIdc;           // profile indication
14243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[2] = mProfileCompatible;    // profile compatibility
14253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[3] = mLevelIdc;
142603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
14273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne
1428b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (mOwner->useNalLengthFour()) {
1429b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        header[4] = 0xfc | 3;  // length size == 4 bytes
1430b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    } else {
1431b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        header[4] = 0xfc | 1;  // length size == 2 bytes
1432b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    }
143303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
14343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 3-bit '111' followed by 5-bit numSequenceParameterSets
14353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nSequenceParamSets = mSeqParamSets.size();
14363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[5] = 0xe0 | nSequenceParamSets;
14373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 6;
14383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mSeqParamSets.begin();
14393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mSeqParamSets.end(); ++it) {
14403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit sequence parameter set length
14413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t seqParamSetLength = it->mLength;
14423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = seqParamSetLength >> 8;
14433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = seqParamSetLength & 0xff;
14443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
14453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // SPS NAL unit (sequence parameter length bytes)
14463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, seqParamSetLength);
14473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + seqParamSetLength);
14483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
14493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
14503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 8-bit nPictureParameterSets
14513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nPictureParamSets = mPicParamSets.size();
14523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = nPictureParamSets;
14533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 1;
14543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mPicParamSets.begin();
14553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mPicParamSets.end(); ++it) {
14563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit picture parameter set length
14573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t picParamSetLength = it->mLength;
14583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = picParamSetLength >> 8;
14593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = picParamSetLength & 0xff;
14603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
14613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // PPS Nal unit (picture parameter set length bytes)
14623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, picParamSetLength);
14633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + picParamSetLength);
14643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
146503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
146603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    return OK;
146703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
146803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
1469872a481558350634a3fd5cb67939de288af00ecbJames Dong/*
1470872a481558350634a3fd5cb67939de288af00ecbJames Dong* The video track's media time adjustment for real-time applications
1471872a481558350634a3fd5cb67939de288af00ecbJames Dong* is described as follows:
1472872a481558350634a3fd5cb67939de288af00ecbJames Dong*
1473872a481558350634a3fd5cb67939de288af00ecbJames Dong* First, the media time adjustment is done for every period of
1474872a481558350634a3fd5cb67939de288af00ecbJames Dong* kVideoMediaTimeAdjustPeriodTimeUs. kVideoMediaTimeAdjustPeriodTimeUs
1475872a481558350634a3fd5cb67939de288af00ecbJames Dong* is currently a fixed value chosen heuristically. The value of
1476872a481558350634a3fd5cb67939de288af00ecbJames Dong* kVideoMediaTimeAdjustPeriodTimeUs should not be very large or very small
1477872a481558350634a3fd5cb67939de288af00ecbJames Dong* for two considerations: on one hand, a relatively large value
1478872a481558350634a3fd5cb67939de288af00ecbJames Dong* helps reduce large fluctuation of drift time in the audio encoding
1479872a481558350634a3fd5cb67939de288af00ecbJames Dong* path; while on the other hand, a relatively small value helps keep
1480872a481558350634a3fd5cb67939de288af00ecbJames Dong* restoring synchronization in audio/video more frequently. Note for the
1481872a481558350634a3fd5cb67939de288af00ecbJames Dong* very first period of kVideoMediaTimeAdjustPeriodTimeUs, there is
1482872a481558350634a3fd5cb67939de288af00ecbJames Dong* no media time adjustment for the video track.
1483872a481558350634a3fd5cb67939de288af00ecbJames Dong*
1484872a481558350634a3fd5cb67939de288af00ecbJames Dong* Second, the total accumulated audio track time drift found
1485872a481558350634a3fd5cb67939de288af00ecbJames Dong* in a period of kVideoMediaTimeAdjustPeriodTimeUs is distributed
1486872a481558350634a3fd5cb67939de288af00ecbJames Dong* over a stream of incoming video frames. The number of video frames
1487872a481558350634a3fd5cb67939de288af00ecbJames Dong* affected is determined based on the number of recorded video frames
1488872a481558350634a3fd5cb67939de288af00ecbJames Dong* within the past kVideoMediaTimeAdjustPeriodTimeUs period.
1489872a481558350634a3fd5cb67939de288af00ecbJames Dong* We choose to distribute the drift time over only a portion
1490872a481558350634a3fd5cb67939de288af00ecbJames Dong* (rather than all) of the total number of recorded video frames
1491872a481558350634a3fd5cb67939de288af00ecbJames Dong* in order to make sure that the video track media time adjustment is
1492872a481558350634a3fd5cb67939de288af00ecbJames Dong* completed for the current period before the next video track media
1493872a481558350634a3fd5cb67939de288af00ecbJames Dong* time adjustment period starts. Currently, the portion chosen is a
1494872a481558350634a3fd5cb67939de288af00ecbJames Dong* half (0.5).
1495872a481558350634a3fd5cb67939de288af00ecbJames Dong*
1496872a481558350634a3fd5cb67939de288af00ecbJames Dong* Last, various additional checks are performed to ensure that
1497872a481558350634a3fd5cb67939de288af00ecbJames Dong* the actual audio encoding path does not have too much drift.
1498872a481558350634a3fd5cb67939de288af00ecbJames Dong* In particular, 1) we want to limit the average incremental time
1499872a481558350634a3fd5cb67939de288af00ecbJames Dong* adjustment for each video frame to be less than a threshold
1500872a481558350634a3fd5cb67939de288af00ecbJames Dong* for a single period of kVideoMediaTimeAdjustPeriodTimeUs.
1501872a481558350634a3fd5cb67939de288af00ecbJames Dong* Currently, the threshold is set to 5 ms. If the average incremental
1502872a481558350634a3fd5cb67939de288af00ecbJames Dong* media time adjustment for a video frame is larger than the
1503872a481558350634a3fd5cb67939de288af00ecbJames Dong* threshold, the audio encoding path has too much time drift.
1504872a481558350634a3fd5cb67939de288af00ecbJames Dong* 2) We also want to limit the total time drift in the audio
1505872a481558350634a3fd5cb67939de288af00ecbJames Dong* encoding path to be less than a threshold for a period of
1506872a481558350634a3fd5cb67939de288af00ecbJames Dong* kVideoMediaTimeAdjustPeriodTimeUs. Currently, the threshold
1507872a481558350634a3fd5cb67939de288af00ecbJames Dong* is 0.5% of kVideoMediaTimeAdjustPeriodTimeUs. If the time drift of
1508872a481558350634a3fd5cb67939de288af00ecbJames Dong* the audio encoding path is larger than the threshold, the audio
1509872a481558350634a3fd5cb67939de288af00ecbJames Dong* encoding path has too much time drift. We treat the large time
1510872a481558350634a3fd5cb67939de288af00ecbJames Dong* drift of the audio encoding path as errors, since there is no
1511872a481558350634a3fd5cb67939de288af00ecbJames Dong* way to keep audio/video in synchronization for real-time
1512872a481558350634a3fd5cb67939de288af00ecbJames Dong* applications if the time drift is too large unless we drop some
1513872a481558350634a3fd5cb67939de288af00ecbJames Dong* video frames, which has its own problems that we don't want
1514872a481558350634a3fd5cb67939de288af00ecbJames Dong* to get into for the time being.
1515872a481558350634a3fd5cb67939de288af00ecbJames Dong*/
1516872a481558350634a3fd5cb67939de288af00ecbJames Dongvoid MPEG4Writer::Track::adjustMediaTime(int64_t *timestampUs) {
1517872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (*timestampUs - mPrevMediaTimeAdjustTimestampUs >=
1518872a481558350634a3fd5cb67939de288af00ecbJames Dong        kVideoMediaTimeAdjustPeriodTimeUs) {
1519872a481558350634a3fd5cb67939de288af00ecbJames Dong
1520872a481558350634a3fd5cb67939de288af00ecbJames Dong        LOGV("New media time adjustment period at %lld us", *timestampUs);
1521872a481558350634a3fd5cb67939de288af00ecbJames Dong        mIsMediaTimeAdjustmentOn = true;
1522872a481558350634a3fd5cb67939de288af00ecbJames Dong        mMediaTimeAdjustNumFrames =
1523872a481558350634a3fd5cb67939de288af00ecbJames Dong                (mNumSamples - mPrevMediaTimeAdjustSample) >> 1;
1524872a481558350634a3fd5cb67939de288af00ecbJames Dong
1525872a481558350634a3fd5cb67939de288af00ecbJames Dong        mPrevMediaTimeAdjustTimestampUs = *timestampUs;
1526872a481558350634a3fd5cb67939de288af00ecbJames Dong        mPrevMediaTimeAdjustSample = mNumSamples;
1527872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t totalAccumDriftTimeUs = mOwner->getDriftTimeUs();
1528872a481558350634a3fd5cb67939de288af00ecbJames Dong        mTotalDriftTimeToAdjustUs =
1529872a481558350634a3fd5cb67939de288af00ecbJames Dong                totalAccumDriftTimeUs - mPrevTotalAccumDriftTimeUs;
1530872a481558350634a3fd5cb67939de288af00ecbJames Dong
1531872a481558350634a3fd5cb67939de288af00ecbJames Dong        mPrevTotalAccumDriftTimeUs = totalAccumDriftTimeUs;
1532872a481558350634a3fd5cb67939de288af00ecbJames Dong
1533872a481558350634a3fd5cb67939de288af00ecbJames Dong        // Check on incremental adjusted time per frame
1534872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t adjustTimePerFrameUs =
1535872a481558350634a3fd5cb67939de288af00ecbJames Dong                mTotalDriftTimeToAdjustUs / mMediaTimeAdjustNumFrames;
1536872a481558350634a3fd5cb67939de288af00ecbJames Dong
1537872a481558350634a3fd5cb67939de288af00ecbJames Dong        if (adjustTimePerFrameUs < 0) {
1538872a481558350634a3fd5cb67939de288af00ecbJames Dong            adjustTimePerFrameUs = -adjustTimePerFrameUs;
1539872a481558350634a3fd5cb67939de288af00ecbJames Dong        }
1540872a481558350634a3fd5cb67939de288af00ecbJames Dong        if (adjustTimePerFrameUs >= 5000) {
1541872a481558350634a3fd5cb67939de288af00ecbJames Dong            LOGE("Adjusted time per video frame is %lld us",
1542872a481558350634a3fd5cb67939de288af00ecbJames Dong                adjustTimePerFrameUs);
1543872a481558350634a3fd5cb67939de288af00ecbJames Dong            CHECK(!"Video frame time adjustment is too large!");
1544872a481558350634a3fd5cb67939de288af00ecbJames Dong        }
1545872a481558350634a3fd5cb67939de288af00ecbJames Dong
1546872a481558350634a3fd5cb67939de288af00ecbJames Dong        // Check on total accumulated time drift within a period of
1547872a481558350634a3fd5cb67939de288af00ecbJames Dong        // kVideoMediaTimeAdjustPeriodTimeUs.
1548872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t driftPercentage = (mTotalDriftTimeToAdjustUs * 1000)
1549872a481558350634a3fd5cb67939de288af00ecbJames Dong                / kVideoMediaTimeAdjustPeriodTimeUs;
1550872a481558350634a3fd5cb67939de288af00ecbJames Dong
1551872a481558350634a3fd5cb67939de288af00ecbJames Dong        if (driftPercentage < 0) {
1552872a481558350634a3fd5cb67939de288af00ecbJames Dong            driftPercentage = -driftPercentage;
1553872a481558350634a3fd5cb67939de288af00ecbJames Dong        }
1554872a481558350634a3fd5cb67939de288af00ecbJames Dong        if (driftPercentage > 5) {
1555872a481558350634a3fd5cb67939de288af00ecbJames Dong            LOGE("Audio track has time drift %lld us over %lld us",
1556872a481558350634a3fd5cb67939de288af00ecbJames Dong                mTotalDriftTimeToAdjustUs,
1557872a481558350634a3fd5cb67939de288af00ecbJames Dong                kVideoMediaTimeAdjustPeriodTimeUs);
1558872a481558350634a3fd5cb67939de288af00ecbJames Dong
1559872a481558350634a3fd5cb67939de288af00ecbJames Dong            CHECK(!"The audio track media time drifts too much!");
1560872a481558350634a3fd5cb67939de288af00ecbJames Dong        }
1561872a481558350634a3fd5cb67939de288af00ecbJames Dong
1562872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
1563872a481558350634a3fd5cb67939de288af00ecbJames Dong
1564872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (mIsMediaTimeAdjustmentOn) {
1565872a481558350634a3fd5cb67939de288af00ecbJames Dong        if (mNumSamples - mPrevMediaTimeAdjustSample <=
1566872a481558350634a3fd5cb67939de288af00ecbJames Dong            mMediaTimeAdjustNumFrames) {
1567872a481558350634a3fd5cb67939de288af00ecbJames Dong
1568872a481558350634a3fd5cb67939de288af00ecbJames Dong            // Do media time incremental adjustment
1569872a481558350634a3fd5cb67939de288af00ecbJames Dong            int64_t incrementalAdjustTimeUs =
1570872a481558350634a3fd5cb67939de288af00ecbJames Dong                        (mTotalDriftTimeToAdjustUs *
1571872a481558350634a3fd5cb67939de288af00ecbJames Dong                            (mNumSamples - mPrevMediaTimeAdjustSample))
1572872a481558350634a3fd5cb67939de288af00ecbJames Dong                                / mMediaTimeAdjustNumFrames;
1573872a481558350634a3fd5cb67939de288af00ecbJames Dong
1574872a481558350634a3fd5cb67939de288af00ecbJames Dong            *timestampUs +=
1575872a481558350634a3fd5cb67939de288af00ecbJames Dong                (incrementalAdjustTimeUs + mPrevTotalAccumDriftTimeUs);
1576872a481558350634a3fd5cb67939de288af00ecbJames Dong
1577872a481558350634a3fd5cb67939de288af00ecbJames Dong            LOGV("Incremental video frame media time adjustment: %lld us",
1578872a481558350634a3fd5cb67939de288af00ecbJames Dong                (incrementalAdjustTimeUs + mPrevTotalAccumDriftTimeUs));
1579872a481558350634a3fd5cb67939de288af00ecbJames Dong        } else {
1580872a481558350634a3fd5cb67939de288af00ecbJames Dong            // Within the remaining adjustment period,
1581872a481558350634a3fd5cb67939de288af00ecbJames Dong            // no incremental adjustment is needed.
1582872a481558350634a3fd5cb67939de288af00ecbJames Dong            *timestampUs +=
1583872a481558350634a3fd5cb67939de288af00ecbJames Dong                (mTotalDriftTimeToAdjustUs + mPrevTotalAccumDriftTimeUs);
1584872a481558350634a3fd5cb67939de288af00ecbJames Dong
1585872a481558350634a3fd5cb67939de288af00ecbJames Dong            LOGV("Fixed video frame media time adjustment: %lld us",
1586872a481558350634a3fd5cb67939de288af00ecbJames Dong                (mTotalDriftTimeToAdjustUs + mPrevTotalAccumDriftTimeUs));
1587872a481558350634a3fd5cb67939de288af00ecbJames Dong        }
1588872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
1589872a481558350634a3fd5cb67939de288af00ecbJames Dong}
1590872a481558350634a3fd5cb67939de288af00ecbJames Dong
1591872a481558350634a3fd5cb67939de288af00ecbJames Dong/*
1592872a481558350634a3fd5cb67939de288af00ecbJames Dong * Updates the drift time from the audio track so that
1593872a481558350634a3fd5cb67939de288af00ecbJames Dong * the video track can get the updated drift time information
1594872a481558350634a3fd5cb67939de288af00ecbJames Dong * from the file writer. The fluctuation of the drift time of the audio
1595872a481558350634a3fd5cb67939de288af00ecbJames Dong * encoding path is smoothed out with a simple filter by giving a larger
1596872a481558350634a3fd5cb67939de288af00ecbJames Dong * weight to more recently drift time. The filter coefficients, 0.5 and 0.5,
1597872a481558350634a3fd5cb67939de288af00ecbJames Dong * are heuristically determined.
1598872a481558350634a3fd5cb67939de288af00ecbJames Dong */
1599872a481558350634a3fd5cb67939de288af00ecbJames Dongvoid MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) {
1600872a481558350634a3fd5cb67939de288af00ecbJames Dong    int64_t driftTimeUs = 0;
1601872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) {
1602872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t prevDriftTimeUs = mOwner->getDriftTimeUs();
1603872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1;
1604872a481558350634a3fd5cb67939de288af00ecbJames Dong        mOwner->setDriftTimeUs(timeUs);
1605872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
1606872a481558350634a3fd5cb67939de288af00ecbJames Dong}
1607872a481558350634a3fd5cb67939de288af00ecbJames Dong
160837187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::threadEntry() {
160930ab66297501757d745b9ae10da61adcd891f497Andreas Huber    int32_t count = 0;
161013aec890216948b0c364f8f92792129d0335f506James Dong    const int64_t interleaveDurationUs = mOwner->interleaveDuration();
161113aec890216948b0c364f8f92792129d0335f506James Dong    int64_t chunkTimestampUs = 0;
161213aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nChunks = 0;
161313aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nZeroLengthFrames = 0;
16148f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t lastTimestampUs = 0;  // Previous sample time stamp in ms
16158f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t lastDurationUs = 0;   // Between the previous two samples in ms
1616c059860c73678a202bfa33062723e8f82fb779d9James Dong    int64_t currDurationTicks = 0;  // Timescale based ticks
1617c059860c73678a202bfa33062723e8f82fb779d9James Dong    int64_t lastDurationTicks = 0;  // Timescale based ticks
16188f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int32_t sampleCount = 1;      // Sample count in the current stts table entry
1619be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    uint32_t previousSampleSize = 0;  // Size of the previous sample
1620a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    int64_t previousPausedDurationUs = 0;
16211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    int64_t timestampUs;
1622e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
1623d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong    sp<MetaData> meta_data;
162420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1625ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    mNumSamples = 0;
162693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t err = OK;
162720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBuffer *buffer;
162893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    while (!mDone && (err = mSource->read(&buffer)) == OK) {
162920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (buffer->range_length() == 0) {
163020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer->release();
163120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer = NULL;
163213aec890216948b0c364f8f92792129d0335f506James Dong            ++nZeroLengthFrames;
163320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            continue;
163420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
163520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1636a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // If the codec specific data has not been received yet, delay pause.
1637a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // After the codec specific data is received, discard what we received
1638a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // when the track is to be paused.
1639a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused && !mResumed) {
1640a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer->release();
1641a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer = NULL;
1642a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            continue;
1643a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
1644a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
164530ab66297501757d745b9ae10da61adcd891f497Andreas Huber        ++count;
164630ab66297501757d745b9ae10da61adcd891f497Andreas Huber
164703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        int32_t isCodecConfig;
164803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig)
164903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                && isCodecConfig) {
1650548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            CHECK(!mGotAllCodecSpecificData);
1651548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
16521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (mIsAvc) {
165303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                status_t err = makeAVCCodecSpecificData(
165403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        (const uint8_t *)buffer->data()
165503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                            + buffer->range_offset(),
165603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        buffer->range_length());
1657be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                CHECK_EQ(OK, err);
16581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            } else if (mIsMPEG4) {
165903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificDataSize = buffer->range_length();
166003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificData = malloc(mCodecSpecificDataSize);
166103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                memcpy(mCodecSpecificData,
166203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        (const uint8_t *)buffer->data()
166303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                            + buffer->range_offset(),
166403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                       buffer->range_length());
166530ab66297501757d745b9ae10da61adcd891f497Andreas Huber            }
166630ab66297501757d745b9ae10da61adcd891f497Andreas Huber
166730ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer->release();
166830ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer = NULL;
166930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
1670548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            mGotAllCodecSpecificData = true;
167130ab66297501757d745b9ae10da61adcd891f497Andreas Huber            continue;
1672a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
1673a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
1674d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // Make a deep copy of the MediaBuffer and Metadata and release
1675d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // the original as soon as we can
1676d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        MediaBuffer *copy = new MediaBuffer(buffer->range_length());
1677d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(),
1678d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong                buffer->range_length());
1679d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        copy->set_range(0, buffer->range_length());
1680d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data = new MetaData(*buffer->meta_data().get());
1681d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer->release();
1682d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer = NULL;
1683d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
16841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (mIsAvc) StripStartcode(copy);
1685e136c3bb38e88315bf8797a464ebf2c788296b22James Dong
1686b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        size_t sampleSize = copy->range_length();
1687b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        if (mIsAvc) {
1688b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            if (mOwner->useNalLengthFour()) {
1689b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                sampleSize += 4;
1690b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            } else {
1691b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                sampleSize += 2;
1692b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            }
1693b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        }
1694050b28a593350047845a45a14cc5026221ac1620James Dong
1695d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        // Max file size or duration handling
16961f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mMdatSizeBytes += sampleSize;
16971f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        updateTrackSizeEstimate();
16981f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1699d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileSizeLimit()) {
1700d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
1701d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
1702d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
1703d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileDurationLimit()) {
1704d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
1705d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
1706d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
1707d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1708050b28a593350047845a45a14cc5026221ac1620James Dong
1709d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        int32_t isSync = false;
1710d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data->findInt32(kKeyIsSyncFrame, &isSync);
1711d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
17128428af5381e835cc783b7ecb0d71cb60961c99c2James Dong        /*
17138428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * The original timestamp found in the data buffer will be modified as below:
17148428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         *
17158428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * There is a playback offset into this track if the track's start time
17168428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * is not the same as the movie start time, which will be recorded in edst
17178428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * box of the output file. The playback offset is to make sure that the
17188428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * starting time of the audio/video tracks are synchronized. Although the
17198428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * track's media timestamp may be subject to various modifications
17208428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * as outlined below, the track's playback offset time remains unchanged
17218428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * once the first data buffer of the track is received.
17228428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         *
17238428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * The media time stamp will be calculated by subtracting the playback offset
17248428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * (and potential pause durations) from the original timestamp in the buffer.
17258428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         *
17268428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * If this track is a video track for a real-time recording application with
17278428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * both audio and video tracks, its media timestamp will subject to further
17288428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * modification based on the media clock of the audio track. This modification
17298428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * is needed for the purpose of maintaining good audio/video synchronization.
17308428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         *
17318428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * If the recording session is paused and resumed multiple times, the track
17328428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * media timestamp will be modified as if the  recording session had never been
17338428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * paused at all during playback of the recorded output file. In other words,
17348428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * the output file will have no memory of pause/resume durations.
17358428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         *
17368428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         */
1737d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        CHECK(meta_data->findInt64(kKeyTime, &timestampUs));
17388428af5381e835cc783b7ecb0d71cb60961c99c2James Dong        LOGV("%s timestampUs: %lld", mIsAudio? "Audio": "Video", timestampUs);
1739d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
1740d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong////////////////////////////////////////////////////////////////////////////////
17418644c14618d30d9e57a69df40ed939986ebf02c4James Dong        if (mSampleSizes.empty()) {
1742f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mStartTimestampUs = timestampUs;
1743f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mOwner->setStartTimestampUs(mStartTimestampUs);
17448428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            previousPausedDurationUs = mStartTimestampUs;
17453c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        }
174648c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber
1747a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mResumed) {
17488428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs;
17498428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            CHECK(durExcludingEarlierPausesUs >= 0);
17508428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs;
17518428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            CHECK(pausedDurationUs >= lastDurationUs);
17528428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            previousPausedDurationUs += pausedDurationUs - lastDurationUs;
1753a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mResumed = false;
1754a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
1755a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
1756a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        timestampUs -= previousPausedDurationUs;
17578428af5381e835cc783b7ecb0d71cb60961c99c2James Dong        CHECK(timestampUs >= 0);
1758872a481558350634a3fd5cb67939de288af00ecbJames Dong
1759872a481558350634a3fd5cb67939de288af00ecbJames Dong        // Media time adjustment for real-time applications
1760872a481558350634a3fd5cb67939de288af00ecbJames Dong        if (mIsRealTimeRecording) {
1761872a481558350634a3fd5cb67939de288af00ecbJames Dong            if (mIsAudio) {
1762872a481558350634a3fd5cb67939de288af00ecbJames Dong                updateDriftTime(meta_data);
1763872a481558350634a3fd5cb67939de288af00ecbJames Dong            } else {
1764872a481558350634a3fd5cb67939de288af00ecbJames Dong                adjustMediaTime(&timestampUs);
1765e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            }
1766e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        }
1767872a481558350634a3fd5cb67939de288af00ecbJames Dong
1768e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        CHECK(timestampUs >= 0);
1769e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        if (mNumSamples > 1) {
1770e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            if (timestampUs <= lastTimestampUs) {
17714f86a980fee1880dca61b828599fa6d76755a485James Dong                LOGW("Frame arrives too late!");
17724f86a980fee1880dca61b828599fa6d76755a485James Dong                // Don't drop the late frame, since dropping a frame may cause
17734f86a980fee1880dca61b828599fa6d76755a485James Dong                // problems later during playback
17744f86a980fee1880dca61b828599fa6d76755a485James Dong
17754f86a980fee1880dca61b828599fa6d76755a485James Dong                // The idea here is to avoid having two or more samples with the
17764f86a980fee1880dca61b828599fa6d76755a485James Dong                // same timestamp in the output file.
17774f86a980fee1880dca61b828599fa6d76755a485James Dong                if (mTimeScale >= 1000000LL) {
177840e9940fadf22daa64c1e766fa8a855c7b149c17James Dong                    timestampUs = lastTimestampUs + 1;
17794f86a980fee1880dca61b828599fa6d76755a485James Dong                } else {
178040e9940fadf22daa64c1e766fa8a855c7b149c17James Dong                    timestampUs = lastTimestampUs + (1000000LL + (mTimeScale >> 1)) / mTimeScale;
17814f86a980fee1880dca61b828599fa6d76755a485James Dong                }
1782e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            }
1783e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        }
1784e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
17858428af5381e835cc783b7ecb0d71cb60961c99c2James Dong        LOGV("%s media time stamp: %lld and previous paused duration %lld",
17868428af5381e835cc783b7ecb0d71cb60961c99c2James Dong                mIsAudio? "Audio": "Video", timestampUs, previousPausedDurationUs);
1787c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong        if (timestampUs > mTrackDurationUs) {
1788c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong            mTrackDurationUs = timestampUs;
17893b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber        }
17903b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber
17918644c14618d30d9e57a69df40ed939986ebf02c4James Dong        mSampleSizes.push_back(sampleSize);
1792ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong        ++mNumSamples;
1793ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong        if (mNumSamples > 2) {
1794c059860c73678a202bfa33062723e8f82fb779d9James Dong            // We need to use the time scale based ticks, rather than the
1795c059860c73678a202bfa33062723e8f82fb779d9James Dong            // timestamp itself to determine whether we have to use a new
1796c059860c73678a202bfa33062723e8f82fb779d9James Dong            // stts entry, since we may have rounding errors.
1797c059860c73678a202bfa33062723e8f82fb779d9James Dong            // The calculation is intended to reduce the accumulated
1798c059860c73678a202bfa33062723e8f82fb779d9James Dong            // rounding errors.
1799c059860c73678a202bfa33062723e8f82fb779d9James Dong            currDurationTicks =
1800c059860c73678a202bfa33062723e8f82fb779d9James Dong                     ((timestampUs * mTimeScale + 500000LL) / 1000000LL -
1801c059860c73678a202bfa33062723e8f82fb779d9James Dong                     (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL);
1802c059860c73678a202bfa33062723e8f82fb779d9James Dong
1803c059860c73678a202bfa33062723e8f82fb779d9James Dong            if (currDurationTicks != lastDurationTicks) {
18041f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                addOneSttsTableEntry(sampleCount, lastDurationUs);
1805be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                sampleCount = 1;
1806be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            } else {
1807be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                ++sampleCount;
1808be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
1809be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
1810be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        if (mSamplesHaveSameSize) {
1811ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong            if (mNumSamples >= 2 && previousSampleSize != sampleSize) {
1812be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mSamplesHaveSameSize = false;
1813be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
18148644c14618d30d9e57a69df40ed939986ebf02c4James Dong            previousSampleSize = sampleSize;
1815be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
18168644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastDurationUs = timestampUs - lastTimestampUs;
1817c059860c73678a202bfa33062723e8f82fb779d9James Dong        lastDurationTicks = currDurationTicks;
18188644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastTimestampUs = timestampUs;
181920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1820d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        if (isSync != 0) {
18211f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            addOneStssTableEntry(mNumSamples);
1822d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        }
1823d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
182493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (mTrackingProgressStatus) {
182593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            if (mPreviousTrackTimeUs <= 0) {
182693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong                mPreviousTrackTimeUs = mStartTimestampUs;
182793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            }
1828faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong            trackProgressStatus(timestampUs);
182993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
183058ae9c530247668f8af36e30d228c716c226b3d4James Dong        if (mOwner->numTracks() == 1) {
18311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            off_t offset = mIsAvc? mOwner->addLengthPrefixedSample_l(copy)
183258ae9c530247668f8af36e30d228c716c226b3d4James Dong                                 : mOwner->addSample_l(copy);
183358ae9c530247668f8af36e30d228c716c226b3d4James Dong            if (mChunkOffsets.empty()) {
18341f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                addChunkOffset(offset);
183558ae9c530247668f8af36e30d228c716c226b3d4James Dong            }
183658ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy->release();
183758ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy = NULL;
183858ae9c530247668f8af36e30d228c716c226b3d4James Dong            continue;
183958ae9c530247668f8af36e30d228c716c226b3d4James Dong        }
184013aec890216948b0c364f8f92792129d0335f506James Dong
184113aec890216948b0c364f8f92792129d0335f506James Dong        mChunkSamples.push_back(copy);
184213aec890216948b0c364f8f92792129d0335f506James Dong        if (interleaveDurationUs == 0) {
18431f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            addOneStscTableEntry(++nChunks, 1);
18441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            bufferChunk(timestampUs);
184513aec890216948b0c364f8f92792129d0335f506James Dong        } else {
184613aec890216948b0c364f8f92792129d0335f506James Dong            if (chunkTimestampUs == 0) {
184713aec890216948b0c364f8f92792129d0335f506James Dong                chunkTimestampUs = timestampUs;
184813aec890216948b0c364f8f92792129d0335f506James Dong            } else {
184913aec890216948b0c364f8f92792129d0335f506James Dong                if (timestampUs - chunkTimestampUs > interleaveDurationUs) {
185013aec890216948b0c364f8f92792129d0335f506James Dong                    ++nChunks;
185113aec890216948b0c364f8f92792129d0335f506James Dong                    if (nChunks == 1 ||  // First chunk
185213aec890216948b0c364f8f92792129d0335f506James Dong                        (--(mStscTableEntries.end()))->samplesPerChunk !=
185313aec890216948b0c364f8f92792129d0335f506James Dong                         mChunkSamples.size()) {
18541f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                        addOneStscTableEntry(nChunks, mChunkSamples.size());
185513aec890216948b0c364f8f92792129d0335f506James Dong                    }
18561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                    bufferChunk(timestampUs);
185713aec890216948b0c364f8f92792129d0335f506James Dong                    chunkTimestampUs = timestampUs;
185813aec890216948b0c364f8f92792129d0335f506James Dong                }
185913aec890216948b0c364f8f92792129d0335f506James Dong            }
186013aec890216948b0c364f8f92792129d0335f506James Dong        }
186113aec890216948b0c364f8f92792129d0335f506James Dong
186220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
186325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
1864a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong    if (mSampleSizes.empty() ||                      // no samples written
1865a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong        (!mIsAudio && mNumStssTableEntries == 0) ||  // no sync frames for video
1866a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong        (OK != checkCodecSpecificData())) {          // no codec specific data
1867690f546b0ee548dbfe997df36418e5302ec2d786James Dong        err = ERROR_MALFORMED;
1868f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong    }
1869faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    mOwner->trackProgressStatus(this, -1, err);
1870be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
187113aec890216948b0c364f8f92792129d0335f506James Dong    // Last chunk
187258ae9c530247668f8af36e30d228c716c226b3d4James Dong    if (mOwner->numTracks() == 1) {
18731f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        addOneStscTableEntry(1, mNumSamples);
187458ae9c530247668f8af36e30d228c716c226b3d4James Dong    } else if (!mChunkSamples.empty()) {
18751f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        addOneStscTableEntry(++nChunks, mChunkSamples.size());
18761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        bufferChunk(timestampUs);
187713aec890216948b0c364f8f92792129d0335f506James Dong    }
187813aec890216948b0c364f8f92792129d0335f506James Dong
1879be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // We don't really know how long the last frame lasts, since
1880be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // there is no frame time after it, just repeat the previous
1881be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // frame's duration.
1882ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    if (mNumSamples == 1) {
18838f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        lastDurationUs = 0;  // A single sample's duration
1884be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    } else {
1885be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        ++sampleCount;  // Count for the last sample
1886be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    }
18871f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    addOneSttsTableEntry(sampleCount, lastDurationUs);
1888c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs += lastDurationUs;
188925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = true;
18901f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    LOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s",
18911f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            count, nZeroLengthFrames, mNumSamples, mIsAudio? "audio": "video");
1892872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (mIsAudio) {
1893872a481558350634a3fd5cb67939de288af00ecbJames Dong        LOGI("Audio track drift time: %lld us", mOwner->getDriftTimeUs());
1894872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
1895365a963142093a1cd8efdcea76b5f65096a5b115James Dong
189637187916a486504acaf83bea30147eb5fbf46ae5James Dong    if (err == ERROR_END_OF_STREAM) {
189737187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
189837187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
189937187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
1900365a963142093a1cd8efdcea76b5f65096a5b115James Dong}
1901365a963142093a1cd8efdcea76b5f65096a5b115James Dong
1902faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) {
1903faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    LOGV("trackProgressStatus: %lld us", timeUs);
1904215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    if (mTrackEveryTimeDurationUs > 0 &&
1905215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) {
190693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        LOGV("Fire time tracking progress status at %lld us", timeUs);
1907faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        mOwner->trackProgressStatus(this, timeUs - mPreviousTrackTimeUs, err);
190893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        mPreviousTrackTimeUs = timeUs;
190993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
191093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
191193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
1912faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::trackProgressStatus(
1913faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        const MPEG4Writer::Track* track, int64_t timeUs, status_t err) {
1914faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    Mutex::Autolock lock(mLock);
1915faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    int32_t nTracks = mTracks.size();
1916faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    CHECK(nTracks >= 1);
1917faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    CHECK(nTracks < 64);  // Arbitrary number
1918faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
1919faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    int32_t trackNum = 0;
1920faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    CHECK(trackNum < nTracks);
1921faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    trackNum <<= 16;
1922faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
1923faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Error notification
1924faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Do not consider ERROR_END_OF_STREAM an error
1925faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (err != OK && err != ERROR_END_OF_STREAM) {
1926faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        notify(MEDIA_RECORDER_EVENT_ERROR,
1927faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               trackNum | MEDIA_RECORDER_ERROR_UNKNOWN,
1928faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
1929faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        return;
1930faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
1931faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
1932faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (timeUs == -1) {
1933faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send completion notification
1934faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        notify(MEDIA_RECORDER_EVENT_INFO,
1935faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               trackNum | MEDIA_RECORDER_INFO_COMPLETION_STATUS,
1936faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
1937faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        return;
1938faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    } else {
1939faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send progress status
1940faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        notify(MEDIA_RECORDER_EVENT_INFO,
1941faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               trackNum | MEDIA_RECORDER_INFO_PROGRESS_TIME_STATUS,
1942faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               timeUs / 1000);
1943faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
1944faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong}
1945faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
1946d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dongvoid MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) {
1947d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong    LOGV("setDriftTimeUs: %lld us", driftTimeUs);
1948e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
1949d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong    mDriftTimeUs = driftTimeUs;
1950e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
1951e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
1952e259531ce59ab1f31de5a23124b22536f6a5a767James Dongint64_t MPEG4Writer::getDriftTimeUs() {
1953e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    LOGV("getDriftTimeUs: %lld us", mDriftTimeUs);
1954e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
1955e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    return mDriftTimeUs;
1956e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
1957e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
1958b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dongbool MPEG4Writer::useNalLengthFour() {
1959b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    return mUse4ByteNalLength;
1960b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong}
1961b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong
19621c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::Track::bufferChunk(int64_t timestampUs) {
19631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("bufferChunk");
19641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
19651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Chunk chunk(this, timestampUs, mChunkSamples);
19661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mOwner->bufferChunk(chunk);
196713aec890216948b0c364f8f92792129d0335f506James Dong    mChunkSamples.clear();
196820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
196920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
19703b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const {
1971c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    return mTrackDurationUs;
197220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
197320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1974d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const {
1975d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return mEstimatedTrackSizeBytes;
1976d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
1977d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1978690f546b0ee548dbfe997df36418e5302ec2d786James Dongstatus_t MPEG4Writer::Track::checkCodecSpecificData() const {
1979690f546b0ee548dbfe997df36418e5302ec2d786James Dong    const char *mime;
1980690f546b0ee548dbfe997df36418e5302ec2d786James Dong    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
1981690f546b0ee548dbfe997df36418e5302ec2d786James Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) ||
1982690f546b0ee548dbfe997df36418e5302ec2d786James Dong        !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) ||
1983690f546b0ee548dbfe997df36418e5302ec2d786James Dong        !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
1984690f546b0ee548dbfe997df36418e5302ec2d786James Dong        if (!mCodecSpecificData ||
1985690f546b0ee548dbfe997df36418e5302ec2d786James Dong            mCodecSpecificDataSize <= 0) {
1986a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong            LOGE("Missing codec specific data");
1987690f546b0ee548dbfe997df36418e5302ec2d786James Dong            return ERROR_MALFORMED;
1988690f546b0ee548dbfe997df36418e5302ec2d786James Dong        }
1989690f546b0ee548dbfe997df36418e5302ec2d786James Dong    } else {
1990690f546b0ee548dbfe997df36418e5302ec2d786James Dong        if (mCodecSpecificData ||
1991690f546b0ee548dbfe997df36418e5302ec2d786James Dong            mCodecSpecificDataSize > 0) {
1992a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong            LOGE("Unexepected codec specific data found");
1993690f546b0ee548dbfe997df36418e5302ec2d786James Dong            return ERROR_MALFORMED;
1994690f546b0ee548dbfe997df36418e5302ec2d786James Dong        }
1995690f546b0ee548dbfe997df36418e5302ec2d786James Dong    }
1996690f546b0ee548dbfe997df36418e5302ec2d786James Dong    return OK;
1997690f546b0ee548dbfe997df36418e5302ec2d786James Dong}
1998690f546b0ee548dbfe997df36418e5302ec2d786James Dong
19991acfe8649f8169caf2ff098c2dc2de880d9a3760James Dongvoid MPEG4Writer::Track::writeTrackHeader(
20001acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        int32_t trackID, bool use32BitOffset) {
200120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const char *mime;
200220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool success = mMeta->findCString(kKeyMIMEType, &mime);
20030c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(success);
200420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
20058f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    LOGV("%s track time scale: %d",
20061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsAudio? "Audio": "Video", mTimeScale);
20078f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
200820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    time_t now = time(NULL);
20098f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int32_t mvhdTimeScale = mOwner->getTimeScale();
20108f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t trakDurationUs = getDurationUs();
201120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
201220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOwner->beginBox("trak");
201320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
201420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->beginBox("tkhd");
20151acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        // Flags = 7 to indicate that the track is enabled, and
20161acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        // part of the presentation
20171acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        mOwner->writeInt32(0x07);          // version=0, flags=7
201820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(now);           // creation time
201920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(now);           // modification time
202020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(trackID);
202120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);             // reserved
20228f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int32_t tkhdDuration =
20238f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
20248f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        mOwner->writeInt32(tkhdDuration);  // in mvhd timescale
202520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);             // reserved
202620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);             // reserved
202720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt16(0);             // layer
202820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt16(0);             // alternate group
20291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mOwner->writeInt16(mIsAudio ? 0x100 : 0);  // volume
203020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt16(0);             // reserved
203120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
203220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0x10000);       // matrix
203320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
203420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
203520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
203620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0x10000);
203720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
203820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
203920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
204020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0x40000000);
204120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
20421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (mIsAudio) {
204320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);
204420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);
204520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        } else {
204620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            int32_t width, height;
204720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            bool success = mMeta->findInt32(kKeyWidth, &width);
204820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            success = success && mMeta->findInt32(kKeyHeight, &height);
20490c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber            CHECK(success);
205020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2051050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->writeInt32(width << 16);   // 32-bit fixed-point value
2052050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->writeInt32(height << 16);  // 32-bit fixed-point value
205320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
205420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->endBox();  // tkhd
205520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2056f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong      int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
2057f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong      if (mStartTimestampUs != moovStartTimeUs) {
20583c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        mOwner->beginBox("edts");
20593c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong          mOwner->beginBox("elst");
20601acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong            mOwner->writeInt32(0);           // version=0, flags=0: 32-bit time
20611acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong            mOwner->writeInt32(2);           // never ends with an empty list
20628f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
20638f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            // First elst entry: specify the starting time offset
20648f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            int64_t offsetUs = mStartTimestampUs - moovStartTimeUs;
20658428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            LOGV("OffsetUs: %lld", offsetUs);
20668f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            int32_t seg = (offsetUs * mvhdTimeScale + 5E5) / 1E6;
20678f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            mOwner->writeInt32(seg);         // in mvhd timecale
20688f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            mOwner->writeInt32(-1);          // starting time offset
20698f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            mOwner->writeInt32(1 << 16);     // rate = 1.0
20708f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
20718f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            // Second elst entry: specify the track duration
20728f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            seg = (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
20738f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            mOwner->writeInt32(seg);         // in mvhd timescale
20741acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong            mOwner->writeInt32(0);
20751acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong            mOwner->writeInt32(1 << 16);
20763c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong          mOwner->endBox();
20773c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        mOwner->endBox();
20783c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong      }
20793c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
208020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->beginBox("mdia");
208120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
208220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("mdhd");
208320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // version=0, flags=0
208420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(now);           // creation time
208520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(now);           // modification time
20868f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong          mOwner->writeInt32(mTimeScale);    // media timescale
20878f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong          int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6;
20888f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong          mOwner->writeInt32(mdhdDuration);  // use media timescale
20891acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // Language follows the three letter standard ISO-639-2/T
20901acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // 'e', 'n', 'g' for "English", for instance.
20911acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // Each character is packed as the difference between its ASCII value and 0x60.
20921acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // For "English", these are 00101, 01110, 00111.
20931acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // XXX: Where is the padding bit located: 0x15C7?
20941acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          mOwner->writeInt16(0);             // language code
209520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt16(0);             // predefined
209620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->endBox();
209720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
209820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("hdlr");
209920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // version=0, flags=0
2100050b28a593350047845a45a14cc5026221ac1620James Dong          mOwner->writeInt32(0);             // component type: should be mhlr
21011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong          mOwner->writeFourcc(mIsAudio ? "soun" : "vide");  // component subtype
210220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // reserved
210320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // reserved
210420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // reserved
21051acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // Removing "r" for the name string just makes the string 4 byte aligned
21061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong          mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle");  // name
210720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->endBox();
210820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
210920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("minf");
21101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong          if (mIsAudio) {
211120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->beginBox("smhd");
211220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt32(0);           // version=0, flags=0
211320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // balance
211420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // reserved
211520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->endBox();
211620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          } else {
211720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->beginBox("vmhd");
21181acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong              mOwner->writeInt32(0x01);        // version=0, flags=1
211920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // graphics mode
212020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // opcolor
212120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);
212220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);
212320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->endBox();
212420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          }
2125050b28a593350047845a45a14cc5026221ac1620James Dong
2126050b28a593350047845a45a14cc5026221ac1620James Dong          mOwner->beginBox("dinf");
2127050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->beginBox("dref");
2128050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->writeInt32(0);  // version=0, flags=0
21291acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong              mOwner->writeInt32(1);  // entry count (either url or urn)
21301acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong              // The table index here refers to the sample description index
21311acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong              // in the sample table entries.
2132050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->beginBox("url ");
21331acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                mOwner->writeInt32(1);  // version=0, flags=1 (self-contained)
2134050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->endBox();  // url
2135050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->endBox();  // dref
2136050b28a593350047845a45a14cc5026221ac1620James Dong          mOwner->endBox();  // dinf
2137050b28a593350047845a45a14cc5026221ac1620James Dong
213820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("stbl");
213920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
214020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stsd");
214120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);               // version=0, flags=0
214220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(1);               // entry count
21431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (mIsAudio) {
214425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                const char *fourcc = NULL;
214518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) {
214625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    fourcc = "samr";
214718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
214825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    fourcc = "sawb";
2149050b28a593350047845a45a14cc5026221ac1620James Dong                } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
2150050b28a593350047845a45a14cc5026221ac1620James Dong                    fourcc = "mp4a";
215125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                } else {
215225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    LOGE("Unknown mime type '%s'.", mime);
215325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    CHECK(!"should not be here, unknown mime type.");
215425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                }
215525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
215625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                mOwner->beginBox(fourcc);          // audio format
215720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
215820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
2159050b28a593350047845a45a14cc5026221ac1620James Dong                  mOwner->writeInt16(0x1);         // data ref index
216020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
216120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
2162050b28a593350047845a45a14cc5026221ac1620James Dong                  int32_t nChannels;
2163050b28a593350047845a45a14cc5026221ac1620James Dong                  CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels));
2164050b28a593350047845a45a14cc5026221ac1620James Dong                  mOwner->writeInt16(nChannels);   // channel count
216520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(16);          // sample size
216620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // predefined
216720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
216820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
216920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  int32_t samplerate;
217020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  bool success = mMeta->findInt32(kKeySampleRate, &samplerate);
21710c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                  CHECK(success);
217220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(samplerate << 16);
2173050b28a593350047845a45a14cc5026221ac1620James Dong                  if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
2174050b28a593350047845a45a14cc5026221ac1620James Dong                    mOwner->beginBox("esds");
217551dfe6d646ddcc5fc252aa4c19c9936d32af8ad7James Dong                        CHECK(mCodecSpecificData);
217651dfe6d646ddcc5fc252aa4c19c9936d32af8ad7James Dong                        CHECK(mCodecSpecificDataSize > 0);
2177050b28a593350047845a45a14cc5026221ac1620James Dong
2178050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt32(0);     // version=0, flags=0
2179050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x03);   // ES_DescrTag
2180050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(23 + mCodecSpecificDataSize);
2181050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt16(0x0000);// ES_ID
2182050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x00);
2183050b28a593350047845a45a14cc5026221ac1620James Dong
2184050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x04);   // DecoderConfigDescrTag
2185050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(15 + mCodecSpecificDataSize);
2186050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x40);   // objectTypeIndication ISO/IEC 14492-2
2187050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x15);   // streamType AudioStream
2188050b28a593350047845a45a14cc5026221ac1620James Dong
2189050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt16(0x03);  // XXX
2190050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x00);   // buffer size 24-bit
2191050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt32(96000); // max bit rate
2192050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt32(96000); // avg bit rate
2193050b28a593350047845a45a14cc5026221ac1620James Dong
2194050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x05);   // DecoderSpecificInfoTag
2195050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(mCodecSpecificDataSize);
2196050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
2197050b28a593350047845a45a14cc5026221ac1620James Dong
2198050b28a593350047845a45a14cc5026221ac1620James Dong                        static const uint8_t kData2[] = {
2199050b28a593350047845a45a14cc5026221ac1620James Dong                            0x06,  // SLConfigDescriptorTag
2200050b28a593350047845a45a14cc5026221ac1620James Dong                            0x01,
2201050b28a593350047845a45a14cc5026221ac1620James Dong                            0x02
2202050b28a593350047845a45a14cc5026221ac1620James Dong                        };
2203050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->write(kData2, sizeof(kData2));
2204050b28a593350047845a45a14cc5026221ac1620James Dong
2205050b28a593350047845a45a14cc5026221ac1620James Dong                    mOwner->endBox();  // esds
22065aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                  } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) ||
22075aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                             !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
22085aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                    // 3gpp2 Spec AMRSampleEntry fields
22095aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                    mOwner->beginBox("damr");
22105aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                      mOwner->writeCString("   ");  // vendor: 4 bytes
22115aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                      mOwner->writeInt8(0);         // decoder version
22125aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                      mOwner->writeInt16(0x83FF);   // mode set: all enabled
22135aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                      mOwner->writeInt8(0);         // mode change period
22145aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                      mOwner->writeInt8(1);         // frames per sample
22155aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                    mOwner->endBox();
2216050b28a593350047845a45a14cc5026221ac1620James Dong                  }
221720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mOwner->endBox();
221820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
221918291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
222020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    mOwner->beginBox("mp4v");
222118291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
222220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    mOwner->beginBox("s263");
222330ab66297501757d745b9ae10da61adcd891f497Andreas Huber                } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
222430ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    mOwner->beginBox("avc1");
222520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                } else {
222625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    LOGE("Unknown mime type '%s'.", mime);
22270c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                    CHECK(!"should not be here, unknown mime type.");
222820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
222920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
223020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
223120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
22321acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                  mOwner->writeInt16(1);           // data ref index
223320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // predefined
223420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
223520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // predefined
223620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // predefined
223720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // predefined
223820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
223920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  int32_t width, height;
224020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  bool success = mMeta->findInt32(kKeyWidth, &width);
224120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  success = success && mMeta->findInt32(kKeyHeight, &height);
22420c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                  CHECK(success);
224320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
224420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(width);
224520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(height);
224620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0x480000);    // horiz resolution
224720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0x480000);    // vert resolution
224820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
224920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(1);           // frame count
225020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->write("                                ", 32);
225120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0x18);        // depth
225220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(-1);          // predefined
225320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
22540c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                  CHECK(23 + mCodecSpecificDataSize < 128);
225520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
225618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                  if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
2257a37923e9a57d489e7bed2129369219039fa5f12cJames Dong                      CHECK(mCodecSpecificData);
2258a37923e9a57d489e7bed2129369219039fa5f12cJames Dong                      CHECK(mCodecSpecificDataSize > 0);
225920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->beginBox("esds");
226020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
226120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt32(0);           // version=0, flags=0
226220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
226320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x03);  // ES_DescrTag
226420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(23 + mCodecSpecificDataSize);
226520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt16(0x0000);  // ES_ID
226620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x1f);
226720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
226820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x04);  // DecoderConfigDescrTag
226920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(15 + mCodecSpecificDataSize);
227020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x20);  // objectTypeIndication ISO/IEC 14492-2
227120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x11);  // streamType VisualStream
227220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
227320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        static const uint8_t kData[] = {
227420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x01, 0x77, 0x00,
227520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x00, 0x03, 0xe8, 0x00,
227620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x00, 0x03, 0xe8, 0x00
227720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        };
227820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->write(kData, sizeof(kData));
2279050b28a593350047845a45a14cc5026221ac1620James Dong
228020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x05);  // DecoderSpecificInfoTag
228120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
228220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(mCodecSpecificDataSize);
228320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
228420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
228520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        static const uint8_t kData2[] = {
228620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x06,  // SLConfigDescriptorTag
228720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x01,
228820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x02
228920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        };
229020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->write(kData2, sizeof(kData2));
229120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
229220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->endBox();  // esds
229318291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                  } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
229420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->beginBox("d263");
229520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
229620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt32(0);  // vendor
229720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt8(0);   // decoder version
229820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt8(10);  // level: 10
229920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt8(0);   // profile: 0
230020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
230120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->endBox();  // d263
230230ab66297501757d745b9ae10da61adcd891f497Andreas Huber                  } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
230351dfe6d646ddcc5fc252aa4c19c9936d32af8ad7James Dong                      CHECK(mCodecSpecificData);
230495fcef25b48e35b625899288971ab628efbf8584Andreas Huber                      CHECK(mCodecSpecificDataSize >= 5);
230595fcef25b48e35b625899288971ab628efbf8584Andreas Huber
230695fcef25b48e35b625899288971ab628efbf8584Andreas Huber                      // Patch avcc's lengthSize field to match the number
230795fcef25b48e35b625899288971ab628efbf8584Andreas Huber                      // of bytes we use to indicate the size of a nal unit.
230895fcef25b48e35b625899288971ab628efbf8584Andreas Huber                      uint8_t *ptr = (uint8_t *)mCodecSpecificData;
230995fcef25b48e35b625899288971ab628efbf8584Andreas Huber                      ptr[4] =
231095fcef25b48e35b625899288971ab628efbf8584Andreas Huber                          (ptr[4] & 0xfc)
231195fcef25b48e35b625899288971ab628efbf8584Andreas Huber                            | (mOwner->useNalLengthFour() ? 3 : 1);
231295fcef25b48e35b625899288971ab628efbf8584Andreas Huber
231330ab66297501757d745b9ae10da61adcd891f497Andreas Huber                      mOwner->beginBox("avcC");
231430ab66297501757d745b9ae10da61adcd891f497Andreas Huber                        mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
231530ab66297501757d745b9ae10da61adcd891f497Andreas Huber                      mOwner->endBox();  // avcC
231620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  }
231730ab66297501757d745b9ae10da61adcd891f497Andreas Huber
23181acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                  mOwner->beginBox("pasp");
23191acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                    // This is useful if the pixel is not square
23201acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                    mOwner->writeInt32(1 << 16);  // hspacing
23211acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                    mOwner->writeInt32(1 << 16);  // vspacing
23221acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                  mOwner->endBox();  // pasp
232330ab66297501757d745b9ae10da61adcd891f497Andreas Huber                mOwner->endBox();  // mp4v, s263 or avc1
232420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
232520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stsd
232620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
232720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stts");
232820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
23291f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            mOwner->writeInt32(mNumSttsTableEntries);
2330c059860c73678a202bfa33062723e8f82fb779d9James Dong            int64_t prevTimestampUs = 0;
2331be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin();
2332be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                 it != mSttsTableEntries.end(); ++it) {
2333be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mOwner->writeInt32(it->sampleCount);
2334c059860c73678a202bfa33062723e8f82fb779d9James Dong
2335c059860c73678a202bfa33062723e8f82fb779d9James Dong                // Make sure that we are calculating the sample duration the exactly
2336c059860c73678a202bfa33062723e8f82fb779d9James Dong                // same way as we made decision on how to create stts entries.
2337c059860c73678a202bfa33062723e8f82fb779d9James Dong                int64_t currTimestampUs = prevTimestampUs + it->sampleDurationUs;
2338c059860c73678a202bfa33062723e8f82fb779d9James Dong                int32_t dur = ((currTimestampUs * mTimeScale + 500000LL) / 1000000LL -
2339c059860c73678a202bfa33062723e8f82fb779d9James Dong                               (prevTimestampUs * mTimeScale + 500000LL) / 1000000LL);
2340c059860c73678a202bfa33062723e8f82fb779d9James Dong                prevTimestampUs += (it->sampleCount * it->sampleDurationUs);
2341c059860c73678a202bfa33062723e8f82fb779d9James Dong
23428f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong                mOwner->writeInt32(dur);
234320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
234420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stts
234520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
23461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong          if (!mIsAudio) {
2347050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->beginBox("stss");
2348050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->writeInt32(0);  // version=0, flags=0
23491f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong              mOwner->writeInt32(mNumStssTableEntries);  // number of sync frames
2350050b28a593350047845a45a14cc5026221ac1620James Dong              for (List<int32_t>::iterator it = mStssTableEntries.begin();
2351050b28a593350047845a45a14cc5026221ac1620James Dong                   it != mStssTableEntries.end(); ++it) {
2352050b28a593350047845a45a14cc5026221ac1620James Dong                  mOwner->writeInt32(*it);
2353050b28a593350047845a45a14cc5026221ac1620James Dong              }
2354050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->endBox();  // stss
2355050b28a593350047845a45a14cc5026221ac1620James Dong          }
2356050b28a593350047845a45a14cc5026221ac1620James Dong
235720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stsz");
235820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
2359be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            if (mSamplesHaveSameSize) {
23608644c14618d30d9e57a69df40ed939986ebf02c4James Dong                List<size_t>::iterator it = mSampleSizes.begin();
23618644c14618d30d9e57a69df40ed939986ebf02c4James Dong                mOwner->writeInt32(*it);  // default sample size
2362be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            } else {
2363be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mOwner->writeInt32(0);
2364be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
2365ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong            mOwner->writeInt32(mNumSamples);
2366be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            if (!mSamplesHaveSameSize) {
23678644c14618d30d9e57a69df40ed939986ebf02c4James Dong                for (List<size_t>::iterator it = mSampleSizes.begin();
23688644c14618d30d9e57a69df40ed939986ebf02c4James Dong                     it != mSampleSizes.end(); ++it) {
23698644c14618d30d9e57a69df40ed939986ebf02c4James Dong                    mOwner->writeInt32(*it);
2370be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                }
237120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
237220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stsz
237320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
237420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stsc");
237520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
23761f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            mOwner->writeInt32(mNumStscTableEntries);
237713aec890216948b0c364f8f92792129d0335f506James Dong            for (List<StscTableEntry>::iterator it = mStscTableEntries.begin();
237813aec890216948b0c364f8f92792129d0335f506James Dong                 it != mStscTableEntries.end(); ++it) {
237913aec890216948b0c364f8f92792129d0335f506James Dong                mOwner->writeInt32(it->firstChunk);
238013aec890216948b0c364f8f92792129d0335f506James Dong                mOwner->writeInt32(it->samplesPerChunk);
238113aec890216948b0c364f8f92792129d0335f506James Dong                mOwner->writeInt32(it->sampleDescriptionId);
238220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
238320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stsc
23841acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          mOwner->beginBox(use32BitOffset? "stco": "co64");
238520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
23861f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            mOwner->writeInt32(mNumStcoTableEntries);
238713aec890216948b0c364f8f92792129d0335f506James Dong            for (List<off_t>::iterator it = mChunkOffsets.begin();
238813aec890216948b0c364f8f92792129d0335f506James Dong                 it != mChunkOffsets.end(); ++it) {
23891acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                if (use32BitOffset) {
23901acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                    mOwner->writeInt32(static_cast<int32_t>(*it));
23911acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                } else {
23921acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                    mOwner->writeInt64((*it));
23931acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                }
239420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
23958f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong          mOwner->endBox();  // stco or co64
239620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
239720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->endBox();  // stbl
23981acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong       mOwner->endBox();  // minf
239920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->endBox();  // mdia
240020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOwner->endBox();  // trak
240120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
240220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
240320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
2404