MPEG4Writer.cpp revision a007e8229fb2be4866c483f9cd6c4af238a2da5e
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),
215a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong      mIsFileSizeLimitExplicitlyRequested(false),
216a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
217a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mStarted(false),
21820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOffset(0),
21913aec890216948b0c364f8f92792129d0335f506James Dong      mMdatOffset(0),
2207837c17063a4c50bc856ba59418516fdab731de7James Dong      mEstimatedMoovBoxSize(0),
221f01528f435e6b1f02d118fcd8305a148c27a89f1James Dong      mInterleaveDurationUs(1000000) {
2220c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(mFile != NULL);
22320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
22420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
22530ab66297501757d745b9ae10da61adcd891f497Andreas HuberMPEG4Writer::MPEG4Writer(int fd)
22630ab66297501757d745b9ae10da61adcd891f497Andreas Huber    : mFile(fdopen(fd, "wb")),
227b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong      mUse4ByteNalLength(true),
2281acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong      mUse32BitOffset(true),
229a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong      mIsFileSizeLimitExplicitlyRequested(false),
230a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
231a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mStarted(false),
23230ab66297501757d745b9ae10da61adcd891f497Andreas Huber      mOffset(0),
23313aec890216948b0c364f8f92792129d0335f506James Dong      mMdatOffset(0),
2347837c17063a4c50bc856ba59418516fdab731de7James Dong      mEstimatedMoovBoxSize(0),
235f01528f435e6b1f02d118fcd8305a148c27a89f1James Dong      mInterleaveDurationUs(1000000) {
23630ab66297501757d745b9ae10da61adcd891f497Andreas Huber    CHECK(mFile != NULL);
23730ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
23830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
23920111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() {
24020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    stop();
24120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2421f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    while (!mTracks.empty()) {
2431f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        List<Track *>::iterator it = mTracks.begin();
24420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        delete *it;
2451f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        (*it) = NULL;
2461f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mTracks.erase(it);
24720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
24820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.clear();
24920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
25020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
251dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::dump(
252dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        int fd, const Vector<String16>& args) {
253dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    const size_t SIZE = 256;
254dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    char buffer[SIZE];
255dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    String8 result;
256dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "   MPEG4Writer %p\n", this);
257dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
258dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "     mStarted: %s\n", mStarted? "true": "false");
259dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
260dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    ::write(fd, result.string(), result.size());
261dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    for (List<Track *>::iterator it = mTracks.begin();
262dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong         it != mTracks.end(); ++it) {
263dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        (*it)->dump(fd, args);
264dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    }
265dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    return OK;
266dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong}
267dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong
268dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::Track::dump(
269dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        int fd, const Vector<String16>& args) const {
270dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    const size_t SIZE = 256;
271dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    char buffer[SIZE];
272dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    String8 result;
273dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "     %s track\n", mIsAudio? "Audio": "Video");
274dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
275dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "       reached EOS: %s\n",
276dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong            mReachedEOS? "true": "false");
277dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
278dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    ::write(fd, result.string(), result.size());
279dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    return OK;
280dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong}
281dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong
2822dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huberstatus_t MPEG4Writer::addSource(const sp<MediaSource> &source) {
28325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    Track *track = new Track(this, source);
28420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.push_back(track);
2852dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
2862dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    return OK;
28720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
28820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
28993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::startTracks(MetaData *params) {
290a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
291a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
29293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        status_t err = (*it)->start(params);
293a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
294a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (err != OK) {
295a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            for (List<Track *>::iterator it2 = mTracks.begin();
296a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                 it2 != it; ++it2) {
297a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                (*it2)->stop();
298a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            }
299a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
300a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            return err;
301a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
302a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
303a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    return OK;
304a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
305a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
3062dec2b5be2056c6d9428897dc672185872d30d17James Dongint64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) {
3072dec2b5be2056c6d9428897dc672185872d30d17James Dong    // This implementation is highly experimental/heurisitic.
3082dec2b5be2056c6d9428897dc672185872d30d17James Dong    //
3092dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Statistical analysis shows that metadata usually accounts
3102dec2b5be2056c6d9428897dc672185872d30d17James Dong    // for a small portion of the total file size, usually < 0.6%.
3112dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Currently, lets set to 0.4% for now.
3122dec2b5be2056c6d9428897dc672185872d30d17James Dong
3132dec2b5be2056c6d9428897dc672185872d30d17James Dong    // The default MIN_MOOV_BOX_SIZE is set to 0.4% x 1MB,
3142dec2b5be2056c6d9428897dc672185872d30d17James Dong    // where 1MB is the common file size limit for MMS application.
3152dec2b5be2056c6d9428897dc672185872d30d17James Dong    // The default MAX _MOOV_BOX_SIZE value is based on about 4
3162dec2b5be2056c6d9428897dc672185872d30d17James Dong    // minute video recording with a bit rate about 3 Mbps, because
3172dec2b5be2056c6d9428897dc672185872d30d17James Dong    // statistics also show that most of the video captured are going
3182dec2b5be2056c6d9428897dc672185872d30d17James Dong    // to be less than 3 minutes.
3192dec2b5be2056c6d9428897dc672185872d30d17James Dong
3202dec2b5be2056c6d9428897dc672185872d30d17James Dong    // If the estimation is wrong, we will pay the price of wasting
3212dec2b5be2056c6d9428897dc672185872d30d17James Dong    // some reserved space. This should not happen so often statistically.
3222dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int32_t factor = mUse32BitOffset? 1: 2;
3232dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int64_t MIN_MOOV_BOX_SIZE = 4 * 1024;  // 4 KB
3242dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000);
3252dec2b5be2056c6d9428897dc672185872d30d17James Dong    int64_t size = MIN_MOOV_BOX_SIZE;
3262dec2b5be2056c6d9428897dc672185872d30d17James Dong
327a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
3282dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = mMaxFileSizeLimitBytes * 4 / 1000;
3292dec2b5be2056c6d9428897dc672185872d30d17James Dong    } else if (mMaxFileDurationLimitUs != 0) {
3302dec2b5be2056c6d9428897dc672185872d30d17James Dong        if (bitRate <= 0) {
3312dec2b5be2056c6d9428897dc672185872d30d17James Dong            // We could not estimate the file size since bitRate is not set.
3322dec2b5be2056c6d9428897dc672185872d30d17James Dong            size = MIN_MOOV_BOX_SIZE;
3332dec2b5be2056c6d9428897dc672185872d30d17James Dong        } else {
3342dec2b5be2056c6d9428897dc672185872d30d17James Dong            size = ((mMaxFileDurationLimitUs * bitRate * 4) / 1000 / 8000000);
3352dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
3362dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
3372dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size < MIN_MOOV_BOX_SIZE) {
3382dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MIN_MOOV_BOX_SIZE;
3392dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
3402dec2b5be2056c6d9428897dc672185872d30d17James Dong
3412dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Any long duration recording will be probably end up with
3422dec2b5be2056c6d9428897dc672185872d30d17James Dong    // non-streamable mp4 file.
3432dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size > MAX_MOOV_BOX_SIZE) {
3442dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MAX_MOOV_BOX_SIZE;
3452dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
3462dec2b5be2056c6d9428897dc672185872d30d17James Dong
347a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    LOGI("limits: %lld/%lld bytes/us, bit rate: %d bps and the estimated"
3482dec2b5be2056c6d9428897dc672185872d30d17James Dong         " moov size %lld bytes",
3492dec2b5be2056c6d9428897dc672185872d30d17James Dong         mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size);
3502dec2b5be2056c6d9428897dc672185872d30d17James Dong    return factor * size;
3512dec2b5be2056c6d9428897dc672185872d30d17James Dong}
3522dec2b5be2056c6d9428897dc672185872d30d17James Dong
3532dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t MPEG4Writer::start(MetaData *param) {
35420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mFile == NULL) {
35525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return UNKNOWN_ERROR;
35620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
35720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
358a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    /*
359a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * Check mMaxFileSizeLimitBytes at the beginning
360a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * since mMaxFileSizeLimitBytes may be implicitly
361a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * changed later for 32-bit file offset even if
362a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * user does not ask to set it explicitly.
363a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     */
364a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    if (mMaxFileSizeLimitBytes != 0) {
365a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong        mIsFileSizeLimitExplicitlyRequested = true;
366a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    }
367a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong
3682dec2b5be2056c6d9428897dc672185872d30d17James Dong    int32_t use64BitOffset;
3692dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (param &&
3702dec2b5be2056c6d9428897dc672185872d30d17James Dong        param->findInt32(kKey64BitFileOffset, &use64BitOffset) &&
3712dec2b5be2056c6d9428897dc672185872d30d17James Dong        use64BitOffset) {
3722dec2b5be2056c6d9428897dc672185872d30d17James Dong        mUse32BitOffset = false;
3732dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
3742dec2b5be2056c6d9428897dc672185872d30d17James Dong
3751f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    if (mUse32BitOffset) {
3761f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // Implicit 32 bit file size limit
3771f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        if (mMaxFileSizeLimitBytes == 0) {
3781f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            mMaxFileSizeLimitBytes = kMax32BitFileSize;
3791f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        }
3801f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
3811f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // If file size is set to be larger than the 32 bit file
3821f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // size limit, treat it as an error.
3831f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        if (mMaxFileSizeLimitBytes > kMax32BitFileSize) {
384872a481558350634a3fd5cb67939de288af00ecbJames Dong            LOGW("32-bit file size limit (%lld bytes) too big. "
385d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong                 "It is changed to %lld bytes",
386d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong                mMaxFileSizeLimitBytes, kMax32BitFileSize);
387d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong            mMaxFileSizeLimitBytes = kMax32BitFileSize;
3881f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        }
3891f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    }
3901f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
391b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    int32_t use2ByteNalLength;
392b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (param &&
393b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        param->findInt32(kKey2ByteNalLength, &use2ByteNalLength) &&
394b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        use2ByteNalLength) {
395b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mUse4ByteNalLength = false;
3962dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
3972dec2b5be2056c6d9428897dc672185872d30d17James Dong
398065d1aff96818df54456053f1574aec8a234d0deJames Dong    mStartTimestampUs = -1;
39993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
400a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (mStarted) {
401a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused) {
402a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mPaused = false;
40393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            return startTracks(param);
404a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
405a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
406a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
407a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
4088f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    if (!param ||
4098f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        !param->findInt32(kKeyTimeScale, &mTimeScale)) {
4108f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        mTimeScale = 1000;
4118f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    }
4128f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    CHECK(mTimeScale > 0);
4138f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    LOGV("movie time scale: %d", mTimeScale);
4148f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
4157837c17063a4c50bc856ba59418516fdab731de7James Dong    mStreamableFile = true;
4167837c17063a4c50bc856ba59418516fdab731de7James Dong    mWriteMoovBoxToMemory = false;
4177837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBuffer = NULL;
4187837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
4197837c17063a4c50bc856ba59418516fdab731de7James Dong
42020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    beginBox("ftyp");
42193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong      {
42293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        int32_t fileType;
42393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (param && param->findInt32(kKeyFileType, &fileType) &&
42493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            fileType != OUTPUT_FORMAT_MPEG_4) {
42593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            writeFourcc("3gp4");
42693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        } else {
42793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            writeFourcc("isom");
42893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
42993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong      }
43020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      writeInt32(0);
43120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      writeFourcc("isom");
43293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong      writeFourcc("3gp4");
43320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    endBox();
43420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4357837c17063a4c50bc856ba59418516fdab731de7James Dong    mFreeBoxOffset = mOffset;
43620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4377837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mEstimatedMoovBoxSize == 0) {
4382dec2b5be2056c6d9428897dc672185872d30d17James Dong        int32_t bitRate = -1;
4392dec2b5be2056c6d9428897dc672185872d30d17James Dong        if (param) {
4402dec2b5be2056c6d9428897dc672185872d30d17James Dong            param->findInt32(kKeyBitRate, &bitRate);
4412dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
4422dec2b5be2056c6d9428897dc672185872d30d17James Dong        mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate);
4437837c17063a4c50bc856ba59418516fdab731de7James Dong    }
4447837c17063a4c50bc856ba59418516fdab731de7James Dong    CHECK(mEstimatedMoovBoxSize >= 8);
4457837c17063a4c50bc856ba59418516fdab731de7James Dong    fseeko(mFile, mFreeBoxOffset, SEEK_SET);
4467837c17063a4c50bc856ba59418516fdab731de7James Dong    writeInt32(mEstimatedMoovBoxSize);
4477837c17063a4c50bc856ba59418516fdab731de7James Dong    write("free", 4);
4487837c17063a4c50bc856ba59418516fdab731de7James Dong
4497837c17063a4c50bc856ba59418516fdab731de7James Dong    mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize;
4507837c17063a4c50bc856ba59418516fdab731de7James Dong    mOffset = mMdatOffset;
4517837c17063a4c50bc856ba59418516fdab731de7James Dong    fseeko(mFile, mMdatOffset, SEEK_SET);
4521acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
4531acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("????mdat", 8);
4541acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
4551acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("\x00\x00\x00\x01mdat????????", 16);
4561acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
4571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
4581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    status_t err = startWriterThread();
4591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (err != OK) {
4601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        return err;
4611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
4621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
4631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    err = startTracks(param);
464a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (err != OK) {
465a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return err;
46620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
4671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
468a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mStarted = true;
46925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
47020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
47120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4721f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongbool MPEG4Writer::use32BitFileOffset() const {
4731f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    return mUse32BitOffset;
4741f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
4751f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
47637187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::pause() {
477a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (mFile == NULL) {
47837187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
479a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
480a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
48137187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = OK;
482a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
483a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
48437187916a486504acaf83bea30147eb5fbf46ae5James Dong        status_t status = (*it)->pause();
48537187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (status != OK) {
48637187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
48737187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
488a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
48937187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
490a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
491a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
4921c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::stopWriterThread() {
4931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("stopWriterThread");
4941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
4951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    {
4961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        Mutex::Autolock autolock(mLock);
4971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
4981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mDone = true;
4991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkReadyCondition.signal();
5001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
5011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
5021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void *dummy;
5031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_join(mThread, &dummy);
5041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
5051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
50637187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::stop() {
50720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mFile == NULL) {
50837187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
50920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
51020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
51137187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = OK;
5128f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t maxDurationUs = 0;
51320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
51420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber         it != mTracks.end(); ++it) {
51537187916a486504acaf83bea30147eb5fbf46ae5James Dong        status_t status = (*it)->stop();
51637187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (err == OK && status != OK) {
51737187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
51837187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
51920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5208f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int64_t durationUs = (*it)->getDurationUs();
5218f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        if (durationUs > maxDurationUs) {
5228f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            maxDurationUs = durationUs;
52320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
52420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
52520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    stopWriterThread();
5277837c17063a4c50bc856ba59418516fdab731de7James Dong
52837187916a486504acaf83bea30147eb5fbf46ae5James Dong    // Do not write out movie header on error.
52937187916a486504acaf83bea30147eb5fbf46ae5James Dong    if (err != OK) {
53037187916a486504acaf83bea30147eb5fbf46ae5James Dong        fflush(mFile);
53137187916a486504acaf83bea30147eb5fbf46ae5James Dong        fclose(mFile);
53237187916a486504acaf83bea30147eb5fbf46ae5James Dong        mFile = NULL;
53337187916a486504acaf83bea30147eb5fbf46ae5James Dong        mStarted = false;
53437187916a486504acaf83bea30147eb5fbf46ae5James Dong        return err;
53537187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
53637187916a486504acaf83bea30147eb5fbf46ae5James Dong
53720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // Fix up the size of the 'mdat' chunk.
5381acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
5391acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        fseeko(mFile, mMdatOffset, SEEK_SET);
5401acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        int32_t size = htonl(static_cast<int32_t>(mOffset - mMdatOffset));
5411acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        fwrite(&size, 1, 4, mFile);
5421acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
5431acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        fseeko(mFile, mMdatOffset + 8, SEEK_SET);
5441acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        int64_t size = mOffset - mMdatOffset;
5451acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        size = hton64(size);
5461acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        fwrite(&size, 1, 8, mFile);
5471acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
5487837c17063a4c50bc856ba59418516fdab731de7James Dong    fseeko(mFile, mOffset, SEEK_SET);
54920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
55020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    time_t now = time(NULL);
5517837c17063a4c50bc856ba59418516fdab731de7James Dong    const off_t moovOffset = mOffset;
5527837c17063a4c50bc856ba59418516fdab731de7James Dong    mWriteMoovBoxToMemory = true;
5537837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize);
5547837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
5557837c17063a4c50bc856ba59418516fdab731de7James Dong    CHECK(mMoovBoxBuffer != NULL);
556c059860c73678a202bfa33062723e8f82fb779d9James Dong    int32_t duration = (maxDurationUs * mTimeScale + 5E5) / 1E6;
55720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
55820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    beginBox("moov");
55920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
56020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      beginBox("mvhd");
56120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // version=0, flags=0
56220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(now);           // creation time
56320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(now);           // modification time
5648f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        writeInt32(mTimeScale);    // mvhd timescale
5651acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        writeInt32(duration);
5661acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        writeInt32(0x10000);       // rate: 1.0
56720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt16(0x100);         // volume
56820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt16(0);             // reserved
56920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // reserved
57020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // reserved
57120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0x10000);       // matrix
57220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
57320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
57420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
57520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0x10000);
57620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
57720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
57820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
57920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0x40000000);
58020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
58120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
58220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
58320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
58420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
58520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
58620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(mTracks.size() + 1);  // nextTrackID
58720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      endBox();  // mvhd
58820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
58920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      int32_t id = 1;
59020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      for (List<Track *>::iterator it = mTracks.begin();
59120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber           it != mTracks.end(); ++it, ++id) {
5921acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          (*it)->writeTrackHeader(id, mUse32BitOffset);
59320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      }
59420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    endBox();  // moov
59520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5967837c17063a4c50bc856ba59418516fdab731de7James Dong    mWriteMoovBoxToMemory = false;
5977837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mStreamableFile) {
5987837c17063a4c50bc856ba59418516fdab731de7James Dong        CHECK(mMoovBoxBufferOffset + 8 <= mEstimatedMoovBoxSize);
5997837c17063a4c50bc856ba59418516fdab731de7James Dong
6007837c17063a4c50bc856ba59418516fdab731de7James Dong        // Moov box
6017837c17063a4c50bc856ba59418516fdab731de7James Dong        fseeko(mFile, mFreeBoxOffset, SEEK_SET);
6027837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset = mFreeBoxOffset;
6037837c17063a4c50bc856ba59418516fdab731de7James Dong        write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, mFile);
6047837c17063a4c50bc856ba59418516fdab731de7James Dong
6057837c17063a4c50bc856ba59418516fdab731de7James Dong        // Free box
6062dec2b5be2056c6d9428897dc672185872d30d17James Dong        fseeko(mFile, mOffset, SEEK_SET);
6077837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset);
6087837c17063a4c50bc856ba59418516fdab731de7James Dong        write("free", 4);
6097837c17063a4c50bc856ba59418516fdab731de7James Dong
6107837c17063a4c50bc856ba59418516fdab731de7James Dong        // Free temp memory
6117837c17063a4c50bc856ba59418516fdab731de7James Dong        free(mMoovBoxBuffer);
6127837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBuffer = NULL;
6137837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBufferOffset = 0;
6142dec2b5be2056c6d9428897dc672185872d30d17James Dong    } else {
6152dec2b5be2056c6d9428897dc672185872d30d17James Dong        LOGI("The mp4 file will not be streamable.");
6167837c17063a4c50bc856ba59418516fdab731de7James Dong    }
6177837c17063a4c50bc856ba59418516fdab731de7James Dong
6180c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(mBoxes.empty());
61920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6207837c17063a4c50bc856ba59418516fdab731de7James Dong    fflush(mFile);
62120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fclose(mFile);
62220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mFile = NULL;
623a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mStarted = false;
62437187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
62520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
62620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
62713aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) {
62813aec890216948b0c364f8f92792129d0335f506James Dong    mInterleaveDurationUs = durationUs;
62913aec890216948b0c364f8f92792129d0335f506James Dong    return OK;
63013aec890216948b0c364f8f92792129d0335f506James Dong}
63113aec890216948b0c364f8f92792129d0335f506James Dong
63213aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() {
63313aec890216948b0c364f8f92792129d0335f506James Dong    mLock.lock();
63413aec890216948b0c364f8f92792129d0335f506James Dong}
63513aec890216948b0c364f8f92792129d0335f506James Dong
63613aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() {
63713aec890216948b0c364f8f92792129d0335f506James Dong    mLock.unlock();
63813aec890216948b0c364f8f92792129d0335f506James Dong}
63920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
64013aec890216948b0c364f8f92792129d0335f506James Dongoff_t MPEG4Writer::addSample_l(MediaBuffer *buffer) {
64120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    off_t old_offset = mOffset;
64220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
64320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fwrite((const uint8_t *)buffer->data() + buffer->range_offset(),
64420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber           1, buffer->range_length(), mFile);
64520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
64620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += buffer->range_length();
64720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
64820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return old_offset;
64920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
65020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
65103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) {
65203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (buffer->range_length() < 4) {
65303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return;
65403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
65503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
65603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    const uint8_t *ptr =
65703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        (const uint8_t *)buffer->data() + buffer->range_offset();
65803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
65903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) {
66003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        buffer->set_range(
66103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                buffer->range_offset() + 4, buffer->range_length() - 4);
66203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
66303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
66403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
66513aec890216948b0c364f8f92792129d0335f506James Dongoff_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) {
66630ab66297501757d745b9ae10da61adcd891f497Andreas Huber    off_t old_offset = mOffset;
66730ab66297501757d745b9ae10da61adcd891f497Andreas Huber
66830ab66297501757d745b9ae10da61adcd891f497Andreas Huber    size_t length = buffer->range_length();
66903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
670b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (mUse4ByteNalLength) {
671b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        uint8_t x = length >> 24;
672b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        fwrite(&x, 1, 1, mFile);
673b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = (length >> 16) & 0xff;
674b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        fwrite(&x, 1, 1, mFile);
675b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = (length >> 8) & 0xff;
676b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        fwrite(&x, 1, 1, mFile);
677b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = length & 0xff;
678b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        fwrite(&x, 1, 1, mFile);
679b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong
680b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        fwrite((const uint8_t *)buffer->data() + buffer->range_offset(),
681b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                1, length, mFile);
682b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mOffset += length + 4;
683b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    } else {
684b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        CHECK(length < 65536);
68530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
686b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        uint8_t x = length >> 8;
687b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        fwrite(&x, 1, 1, mFile);
688b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = length & 0xff;
689b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        fwrite(&x, 1, 1, mFile);
690b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        fwrite((const uint8_t *)buffer->data() + buffer->range_offset(),
691b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                1, length, mFile);
692b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mOffset += length + 2;
693b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    }
69430ab66297501757d745b9ae10da61adcd891f497Andreas Huber
69530ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return old_offset;
69630ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
69730ab66297501757d745b9ae10da61adcd891f497Andreas Huber
6987837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write(
6997837c17063a4c50bc856ba59418516fdab731de7James Dong        const void *ptr, size_t size, size_t nmemb, FILE *stream) {
7007837c17063a4c50bc856ba59418516fdab731de7James Dong
7017837c17063a4c50bc856ba59418516fdab731de7James Dong    const size_t bytes = size * nmemb;
7027837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
7031acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        off_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes;
7041acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        if (moovBoxSize > mEstimatedMoovBoxSize) {
7057837c17063a4c50bc856ba59418516fdab731de7James Dong            for (List<off_t>::iterator it = mBoxes.begin();
7067837c17063a4c50bc856ba59418516fdab731de7James Dong                 it != mBoxes.end(); ++it) {
7077837c17063a4c50bc856ba59418516fdab731de7James Dong                (*it) += mOffset;
7087837c17063a4c50bc856ba59418516fdab731de7James Dong            }
7097837c17063a4c50bc856ba59418516fdab731de7James Dong            fseeko(mFile, mOffset, SEEK_SET);
7107837c17063a4c50bc856ba59418516fdab731de7James Dong            fwrite(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, stream);
7117837c17063a4c50bc856ba59418516fdab731de7James Dong            fwrite(ptr, size, nmemb, stream);
7127837c17063a4c50bc856ba59418516fdab731de7James Dong            mOffset += (bytes + mMoovBoxBufferOffset);
7137837c17063a4c50bc856ba59418516fdab731de7James Dong            free(mMoovBoxBuffer);
7147837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBuffer = NULL;
7157837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset = 0;
7167837c17063a4c50bc856ba59418516fdab731de7James Dong            mWriteMoovBoxToMemory = false;
7177837c17063a4c50bc856ba59418516fdab731de7James Dong            mStreamableFile = false;
7187837c17063a4c50bc856ba59418516fdab731de7James Dong        } else {
7197837c17063a4c50bc856ba59418516fdab731de7James Dong            memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes);
7207837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset += bytes;
7217837c17063a4c50bc856ba59418516fdab731de7James Dong        }
7227837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
7237837c17063a4c50bc856ba59418516fdab731de7James Dong        fwrite(ptr, size, nmemb, stream);
7247837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset += bytes;
7257837c17063a4c50bc856ba59418516fdab731de7James Dong    }
7267837c17063a4c50bc856ba59418516fdab731de7James Dong    return bytes;
7277837c17063a4c50bc856ba59418516fdab731de7James Dong}
7287837c17063a4c50bc856ba59418516fdab731de7James Dong
72920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) {
7300c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(fourcc), 4);
73120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7327837c17063a4c50bc856ba59418516fdab731de7James Dong    mBoxes.push_back(mWriteMoovBoxToMemory?
7337837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset: mOffset);
73420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
73520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeInt32(0);
73620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeFourcc(fourcc);
73720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
73820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
73920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() {
7400c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(!mBoxes.empty());
74120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
74220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    off_t offset = *--mBoxes.end();
74320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mBoxes.erase(--mBoxes.end());
74420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7457837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
7467837c17063a4c50bc856ba59418516fdab731de7James Dong       int32_t x = htonl(mMoovBoxBufferOffset - offset);
7477837c17063a4c50bc856ba59418516fdab731de7James Dong       memcpy(mMoovBoxBuffer + offset, &x, 4);
7487837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
7497837c17063a4c50bc856ba59418516fdab731de7James Dong        fseeko(mFile, offset, SEEK_SET);
7507837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mOffset - offset);
7517837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset -= 4;
7527837c17063a4c50bc856ba59418516fdab731de7James Dong        fseeko(mFile, mOffset, SEEK_SET);
7537837c17063a4c50bc856ba59418516fdab731de7James Dong    }
75420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
75520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
75620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) {
7577837c17063a4c50bc856ba59418516fdab731de7James Dong    write(&x, 1, 1, mFile);
75820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
75920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
76020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) {
76120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htons(x);
7627837c17063a4c50bc856ba59418516fdab731de7James Dong    write(&x, 1, 2, mFile);
76320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
76420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
76520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) {
76620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htonl(x);
7677837c17063a4c50bc856ba59418516fdab731de7James Dong    write(&x, 1, 4, mFile);
76820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
76920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
77020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) {
77120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = hton64(x);
7727837c17063a4c50bc856ba59418516fdab731de7James Dong    write(&x, 1, 8, mFile);
77320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
77420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
77520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) {
77620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t n = strlen(s);
7777837c17063a4c50bc856ba59418516fdab731de7James Dong    write(s, 1, n + 1, mFile);
77820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
77920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
78020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) {
7810c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(s), 4);
7827837c17063a4c50bc856ba59418516fdab731de7James Dong    write(s, 1, 4, mFile);
78320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
78420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
78520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) {
7867837c17063a4c50bc856ba59418516fdab731de7James Dong    write(data, 1, size, mFile);
78720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
78820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
789d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() {
790d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
791d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileSizeLimitBytes == 0) {
792d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
793d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
794d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
795956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize);
796d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
797d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
798d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes();
799d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
8001f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
8011f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    return (nTotalBytesEstimate  + 1024 >= mMaxFileSizeLimitBytes);
802d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
803d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
804d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() {
805d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
806d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileDurationLimitUs == 0) {
807d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
808d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
809d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
810d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
811d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
812d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) {
813d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            return true;
814d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
815d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
816d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return false;
817d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
818d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
81925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() {
82025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool allDone = true;
82125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
82225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber         it != mTracks.end(); ++it) {
82325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        if (!(*it)->reachedEOS()) {
82425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            allDone = false;
82525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            break;
82625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        }
82725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
82825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
82925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return allDone;
83025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
83125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
832f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) {
833f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    LOGI("setStartTimestampUs: %lld", timeUs);
834f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    CHECK(timeUs >= 0);
8353c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
836065d1aff96818df54456053f1574aec8a234d0deJames Dong    if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) {
837f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mStartTimestampUs = timeUs;
838f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        LOGI("Earliest track starting time: %lld", mStartTimestampUs);
8393c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    }
8403c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
8413c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
842f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() {
8433c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
8443c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    return mStartTimestampUs;
8453c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
8463c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
84758ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() {
84858ae9c530247668f8af36e30d228c716c226b3d4James Dong    Mutex::Autolock autolock(mLock);
84958ae9c530247668f8af36e30d228c716c226b3d4James Dong    return mTracks.size();
85058ae9c530247668f8af36e30d228c716c226b3d4James Dong}
85158ae9c530247668f8af36e30d228c716c226b3d4James Dong
85220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
85320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
85420111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track(
85525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        MPEG4Writer *owner, const sp<MediaSource> &source)
85620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mOwner(owner),
85725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mMeta(source->getFormat()),
85820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSource(source),
85920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDone(false),
860a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
861a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mResumed(false),
862c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong      mTrackDurationUs(0),
863956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      mEstimatedTrackSizeBytes(0),
864be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong      mSamplesHaveSameSize(true),
86520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCodecSpecificData(NULL),
86625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mCodecSpecificDataSize(0),
867548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber      mGotAllCodecSpecificData(false),
86825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mReachedEOS(false) {
86919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    getCodecSpecificDataFromInputFormatIfPossible();
8708f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
8711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    const char *mime;
8721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mMeta->findCString(kKeyMIMEType, &mime);
8731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
8741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAudio = !strncasecmp(mime, "audio/", 6);
8751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
8761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong               !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC);
8771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
878c059860c73678a202bfa33062723e8f82fb779d9James Dong    setTimeScale();
879c059860c73678a202bfa33062723e8f82fb779d9James Dong}
880c059860c73678a202bfa33062723e8f82fb779d9James Dong
8811f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::updateTrackSizeEstimate() {
8821f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
8831f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    int64_t stcoBoxSizeBytes = mOwner->use32BitFileOffset()
8841f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                                ? mNumStcoTableEntries * 4
8851f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                                : mNumStcoTableEntries * 8;
8861f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
8871f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mNumSamples * 4);
8881f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
8891f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mEstimatedTrackSizeBytes = mMdatSizeBytes +             // media data size
8901f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                               mNumStscTableEntries * 12 +  // stsc box size
8911f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                               mNumStssTableEntries * 4 +   // stss box size
8921f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                               mNumSttsTableEntries * 8 +   // stts box size
8931f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                               stcoBoxSizeBytes +           // stco box size
8941f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                               stszBoxSizeBytes;            // stsz box size
8951f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
8961f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
8971f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStscTableEntry(
8981f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        size_t chunkId, size_t sampleId) {
8991f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
9001f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        StscTableEntry stscEntry(chunkId, sampleId, 1);
9011f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mStscTableEntries.push_back(stscEntry);
9021f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        ++mNumStscTableEntries;
9031f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
9041f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
9051f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) {
9061f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mStssTableEntries.push_back(sampleId);
9071f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    ++mNumStssTableEntries;
9081f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
9091f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
9101f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneSttsTableEntry(
9111f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        size_t sampleCount, int64_t durationUs) {
9121f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
9131f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    SttsTableEntry sttsEntry(sampleCount, durationUs);
9141f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mSttsTableEntries.push_back(sttsEntry);
9151f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    ++mNumSttsTableEntries;
9161f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
9171f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
9181f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addChunkOffset(off_t offset) {
9191f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    ++mNumStcoTableEntries;
9201f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mChunkOffsets.push_back(offset);
9211f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
9221f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
923c059860c73678a202bfa33062723e8f82fb779d9James Dongvoid MPEG4Writer::Track::setTimeScale() {
924c059860c73678a202bfa33062723e8f82fb779d9James Dong    LOGV("setTimeScale");
925c059860c73678a202bfa33062723e8f82fb779d9James Dong    // Default time scale
926c059860c73678a202bfa33062723e8f82fb779d9James Dong    mTimeScale = 90000;
927c059860c73678a202bfa33062723e8f82fb779d9James Dong
928c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mIsAudio) {
929c059860c73678a202bfa33062723e8f82fb779d9James Dong        // Use the sampling rate as the default time scale for audio track.
930c059860c73678a202bfa33062723e8f82fb779d9James Dong        int32_t sampleRate;
931c059860c73678a202bfa33062723e8f82fb779d9James Dong        bool success = mMeta->findInt32(kKeySampleRate, &sampleRate);
932c059860c73678a202bfa33062723e8f82fb779d9James Dong        CHECK(success);
933c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = sampleRate;
934c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
935c059860c73678a202bfa33062723e8f82fb779d9James Dong
936c059860c73678a202bfa33062723e8f82fb779d9James Dong    // If someone would like to overwrite the timescale, use user-supplied value.
937c059860c73678a202bfa33062723e8f82fb779d9James Dong    int32_t timeScale;
938c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mMeta->findInt32(kKeyTimeScale, &timeScale)) {
939c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = timeScale;
940c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
941c059860c73678a202bfa33062723e8f82fb779d9James Dong
9428f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    CHECK(mTimeScale > 0);
94319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber}
94419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
94519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Hubervoid MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() {
94619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    const char *mime;
94719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
94819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
94919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
95019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        uint32_t type;
95119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        const void *data;
95219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        size_t size;
95319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        if (mMeta->findData(kKeyAVCC, &type, &data, &size)) {
95419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mCodecSpecificData = malloc(size);
95519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mCodecSpecificDataSize = size;
95619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            memcpy(mCodecSpecificData, data, size);
95719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mGotAllCodecSpecificData = true;
95819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        }
95919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
96019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
96119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        uint32_t type;
96219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        const void *data;
96319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        size_t size;
96419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        if (mMeta->findData(kKeyESDS, &type, &data, &size)) {
96519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            ESDS esds(data, size);
96619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            if (esds.getCodecSpecificInfo(&data, &size) == OK) {
96719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mCodecSpecificData = malloc(size);
96819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mCodecSpecificDataSize = size;
96919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                memcpy(mCodecSpecificData, data, size);
97019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mGotAllCodecSpecificData = true;
97119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            }
97219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        }
97319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
97420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
97520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
97620111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() {
97720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    stop();
97820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
97920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mCodecSpecificData != NULL) {
98020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        free(mCodecSpecificData);
98120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mCodecSpecificData = NULL;
98220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
98320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
98420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
98593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) {
98693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    LOGV("initTrackingProgressStatus");
98793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mPreviousTrackTimeUs = -1;
98893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackingProgressStatus = false;
98993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackEveryTimeDurationUs = 0;
99093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    {
99193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        int64_t timeUs;
99293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) {
99393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            LOGV("Receive request to track progress status for every %lld us", timeUs);
99493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackEveryTimeDurationUs = timeUs;
99593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackingProgressStatus = true;
99693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
99793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
99893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
99993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
10001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong// static
10011c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid *MPEG4Writer::ThreadWrapper(void *me) {
10021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("ThreadWrapper: %p", me);
10031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    MPEG4Writer *writer = static_cast<MPEG4Writer *>(me);
10041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    writer->threadFunc();
10051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return NULL;
10061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
10071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
10081c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::bufferChunk(const Chunk& chunk) {
10091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("bufferChunk: %p", chunk.mTrack);
10101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Mutex::Autolock autolock(mLock);
10111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    CHECK_EQ(mDone, false);
10121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
10131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
10141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
10151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
10161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (chunk.mTrack == it->mTrack) {  // Found owner
10171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            it->mChunks.push_back(chunk);
10181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.signal();
10191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            return;
10201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
10211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
10221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
10231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    CHECK("Received a chunk for a unknown track" == 0);
10241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
10251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
10261c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::writeFirstChunk(ChunkInfo* info) {
10271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("writeFirstChunk: %p", info->mTrack);
10281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
10291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    List<Chunk>::iterator chunkIt = info->mChunks.begin();
10301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<MediaBuffer *>::iterator it = chunkIt->mSamples.begin();
10311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != chunkIt->mSamples.end(); ++it) {
10321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
10331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        off_t offset = info->mTrack->isAvc()
10341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                            ? addLengthPrefixedSample_l(*it)
10351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                            : addSample_l(*it);
10361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (it == chunkIt->mSamples.begin()) {
10371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            info->mTrack->addChunkOffset(offset);
10381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
10391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
10401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
10411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    // Done with the current chunk.
10421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    // Release all the samples in this chunk.
10431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    while (!chunkIt->mSamples.empty()) {
10441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        List<MediaBuffer *>::iterator it = chunkIt->mSamples.begin();
10451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it)->release();
10461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it) = NULL;
10471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        chunkIt->mSamples.erase(it);
10481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
10491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    chunkIt->mSamples.clear();
10501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    info->mChunks.erase(chunkIt);
10511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
10521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
10531c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::writeChunks() {
10541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("writeChunks");
10551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    size_t outstandingChunks = 0;
10561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    while (!mChunkInfos.empty()) {
10571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        List<ChunkInfo>::iterator it = mChunkInfos.begin();
10581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        while (!it->mChunks.empty()) {
10591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            CHECK_EQ(OK, writeOneChunk());
10601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            ++outstandingChunks;
10611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
10621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        it->mTrack = NULL;
10631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkInfos.erase(it);
10641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
10651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mChunkInfos.clear();
10661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGD("%d chunks are written in the last batch", outstandingChunks);
10671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
10681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
10691c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::writeOneChunk() {
10701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("writeOneChunk");
10711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
10721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    // Find the smallest timestamp, and write that chunk out
10731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    // XXX: What if some track is just too slow?
10741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL;
10751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Track *track = NULL;
10761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
10771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
10781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (!it->mChunks.empty()) {
10791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            List<Chunk>::iterator chunkIt = it->mChunks.begin();
10801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (chunkIt->mTimeStampUs < minTimestampUs) {
10811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                minTimestampUs = chunkIt->mTimeStampUs;
10821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                track = it->mTrack;
10831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            }
10841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
10851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
10861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
10871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (track == NULL) {
10881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        LOGV("Nothing to be written after all");
10891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        return OK;
10901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
10911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
10921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (mIsFirstChunk) {
10931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsFirstChunk = false;
10941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
10951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
10961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
10971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (it->mTrack == track) {
10981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            writeFirstChunk(&(*it));
10991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
11001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
11011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return OK;
11021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
11031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
11041c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::threadFunc() {
11051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("threadFunc");
11061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
11071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    while (!mDone) {
11081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        {
11091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            Mutex::Autolock autolock(mLock);
11101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.wait(mLock);
11111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            CHECK_EQ(writeOneChunk(), OK);
11121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
11131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
11141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
11151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    {
11161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        // Write ALL samples
11171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        Mutex::Autolock autolock(mLock);
11181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        writeChunks();
11191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
11201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
11211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
11221c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::startWriterThread() {
11231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("startWriterThread");
11241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
11251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mDone = false;
11261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsFirstChunk = true;
1127e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    mDriftTimeUs = 0;
11281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<Track *>::iterator it = mTracks.begin();
11291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mTracks.end(); ++it) {
11301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        ChunkInfo info;
11311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        info.mTrack = *it;
11321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkInfos.push_back(info);
11331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
11341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
11351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_t attr;
11361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_init(&attr);
11371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
11381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_create(&mThread, &attr, ThreadWrapper, this);
11391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_destroy(&attr);
11401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return OK;
11411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
11421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
11431f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
114493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) {
1145a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (!mDone && mPaused) {
1146a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mPaused = false;
1147a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mResumed = true;
1148a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
1149a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
115025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
115193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t startTimeUs;
115219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) {
115319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        startTimeUs = 0;
115419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
115519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
1156d0ea545d8357e7d86ad5f19cb2c6499c91786473James Dong    mIsRealTimeRecording = false;
1157e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    {
1158e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        int32_t isNotRealTime;
1159e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        if (params && params->findInt32(kKeyNotRealTime, &isNotRealTime)) {
1160e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            mIsRealTimeRecording = (isNotRealTime == 0);
1161e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        }
1162e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    }
1163e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
116493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    initTrackingProgressStatus(params);
116593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
1166f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    sp<MetaData> meta = new MetaData;
1167f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    meta->setInt64(kKeyTime, startTimeUs);
1168f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    status_t err = mSource->start(meta.get());
116925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    if (err != OK) {
117025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        mDone = mReachedEOS = true;
117125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return err;
117225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
117320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
117420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_t attr;
117520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_init(&attr);
117620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
117720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
117820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = false;
1179c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs = 0;
118025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = false;
1181956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    mEstimatedTrackSizeBytes = 0;
11821f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mNumStcoTableEntries = 0;
11831f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mNumStssTableEntries = 0;
11841f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mNumStscTableEntries = 0;
11851f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mNumSttsTableEntries = 0;
11861f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mMdatSizeBytes = 0;
1187872a481558350634a3fd5cb67939de288af00ecbJames Dong    mIsMediaTimeAdjustmentOn = false;
1188872a481558350634a3fd5cb67939de288af00ecbJames Dong    mPrevMediaTimeAdjustTimestampUs = 0;
1189872a481558350634a3fd5cb67939de288af00ecbJames Dong    mMediaTimeAdjustNumFrames = 0;
1190872a481558350634a3fd5cb67939de288af00ecbJames Dong    mPrevMediaTimeAdjustSample = 0;
1191872a481558350634a3fd5cb67939de288af00ecbJames Dong    mTotalDriftTimeToAdjustUs = 0;
1192872a481558350634a3fd5cb67939de288af00ecbJames Dong    mPrevTotalAccumDriftTimeUs = 0;
119320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
119425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    pthread_create(&mThread, &attr, ThreadWrapper, this);
119520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_destroy(&attr);
119625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
119725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
119820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
119920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
120037187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::pause() {
1201a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
120237187916a486504acaf83bea30147eb5fbf46ae5James Dong    return OK;
1203a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
1204a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
120537187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::stop() {
120620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mDone) {
120737187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
120820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
120920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
121020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = true;
121120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
121220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *dummy;
121320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_join(mThread, &dummy);
121420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
121537187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = (status_t) dummy;
121637187916a486504acaf83bea30147eb5fbf46ae5James Dong
121737187916a486504acaf83bea30147eb5fbf46ae5James Dong    {
121837187916a486504acaf83bea30147eb5fbf46ae5James Dong        status_t status = mSource->stop();
121937187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (err == OK && status != OK && status != ERROR_END_OF_STREAM) {
122037187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
122137187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
122237187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
122337187916a486504acaf83bea30147eb5fbf46ae5James Dong
122437187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
122520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
122620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
122725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() {
122825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return mReachedEOS;
122925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
123025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
123120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static
123220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) {
123320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = static_cast<Track *>(me);
123420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
123537187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = track->threadEntry();
123637187916a486504acaf83bea30147eb5fbf46ae5James Dong    return (void *) err;
123720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
123820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic void getNalUnitType(uint8_t byte, uint8_t* type) {
12403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    LOGV("getNalUnitType: %d", byte);
12413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
12423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // nal_unit_type: 5-bit unsigned integer
12433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *type = (byte & 0x1F);
12443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
12453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
12463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t *findNextStartCode(
12473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length) {
12483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
12493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    LOGV("findNextStartCode: %p %d", data, length);
12503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
12513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t bytesLeft = length;
12523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    while (bytesLeft > 4  &&
12533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            memcmp("\x00\x00\x00\x01", &data[length - bytesLeft], 4)) {
12543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        --bytesLeft;
12553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
12563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (bytesLeft <= 4) {
12573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        bytesLeft = 0; // Last parameter set
12583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
12593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return &data[length - bytesLeft];
12603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
12613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
12623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongconst uint8_t *MPEG4Writer::Track::parseParamSet(
12633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen) {
12643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
12653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    LOGV("parseParamSet");
12663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    CHECK(type == kNalUnitTypeSeqParamSet ||
12673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong          type == kNalUnitTypePicParamSet);
12683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
12693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *nextStartCode = findNextStartCode(data, length);
12703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *paramSetLen = nextStartCode - data;
12713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (*paramSetLen == 0) {
12723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        LOGE("Param set is malformed, since its length is 0");
12733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return NULL;
12743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
12753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
12763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    AVCParamSet paramSet(*paramSetLen, data);
12773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (type == kNalUnitTypeSeqParamSet) {
12783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (*paramSetLen < 4) {
12793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Seq parameter set malformed");
12803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return NULL;
12813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
12823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mSeqParamSets.empty()) {
12833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc = data[1];
12843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileCompatible = data[2];
12853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mLevelIdc = data[3];
12863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
12873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (mProfileIdc != data[1] ||
12883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mProfileCompatible != data[2] ||
12893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mLevelIdc != data[3]) {
12903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                LOGE("Inconsistent profile/level found in seq parameter sets");
12913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return NULL;
12923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
12933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
12943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mSeqParamSets.push_back(paramSet);
12953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    } else {
12963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mPicParamSets.push_back(paramSet);
12973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
12983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return nextStartCode;
12993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
13003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::copyAVCCodecSpecificData(
13023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
13033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    LOGV("copyAVCCodecSpecificData");
13043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 2 bytes for each of the parameter set length field
13063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // plus the 7 bytes for the header
13073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (size < 4 + 7) {
13083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        LOGE("Codec specific data length too short: %d", size);
13093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return ERROR_MALFORMED;
13103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
13113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize = size;
13133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificData = malloc(size);
13143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    memcpy(mCodecSpecificData, data, size);
13153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
13163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
13173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::parseAVCCodecSpecificData(
13193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
13203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    LOGV("parseAVCCodecSpecificData");
13223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data starts with a start code.
13233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // SPS and PPS are separated with start codes.
13243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Also, SPS must come before PPS
13253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t type = kNalUnitTypeSeqParamSet;
13263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotSps = false;
13273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotPps = false;
13283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *tmp = data;
13293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *nextStartCode = data;
13303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t bytesLeft = size;
13313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t paramSetLen = 0;
13323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize = 0;
13333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) {
13343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        getNalUnitType(*(tmp + 4), &type);
13353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (type == kNalUnitTypeSeqParamSet) {
13363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (gotPps) {
13373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                LOGE("SPS must come before PPS");
13383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
13393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
13403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
13413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotSps = true;
13423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
13433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
13443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else if (type == kNalUnitTypePicParamSet) {
13453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
13463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                LOGE("SPS must come before PPS");
13473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
13483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
13493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotPps) {
13503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotPps = true;
13513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
13523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
13533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
13543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Only SPS and PPS Nal units are expected");
13553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
13563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
13573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nextStartCode == NULL) {
13593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
13603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
13613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Move on to find the next parameter set
13633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        bytesLeft -= nextStartCode - tmp;
13643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        tmp = nextStartCode;
13653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mCodecSpecificDataSize += (2 + paramSetLen);
13663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
13673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
13693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of seq parameter sets
13703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nSeqParamSets = mSeqParamSets.size();
13713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets == 0) {
13723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Cound not find sequence parameter set");
13733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
13743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
13753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets > 0x1F) {
13773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Too many seq parameter sets (%d) found", nSeqParamSets);
13783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
13793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
13803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
13813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
13833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of pic parameter sets
13843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nPicParamSets = mPicParamSets.size();
13853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets == 0) {
13863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Cound not find picture parameter set");
13873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
13883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
13893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets > 0xFF) {
13903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Too many pic parameter sets (%d) found", nPicParamSets);
13913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
13923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
13933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
13943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
13963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the profiles
13973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // These profiles requires additional parameter set extensions
13983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mProfileIdc == 100 || mProfileIdc == 110 ||
13993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc == 122 || mProfileIdc == 144) {
14003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Sorry, no support for profile_idc: %d!", mProfileIdc);
14013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return BAD_VALUE;
14023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
14033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
14043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
14053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
14063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
1407548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
140803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData(
140903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        const uint8_t *data, size_t size) {
1410548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
141103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (mCodecSpecificData != NULL) {
1412548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        LOGE("Already have codec specific data");
141303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
141403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
141503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
14163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (size < 4) {
14173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        LOGE("Codec specific data length too short: %d", size);
141803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
141903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
142003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
14213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data is in the form of AVCCodecSpecificData
14223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (memcmp("\x00\x00\x00\x01", data, 4)) {
14233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return copyAVCCodecSpecificData(data, size);
142403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
142503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
14263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (parseAVCCodecSpecificData(data, size) != OK) {
142703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
142803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
142903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
14303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // ISO 14496-15: AVC file format
14313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize += 7;  // 7 more bytes in the header
143203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    mCodecSpecificData = malloc(mCodecSpecificDataSize);
143303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    uint8_t *header = (uint8_t *)mCodecSpecificData;
14343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = 1;                     // version
14353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[1] = mProfileIdc;           // profile indication
14363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[2] = mProfileCompatible;    // profile compatibility
14373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[3] = mLevelIdc;
143803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
14393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne
1440b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (mOwner->useNalLengthFour()) {
1441b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        header[4] = 0xfc | 3;  // length size == 4 bytes
1442b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    } else {
1443b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        header[4] = 0xfc | 1;  // length size == 2 bytes
1444b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    }
144503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
14463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 3-bit '111' followed by 5-bit numSequenceParameterSets
14473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nSequenceParamSets = mSeqParamSets.size();
14483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[5] = 0xe0 | nSequenceParamSets;
14493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 6;
14503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mSeqParamSets.begin();
14513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mSeqParamSets.end(); ++it) {
14523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit sequence parameter set length
14533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t seqParamSetLength = it->mLength;
14543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = seqParamSetLength >> 8;
14553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = seqParamSetLength & 0xff;
14563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
14573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // SPS NAL unit (sequence parameter length bytes)
14583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, seqParamSetLength);
14593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + seqParamSetLength);
14603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
14613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
14623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 8-bit nPictureParameterSets
14633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nPictureParamSets = mPicParamSets.size();
14643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = nPictureParamSets;
14653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 1;
14663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mPicParamSets.begin();
14673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mPicParamSets.end(); ++it) {
14683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit picture parameter set length
14693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t picParamSetLength = it->mLength;
14703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = picParamSetLength >> 8;
14713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = picParamSetLength & 0xff;
14723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
14733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // PPS Nal unit (picture parameter set length bytes)
14743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, picParamSetLength);
14753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + picParamSetLength);
14763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
147703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
147803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    return OK;
147903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
148003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
1481872a481558350634a3fd5cb67939de288af00ecbJames Dong/*
1482872a481558350634a3fd5cb67939de288af00ecbJames Dong* The video track's media time adjustment for real-time applications
1483872a481558350634a3fd5cb67939de288af00ecbJames Dong* is described as follows:
1484872a481558350634a3fd5cb67939de288af00ecbJames Dong*
1485872a481558350634a3fd5cb67939de288af00ecbJames Dong* First, the media time adjustment is done for every period of
1486872a481558350634a3fd5cb67939de288af00ecbJames Dong* kVideoMediaTimeAdjustPeriodTimeUs. kVideoMediaTimeAdjustPeriodTimeUs
1487872a481558350634a3fd5cb67939de288af00ecbJames Dong* is currently a fixed value chosen heuristically. The value of
1488872a481558350634a3fd5cb67939de288af00ecbJames Dong* kVideoMediaTimeAdjustPeriodTimeUs should not be very large or very small
1489872a481558350634a3fd5cb67939de288af00ecbJames Dong* for two considerations: on one hand, a relatively large value
1490872a481558350634a3fd5cb67939de288af00ecbJames Dong* helps reduce large fluctuation of drift time in the audio encoding
1491872a481558350634a3fd5cb67939de288af00ecbJames Dong* path; while on the other hand, a relatively small value helps keep
1492872a481558350634a3fd5cb67939de288af00ecbJames Dong* restoring synchronization in audio/video more frequently. Note for the
1493872a481558350634a3fd5cb67939de288af00ecbJames Dong* very first period of kVideoMediaTimeAdjustPeriodTimeUs, there is
1494872a481558350634a3fd5cb67939de288af00ecbJames Dong* no media time adjustment for the video track.
1495872a481558350634a3fd5cb67939de288af00ecbJames Dong*
1496872a481558350634a3fd5cb67939de288af00ecbJames Dong* Second, the total accumulated audio track time drift found
1497872a481558350634a3fd5cb67939de288af00ecbJames Dong* in a period of kVideoMediaTimeAdjustPeriodTimeUs is distributed
1498872a481558350634a3fd5cb67939de288af00ecbJames Dong* over a stream of incoming video frames. The number of video frames
1499872a481558350634a3fd5cb67939de288af00ecbJames Dong* affected is determined based on the number of recorded video frames
1500872a481558350634a3fd5cb67939de288af00ecbJames Dong* within the past kVideoMediaTimeAdjustPeriodTimeUs period.
1501872a481558350634a3fd5cb67939de288af00ecbJames Dong* We choose to distribute the drift time over only a portion
1502872a481558350634a3fd5cb67939de288af00ecbJames Dong* (rather than all) of the total number of recorded video frames
1503872a481558350634a3fd5cb67939de288af00ecbJames Dong* in order to make sure that the video track media time adjustment is
1504872a481558350634a3fd5cb67939de288af00ecbJames Dong* completed for the current period before the next video track media
1505872a481558350634a3fd5cb67939de288af00ecbJames Dong* time adjustment period starts. Currently, the portion chosen is a
1506872a481558350634a3fd5cb67939de288af00ecbJames Dong* half (0.5).
1507872a481558350634a3fd5cb67939de288af00ecbJames Dong*
1508872a481558350634a3fd5cb67939de288af00ecbJames Dong* Last, various additional checks are performed to ensure that
1509872a481558350634a3fd5cb67939de288af00ecbJames Dong* the actual audio encoding path does not have too much drift.
1510872a481558350634a3fd5cb67939de288af00ecbJames Dong* In particular, 1) we want to limit the average incremental time
1511872a481558350634a3fd5cb67939de288af00ecbJames Dong* adjustment for each video frame to be less than a threshold
1512872a481558350634a3fd5cb67939de288af00ecbJames Dong* for a single period of kVideoMediaTimeAdjustPeriodTimeUs.
1513872a481558350634a3fd5cb67939de288af00ecbJames Dong* Currently, the threshold is set to 5 ms. If the average incremental
1514872a481558350634a3fd5cb67939de288af00ecbJames Dong* media time adjustment for a video frame is larger than the
1515872a481558350634a3fd5cb67939de288af00ecbJames Dong* threshold, the audio encoding path has too much time drift.
1516872a481558350634a3fd5cb67939de288af00ecbJames Dong* 2) We also want to limit the total time drift in the audio
1517872a481558350634a3fd5cb67939de288af00ecbJames Dong* encoding path to be less than a threshold for a period of
1518872a481558350634a3fd5cb67939de288af00ecbJames Dong* kVideoMediaTimeAdjustPeriodTimeUs. Currently, the threshold
1519872a481558350634a3fd5cb67939de288af00ecbJames Dong* is 0.5% of kVideoMediaTimeAdjustPeriodTimeUs. If the time drift of
1520872a481558350634a3fd5cb67939de288af00ecbJames Dong* the audio encoding path is larger than the threshold, the audio
1521872a481558350634a3fd5cb67939de288af00ecbJames Dong* encoding path has too much time drift. We treat the large time
1522872a481558350634a3fd5cb67939de288af00ecbJames Dong* drift of the audio encoding path as errors, since there is no
1523872a481558350634a3fd5cb67939de288af00ecbJames Dong* way to keep audio/video in synchronization for real-time
1524872a481558350634a3fd5cb67939de288af00ecbJames Dong* applications if the time drift is too large unless we drop some
1525872a481558350634a3fd5cb67939de288af00ecbJames Dong* video frames, which has its own problems that we don't want
1526872a481558350634a3fd5cb67939de288af00ecbJames Dong* to get into for the time being.
1527872a481558350634a3fd5cb67939de288af00ecbJames Dong*/
1528872a481558350634a3fd5cb67939de288af00ecbJames Dongvoid MPEG4Writer::Track::adjustMediaTime(int64_t *timestampUs) {
1529872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (*timestampUs - mPrevMediaTimeAdjustTimestampUs >=
1530872a481558350634a3fd5cb67939de288af00ecbJames Dong        kVideoMediaTimeAdjustPeriodTimeUs) {
1531872a481558350634a3fd5cb67939de288af00ecbJames Dong
1532872a481558350634a3fd5cb67939de288af00ecbJames Dong        LOGV("New media time adjustment period at %lld us", *timestampUs);
1533872a481558350634a3fd5cb67939de288af00ecbJames Dong        mIsMediaTimeAdjustmentOn = true;
1534872a481558350634a3fd5cb67939de288af00ecbJames Dong        mMediaTimeAdjustNumFrames =
1535872a481558350634a3fd5cb67939de288af00ecbJames Dong                (mNumSamples - mPrevMediaTimeAdjustSample) >> 1;
1536872a481558350634a3fd5cb67939de288af00ecbJames Dong
1537872a481558350634a3fd5cb67939de288af00ecbJames Dong        mPrevMediaTimeAdjustTimestampUs = *timestampUs;
1538872a481558350634a3fd5cb67939de288af00ecbJames Dong        mPrevMediaTimeAdjustSample = mNumSamples;
1539872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t totalAccumDriftTimeUs = mOwner->getDriftTimeUs();
1540872a481558350634a3fd5cb67939de288af00ecbJames Dong        mTotalDriftTimeToAdjustUs =
1541872a481558350634a3fd5cb67939de288af00ecbJames Dong                totalAccumDriftTimeUs - mPrevTotalAccumDriftTimeUs;
1542872a481558350634a3fd5cb67939de288af00ecbJames Dong
1543872a481558350634a3fd5cb67939de288af00ecbJames Dong        mPrevTotalAccumDriftTimeUs = totalAccumDriftTimeUs;
1544872a481558350634a3fd5cb67939de288af00ecbJames Dong
1545872a481558350634a3fd5cb67939de288af00ecbJames Dong        // Check on incremental adjusted time per frame
1546872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t adjustTimePerFrameUs =
1547872a481558350634a3fd5cb67939de288af00ecbJames Dong                mTotalDriftTimeToAdjustUs / mMediaTimeAdjustNumFrames;
1548872a481558350634a3fd5cb67939de288af00ecbJames Dong
1549872a481558350634a3fd5cb67939de288af00ecbJames Dong        if (adjustTimePerFrameUs < 0) {
1550872a481558350634a3fd5cb67939de288af00ecbJames Dong            adjustTimePerFrameUs = -adjustTimePerFrameUs;
1551872a481558350634a3fd5cb67939de288af00ecbJames Dong        }
1552872a481558350634a3fd5cb67939de288af00ecbJames Dong        if (adjustTimePerFrameUs >= 5000) {
1553872a481558350634a3fd5cb67939de288af00ecbJames Dong            LOGE("Adjusted time per video frame is %lld us",
1554872a481558350634a3fd5cb67939de288af00ecbJames Dong                adjustTimePerFrameUs);
1555872a481558350634a3fd5cb67939de288af00ecbJames Dong            CHECK(!"Video frame time adjustment is too large!");
1556872a481558350634a3fd5cb67939de288af00ecbJames Dong        }
1557872a481558350634a3fd5cb67939de288af00ecbJames Dong
1558872a481558350634a3fd5cb67939de288af00ecbJames Dong        // Check on total accumulated time drift within a period of
1559872a481558350634a3fd5cb67939de288af00ecbJames Dong        // kVideoMediaTimeAdjustPeriodTimeUs.
1560872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t driftPercentage = (mTotalDriftTimeToAdjustUs * 1000)
1561872a481558350634a3fd5cb67939de288af00ecbJames Dong                / kVideoMediaTimeAdjustPeriodTimeUs;
1562872a481558350634a3fd5cb67939de288af00ecbJames Dong
1563872a481558350634a3fd5cb67939de288af00ecbJames Dong        if (driftPercentage < 0) {
1564872a481558350634a3fd5cb67939de288af00ecbJames Dong            driftPercentage = -driftPercentage;
1565872a481558350634a3fd5cb67939de288af00ecbJames Dong        }
1566872a481558350634a3fd5cb67939de288af00ecbJames Dong        if (driftPercentage > 5) {
1567872a481558350634a3fd5cb67939de288af00ecbJames Dong            LOGE("Audio track has time drift %lld us over %lld us",
1568872a481558350634a3fd5cb67939de288af00ecbJames Dong                mTotalDriftTimeToAdjustUs,
1569872a481558350634a3fd5cb67939de288af00ecbJames Dong                kVideoMediaTimeAdjustPeriodTimeUs);
1570872a481558350634a3fd5cb67939de288af00ecbJames Dong
1571872a481558350634a3fd5cb67939de288af00ecbJames Dong            CHECK(!"The audio track media time drifts too much!");
1572872a481558350634a3fd5cb67939de288af00ecbJames Dong        }
1573872a481558350634a3fd5cb67939de288af00ecbJames Dong
1574872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
1575872a481558350634a3fd5cb67939de288af00ecbJames Dong
1576872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (mIsMediaTimeAdjustmentOn) {
1577872a481558350634a3fd5cb67939de288af00ecbJames Dong        if (mNumSamples - mPrevMediaTimeAdjustSample <=
1578872a481558350634a3fd5cb67939de288af00ecbJames Dong            mMediaTimeAdjustNumFrames) {
1579872a481558350634a3fd5cb67939de288af00ecbJames Dong
1580872a481558350634a3fd5cb67939de288af00ecbJames Dong            // Do media time incremental adjustment
1581872a481558350634a3fd5cb67939de288af00ecbJames Dong            int64_t incrementalAdjustTimeUs =
1582872a481558350634a3fd5cb67939de288af00ecbJames Dong                        (mTotalDriftTimeToAdjustUs *
1583872a481558350634a3fd5cb67939de288af00ecbJames Dong                            (mNumSamples - mPrevMediaTimeAdjustSample))
1584872a481558350634a3fd5cb67939de288af00ecbJames Dong                                / mMediaTimeAdjustNumFrames;
1585872a481558350634a3fd5cb67939de288af00ecbJames Dong
1586872a481558350634a3fd5cb67939de288af00ecbJames Dong            *timestampUs +=
1587872a481558350634a3fd5cb67939de288af00ecbJames Dong                (incrementalAdjustTimeUs + mPrevTotalAccumDriftTimeUs);
1588872a481558350634a3fd5cb67939de288af00ecbJames Dong
1589872a481558350634a3fd5cb67939de288af00ecbJames Dong            LOGV("Incremental video frame media time adjustment: %lld us",
1590872a481558350634a3fd5cb67939de288af00ecbJames Dong                (incrementalAdjustTimeUs + mPrevTotalAccumDriftTimeUs));
1591872a481558350634a3fd5cb67939de288af00ecbJames Dong        } else {
1592872a481558350634a3fd5cb67939de288af00ecbJames Dong            // Within the remaining adjustment period,
1593872a481558350634a3fd5cb67939de288af00ecbJames Dong            // no incremental adjustment is needed.
1594872a481558350634a3fd5cb67939de288af00ecbJames Dong            *timestampUs +=
1595872a481558350634a3fd5cb67939de288af00ecbJames Dong                (mTotalDriftTimeToAdjustUs + mPrevTotalAccumDriftTimeUs);
1596872a481558350634a3fd5cb67939de288af00ecbJames Dong
1597872a481558350634a3fd5cb67939de288af00ecbJames Dong            LOGV("Fixed video frame media time adjustment: %lld us",
1598872a481558350634a3fd5cb67939de288af00ecbJames Dong                (mTotalDriftTimeToAdjustUs + mPrevTotalAccumDriftTimeUs));
1599872a481558350634a3fd5cb67939de288af00ecbJames Dong        }
1600872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
1601872a481558350634a3fd5cb67939de288af00ecbJames Dong}
1602872a481558350634a3fd5cb67939de288af00ecbJames Dong
1603872a481558350634a3fd5cb67939de288af00ecbJames Dong/*
1604872a481558350634a3fd5cb67939de288af00ecbJames Dong * Updates the drift time from the audio track so that
1605872a481558350634a3fd5cb67939de288af00ecbJames Dong * the video track can get the updated drift time information
1606872a481558350634a3fd5cb67939de288af00ecbJames Dong * from the file writer. The fluctuation of the drift time of the audio
1607872a481558350634a3fd5cb67939de288af00ecbJames Dong * encoding path is smoothed out with a simple filter by giving a larger
1608872a481558350634a3fd5cb67939de288af00ecbJames Dong * weight to more recently drift time. The filter coefficients, 0.5 and 0.5,
1609872a481558350634a3fd5cb67939de288af00ecbJames Dong * are heuristically determined.
1610872a481558350634a3fd5cb67939de288af00ecbJames Dong */
1611872a481558350634a3fd5cb67939de288af00ecbJames Dongvoid MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) {
1612872a481558350634a3fd5cb67939de288af00ecbJames Dong    int64_t driftTimeUs = 0;
1613872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) {
1614872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t prevDriftTimeUs = mOwner->getDriftTimeUs();
1615872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1;
1616872a481558350634a3fd5cb67939de288af00ecbJames Dong        mOwner->setDriftTimeUs(timeUs);
1617872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
1618872a481558350634a3fd5cb67939de288af00ecbJames Dong}
1619872a481558350634a3fd5cb67939de288af00ecbJames Dong
162037187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::threadEntry() {
162130ab66297501757d745b9ae10da61adcd891f497Andreas Huber    int32_t count = 0;
162213aec890216948b0c364f8f92792129d0335f506James Dong    const int64_t interleaveDurationUs = mOwner->interleaveDuration();
162313aec890216948b0c364f8f92792129d0335f506James Dong    int64_t chunkTimestampUs = 0;
162413aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nChunks = 0;
162513aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nZeroLengthFrames = 0;
16268f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t lastTimestampUs = 0;  // Previous sample time stamp in ms
16278f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t lastDurationUs = 0;   // Between the previous two samples in ms
1628c059860c73678a202bfa33062723e8f82fb779d9James Dong    int64_t currDurationTicks = 0;  // Timescale based ticks
1629c059860c73678a202bfa33062723e8f82fb779d9James Dong    int64_t lastDurationTicks = 0;  // Timescale based ticks
16308f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int32_t sampleCount = 1;      // Sample count in the current stts table entry
1631be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    uint32_t previousSampleSize = 0;  // Size of the previous sample
1632a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    int64_t previousPausedDurationUs = 0;
16331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    int64_t timestampUs;
1634e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
1635d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong    sp<MetaData> meta_data;
163620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1637ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    mNumSamples = 0;
163893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t err = OK;
163920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBuffer *buffer;
164093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    while (!mDone && (err = mSource->read(&buffer)) == OK) {
164120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (buffer->range_length() == 0) {
164220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer->release();
164320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer = NULL;
164413aec890216948b0c364f8f92792129d0335f506James Dong            ++nZeroLengthFrames;
164520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            continue;
164620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
164720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1648a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // If the codec specific data has not been received yet, delay pause.
1649a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // After the codec specific data is received, discard what we received
1650a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // when the track is to be paused.
1651a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused && !mResumed) {
1652a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer->release();
1653a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer = NULL;
1654a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            continue;
1655a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
1656a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
165730ab66297501757d745b9ae10da61adcd891f497Andreas Huber        ++count;
165830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
165903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        int32_t isCodecConfig;
166003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig)
166103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                && isCodecConfig) {
1662548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            CHECK(!mGotAllCodecSpecificData);
1663548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
16641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (mIsAvc) {
166503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                status_t err = makeAVCCodecSpecificData(
166603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        (const uint8_t *)buffer->data()
166703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                            + buffer->range_offset(),
166803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        buffer->range_length());
1669be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                CHECK_EQ(OK, err);
16701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            } else if (mIsMPEG4) {
167103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificDataSize = buffer->range_length();
167203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificData = malloc(mCodecSpecificDataSize);
167303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                memcpy(mCodecSpecificData,
167403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        (const uint8_t *)buffer->data()
167503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                            + buffer->range_offset(),
167603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                       buffer->range_length());
167730ab66297501757d745b9ae10da61adcd891f497Andreas Huber            }
167830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
167930ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer->release();
168030ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer = NULL;
168130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
1682548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            mGotAllCodecSpecificData = true;
168330ab66297501757d745b9ae10da61adcd891f497Andreas Huber            continue;
1684a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
1685a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
1686d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // Make a deep copy of the MediaBuffer and Metadata and release
1687d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // the original as soon as we can
1688d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        MediaBuffer *copy = new MediaBuffer(buffer->range_length());
1689d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(),
1690d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong                buffer->range_length());
1691d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        copy->set_range(0, buffer->range_length());
1692d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data = new MetaData(*buffer->meta_data().get());
1693d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer->release();
1694d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer = NULL;
1695d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
16961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (mIsAvc) StripStartcode(copy);
1697e136c3bb38e88315bf8797a464ebf2c788296b22James Dong
1698b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        size_t sampleSize = copy->range_length();
1699b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        if (mIsAvc) {
1700b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            if (mOwner->useNalLengthFour()) {
1701b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                sampleSize += 4;
1702b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            } else {
1703b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                sampleSize += 2;
1704b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            }
1705b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        }
1706050b28a593350047845a45a14cc5026221ac1620James Dong
1707d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        // Max file size or duration handling
17081f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mMdatSizeBytes += sampleSize;
17091f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        updateTrackSizeEstimate();
17101f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1711d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileSizeLimit()) {
1712d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
1713d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
1714d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
1715d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileDurationLimit()) {
1716d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
1717d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
1718d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
1719d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1720050b28a593350047845a45a14cc5026221ac1620James Dong
1721d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        int32_t isSync = false;
1722d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data->findInt32(kKeyIsSyncFrame, &isSync);
1723d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
17248428af5381e835cc783b7ecb0d71cb60961c99c2James Dong        /*
17258428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * The original timestamp found in the data buffer will be modified as below:
17268428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         *
17278428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * There is a playback offset into this track if the track's start time
17288428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * is not the same as the movie start time, which will be recorded in edst
17298428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * box of the output file. The playback offset is to make sure that the
17308428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * starting time of the audio/video tracks are synchronized. Although the
17318428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * track's media timestamp may be subject to various modifications
17328428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * as outlined below, the track's playback offset time remains unchanged
17338428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * once the first data buffer of the track is received.
17348428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         *
17358428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * The media time stamp will be calculated by subtracting the playback offset
17368428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * (and potential pause durations) from the original timestamp in the buffer.
17378428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         *
17388428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * If this track is a video track for a real-time recording application with
17398428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * both audio and video tracks, its media timestamp will subject to further
17408428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * modification based on the media clock of the audio track. This modification
17418428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * is needed for the purpose of maintaining good audio/video synchronization.
17428428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         *
17438428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * If the recording session is paused and resumed multiple times, the track
17448428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * media timestamp will be modified as if the  recording session had never been
17458428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * paused at all during playback of the recorded output file. In other words,
17468428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * the output file will have no memory of pause/resume durations.
17478428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         *
17488428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         */
1749d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        CHECK(meta_data->findInt64(kKeyTime, &timestampUs));
17508428af5381e835cc783b7ecb0d71cb60961c99c2James Dong        LOGV("%s timestampUs: %lld", mIsAudio? "Audio": "Video", timestampUs);
1751d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
1752d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong////////////////////////////////////////////////////////////////////////////////
17538644c14618d30d9e57a69df40ed939986ebf02c4James Dong        if (mSampleSizes.empty()) {
1754f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mStartTimestampUs = timestampUs;
1755f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mOwner->setStartTimestampUs(mStartTimestampUs);
17568428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            previousPausedDurationUs = mStartTimestampUs;
17573c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        }
175848c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber
1759a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mResumed) {
17608428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs;
17618428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            CHECK(durExcludingEarlierPausesUs >= 0);
17628428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs;
17638428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            CHECK(pausedDurationUs >= lastDurationUs);
17648428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            previousPausedDurationUs += pausedDurationUs - lastDurationUs;
1765a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mResumed = false;
1766a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
1767a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
1768a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        timestampUs -= previousPausedDurationUs;
17698428af5381e835cc783b7ecb0d71cb60961c99c2James Dong        CHECK(timestampUs >= 0);
1770872a481558350634a3fd5cb67939de288af00ecbJames Dong
1771872a481558350634a3fd5cb67939de288af00ecbJames Dong        // Media time adjustment for real-time applications
1772872a481558350634a3fd5cb67939de288af00ecbJames Dong        if (mIsRealTimeRecording) {
1773872a481558350634a3fd5cb67939de288af00ecbJames Dong            if (mIsAudio) {
1774872a481558350634a3fd5cb67939de288af00ecbJames Dong                updateDriftTime(meta_data);
1775872a481558350634a3fd5cb67939de288af00ecbJames Dong            } else {
1776872a481558350634a3fd5cb67939de288af00ecbJames Dong                adjustMediaTime(&timestampUs);
1777e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            }
1778e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        }
1779872a481558350634a3fd5cb67939de288af00ecbJames Dong
1780e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        CHECK(timestampUs >= 0);
1781e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        if (mNumSamples > 1) {
1782e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            if (timestampUs <= lastTimestampUs) {
17834f86a980fee1880dca61b828599fa6d76755a485James Dong                LOGW("Frame arrives too late!");
17844f86a980fee1880dca61b828599fa6d76755a485James Dong                // Don't drop the late frame, since dropping a frame may cause
17854f86a980fee1880dca61b828599fa6d76755a485James Dong                // problems later during playback
17864f86a980fee1880dca61b828599fa6d76755a485James Dong
17874f86a980fee1880dca61b828599fa6d76755a485James Dong                // The idea here is to avoid having two or more samples with the
17884f86a980fee1880dca61b828599fa6d76755a485James Dong                // same timestamp in the output file.
17894f86a980fee1880dca61b828599fa6d76755a485James Dong                if (mTimeScale >= 1000000LL) {
179040e9940fadf22daa64c1e766fa8a855c7b149c17James Dong                    timestampUs = lastTimestampUs + 1;
17914f86a980fee1880dca61b828599fa6d76755a485James Dong                } else {
179240e9940fadf22daa64c1e766fa8a855c7b149c17James Dong                    timestampUs = lastTimestampUs + (1000000LL + (mTimeScale >> 1)) / mTimeScale;
17934f86a980fee1880dca61b828599fa6d76755a485James Dong                }
1794e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            }
1795e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        }
1796e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
17978428af5381e835cc783b7ecb0d71cb60961c99c2James Dong        LOGV("%s media time stamp: %lld and previous paused duration %lld",
17988428af5381e835cc783b7ecb0d71cb60961c99c2James Dong                mIsAudio? "Audio": "Video", timestampUs, previousPausedDurationUs);
1799c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong        if (timestampUs > mTrackDurationUs) {
1800c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong            mTrackDurationUs = timestampUs;
18013b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber        }
18023b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber
18038644c14618d30d9e57a69df40ed939986ebf02c4James Dong        mSampleSizes.push_back(sampleSize);
1804ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong        ++mNumSamples;
1805ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong        if (mNumSamples > 2) {
1806c059860c73678a202bfa33062723e8f82fb779d9James Dong            // We need to use the time scale based ticks, rather than the
1807c059860c73678a202bfa33062723e8f82fb779d9James Dong            // timestamp itself to determine whether we have to use a new
1808c059860c73678a202bfa33062723e8f82fb779d9James Dong            // stts entry, since we may have rounding errors.
1809c059860c73678a202bfa33062723e8f82fb779d9James Dong            // The calculation is intended to reduce the accumulated
1810c059860c73678a202bfa33062723e8f82fb779d9James Dong            // rounding errors.
1811c059860c73678a202bfa33062723e8f82fb779d9James Dong            currDurationTicks =
1812c059860c73678a202bfa33062723e8f82fb779d9James Dong                     ((timestampUs * mTimeScale + 500000LL) / 1000000LL -
1813c059860c73678a202bfa33062723e8f82fb779d9James Dong                     (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL);
1814c059860c73678a202bfa33062723e8f82fb779d9James Dong
1815c059860c73678a202bfa33062723e8f82fb779d9James Dong            if (currDurationTicks != lastDurationTicks) {
18161f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                addOneSttsTableEntry(sampleCount, lastDurationUs);
1817be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                sampleCount = 1;
1818be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            } else {
1819be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                ++sampleCount;
1820be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
1821be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
1822be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        if (mSamplesHaveSameSize) {
1823ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong            if (mNumSamples >= 2 && previousSampleSize != sampleSize) {
1824be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mSamplesHaveSameSize = false;
1825be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
18268644c14618d30d9e57a69df40ed939986ebf02c4James Dong            previousSampleSize = sampleSize;
1827be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
18288644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastDurationUs = timestampUs - lastTimestampUs;
1829c059860c73678a202bfa33062723e8f82fb779d9James Dong        lastDurationTicks = currDurationTicks;
18308644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastTimestampUs = timestampUs;
183120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1832d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        if (isSync != 0) {
18331f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            addOneStssTableEntry(mNumSamples);
1834d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        }
1835d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
183693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (mTrackingProgressStatus) {
183793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            if (mPreviousTrackTimeUs <= 0) {
183893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong                mPreviousTrackTimeUs = mStartTimestampUs;
183993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            }
1840faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong            trackProgressStatus(timestampUs);
184193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
184258ae9c530247668f8af36e30d228c716c226b3d4James Dong        if (mOwner->numTracks() == 1) {
18431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            off_t offset = mIsAvc? mOwner->addLengthPrefixedSample_l(copy)
184458ae9c530247668f8af36e30d228c716c226b3d4James Dong                                 : mOwner->addSample_l(copy);
184558ae9c530247668f8af36e30d228c716c226b3d4James Dong            if (mChunkOffsets.empty()) {
18461f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                addChunkOffset(offset);
184758ae9c530247668f8af36e30d228c716c226b3d4James Dong            }
184858ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy->release();
184958ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy = NULL;
185058ae9c530247668f8af36e30d228c716c226b3d4James Dong            continue;
185158ae9c530247668f8af36e30d228c716c226b3d4James Dong        }
185213aec890216948b0c364f8f92792129d0335f506James Dong
185313aec890216948b0c364f8f92792129d0335f506James Dong        mChunkSamples.push_back(copy);
185413aec890216948b0c364f8f92792129d0335f506James Dong        if (interleaveDurationUs == 0) {
18551f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            addOneStscTableEntry(++nChunks, 1);
18561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            bufferChunk(timestampUs);
185713aec890216948b0c364f8f92792129d0335f506James Dong        } else {
185813aec890216948b0c364f8f92792129d0335f506James Dong            if (chunkTimestampUs == 0) {
185913aec890216948b0c364f8f92792129d0335f506James Dong                chunkTimestampUs = timestampUs;
186013aec890216948b0c364f8f92792129d0335f506James Dong            } else {
186113aec890216948b0c364f8f92792129d0335f506James Dong                if (timestampUs - chunkTimestampUs > interleaveDurationUs) {
186213aec890216948b0c364f8f92792129d0335f506James Dong                    ++nChunks;
186313aec890216948b0c364f8f92792129d0335f506James Dong                    if (nChunks == 1 ||  // First chunk
186413aec890216948b0c364f8f92792129d0335f506James Dong                        (--(mStscTableEntries.end()))->samplesPerChunk !=
186513aec890216948b0c364f8f92792129d0335f506James Dong                         mChunkSamples.size()) {
18661f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                        addOneStscTableEntry(nChunks, mChunkSamples.size());
186713aec890216948b0c364f8f92792129d0335f506James Dong                    }
18681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                    bufferChunk(timestampUs);
186913aec890216948b0c364f8f92792129d0335f506James Dong                    chunkTimestampUs = timestampUs;
187013aec890216948b0c364f8f92792129d0335f506James Dong                }
187113aec890216948b0c364f8f92792129d0335f506James Dong            }
187213aec890216948b0c364f8f92792129d0335f506James Dong        }
187313aec890216948b0c364f8f92792129d0335f506James Dong
187420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
187525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
1876a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong    if (mSampleSizes.empty() ||                      // no samples written
1877a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong        (!mIsAudio && mNumStssTableEntries == 0) ||  // no sync frames for video
1878a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong        (OK != checkCodecSpecificData())) {          // no codec specific data
1879690f546b0ee548dbfe997df36418e5302ec2d786James Dong        err = ERROR_MALFORMED;
1880f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong    }
1881faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    mOwner->trackProgressStatus(this, -1, err);
1882be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
188313aec890216948b0c364f8f92792129d0335f506James Dong    // Last chunk
188458ae9c530247668f8af36e30d228c716c226b3d4James Dong    if (mOwner->numTracks() == 1) {
18851f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        addOneStscTableEntry(1, mNumSamples);
188658ae9c530247668f8af36e30d228c716c226b3d4James Dong    } else if (!mChunkSamples.empty()) {
18871f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        addOneStscTableEntry(++nChunks, mChunkSamples.size());
18881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        bufferChunk(timestampUs);
188913aec890216948b0c364f8f92792129d0335f506James Dong    }
189013aec890216948b0c364f8f92792129d0335f506James Dong
1891be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // We don't really know how long the last frame lasts, since
1892be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // there is no frame time after it, just repeat the previous
1893be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // frame's duration.
1894ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    if (mNumSamples == 1) {
18958f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        lastDurationUs = 0;  // A single sample's duration
1896be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    } else {
1897be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        ++sampleCount;  // Count for the last sample
1898be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    }
18991f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    addOneSttsTableEntry(sampleCount, lastDurationUs);
1900c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs += lastDurationUs;
190125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = true;
19021f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    LOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s",
19031f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            count, nZeroLengthFrames, mNumSamples, mIsAudio? "audio": "video");
1904872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (mIsAudio) {
1905872a481558350634a3fd5cb67939de288af00ecbJames Dong        LOGI("Audio track drift time: %lld us", mOwner->getDriftTimeUs());
1906872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
1907365a963142093a1cd8efdcea76b5f65096a5b115James Dong
190837187916a486504acaf83bea30147eb5fbf46ae5James Dong    if (err == ERROR_END_OF_STREAM) {
190937187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
191037187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
191137187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
1912365a963142093a1cd8efdcea76b5f65096a5b115James Dong}
1913365a963142093a1cd8efdcea76b5f65096a5b115James Dong
1914faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) {
1915faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    LOGV("trackProgressStatus: %lld us", timeUs);
1916215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    if (mTrackEveryTimeDurationUs > 0 &&
1917215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) {
191893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        LOGV("Fire time tracking progress status at %lld us", timeUs);
1919faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        mOwner->trackProgressStatus(this, timeUs - mPreviousTrackTimeUs, err);
192093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        mPreviousTrackTimeUs = timeUs;
192193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
192293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
192393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
1924faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::trackProgressStatus(
1925faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        const MPEG4Writer::Track* track, int64_t timeUs, status_t err) {
1926faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    Mutex::Autolock lock(mLock);
1927faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    int32_t nTracks = mTracks.size();
1928faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    CHECK(nTracks >= 1);
1929faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    CHECK(nTracks < 64);  // Arbitrary number
1930faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
1931faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    int32_t trackNum = 0;
1932faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    CHECK(trackNum < nTracks);
1933faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    trackNum <<= 16;
1934faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
1935faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Error notification
1936faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Do not consider ERROR_END_OF_STREAM an error
1937faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (err != OK && err != ERROR_END_OF_STREAM) {
1938faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        notify(MEDIA_RECORDER_EVENT_ERROR,
1939faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               trackNum | MEDIA_RECORDER_ERROR_UNKNOWN,
1940faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
1941faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        return;
1942faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
1943faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
1944faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (timeUs == -1) {
1945faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send completion notification
1946faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        notify(MEDIA_RECORDER_EVENT_INFO,
1947faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               trackNum | MEDIA_RECORDER_INFO_COMPLETION_STATUS,
1948faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
1949faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        return;
1950faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    } else {
1951faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send progress status
1952faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        notify(MEDIA_RECORDER_EVENT_INFO,
1953faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               trackNum | MEDIA_RECORDER_INFO_PROGRESS_TIME_STATUS,
1954faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               timeUs / 1000);
1955faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
1956faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong}
1957faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
1958d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dongvoid MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) {
1959d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong    LOGV("setDriftTimeUs: %lld us", driftTimeUs);
1960e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
1961d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong    mDriftTimeUs = driftTimeUs;
1962e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
1963e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
1964e259531ce59ab1f31de5a23124b22536f6a5a767James Dongint64_t MPEG4Writer::getDriftTimeUs() {
1965e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    LOGV("getDriftTimeUs: %lld us", mDriftTimeUs);
1966e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
1967e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    return mDriftTimeUs;
1968e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
1969e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
1970b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dongbool MPEG4Writer::useNalLengthFour() {
1971b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    return mUse4ByteNalLength;
1972b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong}
1973b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong
19741c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::Track::bufferChunk(int64_t timestampUs) {
19751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("bufferChunk");
19761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
19771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Chunk chunk(this, timestampUs, mChunkSamples);
19781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mOwner->bufferChunk(chunk);
197913aec890216948b0c364f8f92792129d0335f506James Dong    mChunkSamples.clear();
198020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
198120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
19823b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const {
1983c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    return mTrackDurationUs;
198420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
198520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1986d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const {
1987d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return mEstimatedTrackSizeBytes;
1988d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
1989d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1990690f546b0ee548dbfe997df36418e5302ec2d786James Dongstatus_t MPEG4Writer::Track::checkCodecSpecificData() const {
1991690f546b0ee548dbfe997df36418e5302ec2d786James Dong    const char *mime;
1992690f546b0ee548dbfe997df36418e5302ec2d786James Dong    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
1993690f546b0ee548dbfe997df36418e5302ec2d786James Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) ||
1994690f546b0ee548dbfe997df36418e5302ec2d786James Dong        !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) ||
1995690f546b0ee548dbfe997df36418e5302ec2d786James Dong        !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
1996690f546b0ee548dbfe997df36418e5302ec2d786James Dong        if (!mCodecSpecificData ||
1997690f546b0ee548dbfe997df36418e5302ec2d786James Dong            mCodecSpecificDataSize <= 0) {
1998a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong            LOGE("Missing codec specific data");
1999690f546b0ee548dbfe997df36418e5302ec2d786James Dong            return ERROR_MALFORMED;
2000690f546b0ee548dbfe997df36418e5302ec2d786James Dong        }
2001690f546b0ee548dbfe997df36418e5302ec2d786James Dong    } else {
2002690f546b0ee548dbfe997df36418e5302ec2d786James Dong        if (mCodecSpecificData ||
2003690f546b0ee548dbfe997df36418e5302ec2d786James Dong            mCodecSpecificDataSize > 0) {
2004a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong            LOGE("Unexepected codec specific data found");
2005690f546b0ee548dbfe997df36418e5302ec2d786James Dong            return ERROR_MALFORMED;
2006690f546b0ee548dbfe997df36418e5302ec2d786James Dong        }
2007690f546b0ee548dbfe997df36418e5302ec2d786James Dong    }
2008690f546b0ee548dbfe997df36418e5302ec2d786James Dong    return OK;
2009690f546b0ee548dbfe997df36418e5302ec2d786James Dong}
2010690f546b0ee548dbfe997df36418e5302ec2d786James Dong
20111acfe8649f8169caf2ff098c2dc2de880d9a3760James Dongvoid MPEG4Writer::Track::writeTrackHeader(
20121acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        int32_t trackID, bool use32BitOffset) {
201320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const char *mime;
201420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool success = mMeta->findCString(kKeyMIMEType, &mime);
20150c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(success);
201620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
20178f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    LOGV("%s track time scale: %d",
20181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsAudio? "Audio": "Video", mTimeScale);
20198f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
202020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    time_t now = time(NULL);
20218f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int32_t mvhdTimeScale = mOwner->getTimeScale();
20228f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t trakDurationUs = getDurationUs();
202320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
202420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOwner->beginBox("trak");
202520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
202620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->beginBox("tkhd");
20271acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        // Flags = 7 to indicate that the track is enabled, and
20281acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        // part of the presentation
20291acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        mOwner->writeInt32(0x07);          // version=0, flags=7
203020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(now);           // creation time
203120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(now);           // modification time
203220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(trackID);
203320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);             // reserved
20348f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int32_t tkhdDuration =
20358f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
20368f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        mOwner->writeInt32(tkhdDuration);  // in mvhd timescale
203720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);             // reserved
203820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);             // reserved
203920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt16(0);             // layer
204020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt16(0);             // alternate group
20411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mOwner->writeInt16(mIsAudio ? 0x100 : 0);  // volume
204220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt16(0);             // reserved
204320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
204420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0x10000);       // matrix
204520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
204620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
204720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
204820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0x10000);
204920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
205020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
205120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
205220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0x40000000);
205320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
20541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (mIsAudio) {
205520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);
205620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);
205720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        } else {
205820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            int32_t width, height;
205920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            bool success = mMeta->findInt32(kKeyWidth, &width);
206020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            success = success && mMeta->findInt32(kKeyHeight, &height);
20610c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber            CHECK(success);
206220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2063050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->writeInt32(width << 16);   // 32-bit fixed-point value
2064050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->writeInt32(height << 16);  // 32-bit fixed-point value
206520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
206620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->endBox();  // tkhd
206720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2068f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong      int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
2069f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong      if (mStartTimestampUs != moovStartTimeUs) {
20703c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        mOwner->beginBox("edts");
20713c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong          mOwner->beginBox("elst");
20721acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong            mOwner->writeInt32(0);           // version=0, flags=0: 32-bit time
20731acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong            mOwner->writeInt32(2);           // never ends with an empty list
20748f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
20758f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            // First elst entry: specify the starting time offset
20768f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            int64_t offsetUs = mStartTimestampUs - moovStartTimeUs;
20778428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            LOGV("OffsetUs: %lld", offsetUs);
20788f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            int32_t seg = (offsetUs * mvhdTimeScale + 5E5) / 1E6;
20798f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            mOwner->writeInt32(seg);         // in mvhd timecale
20808f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            mOwner->writeInt32(-1);          // starting time offset
20818f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            mOwner->writeInt32(1 << 16);     // rate = 1.0
20828f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
20838f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            // Second elst entry: specify the track duration
20848f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            seg = (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
20858f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            mOwner->writeInt32(seg);         // in mvhd timescale
20861acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong            mOwner->writeInt32(0);
20871acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong            mOwner->writeInt32(1 << 16);
20883c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong          mOwner->endBox();
20893c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        mOwner->endBox();
20903c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong      }
20913c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
209220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->beginBox("mdia");
209320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
209420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("mdhd");
209520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // version=0, flags=0
209620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(now);           // creation time
209720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(now);           // modification time
20988f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong          mOwner->writeInt32(mTimeScale);    // media timescale
20998f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong          int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6;
21008f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong          mOwner->writeInt32(mdhdDuration);  // use media timescale
21011acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // Language follows the three letter standard ISO-639-2/T
21021acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // 'e', 'n', 'g' for "English", for instance.
21031acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // Each character is packed as the difference between its ASCII value and 0x60.
21041acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // For "English", these are 00101, 01110, 00111.
21051acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // XXX: Where is the padding bit located: 0x15C7?
21061acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          mOwner->writeInt16(0);             // language code
210720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt16(0);             // predefined
210820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->endBox();
210920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
211020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("hdlr");
211120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // version=0, flags=0
2112050b28a593350047845a45a14cc5026221ac1620James Dong          mOwner->writeInt32(0);             // component type: should be mhlr
21131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong          mOwner->writeFourcc(mIsAudio ? "soun" : "vide");  // component subtype
211420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // reserved
211520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // reserved
211620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // reserved
21171acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // Removing "r" for the name string just makes the string 4 byte aligned
21181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong          mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle");  // name
211920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->endBox();
212020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
212120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("minf");
21221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong          if (mIsAudio) {
212320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->beginBox("smhd");
212420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt32(0);           // version=0, flags=0
212520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // balance
212620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // reserved
212720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->endBox();
212820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          } else {
212920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->beginBox("vmhd");
21301acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong              mOwner->writeInt32(0x01);        // version=0, flags=1
213120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // graphics mode
213220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // opcolor
213320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);
213420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);
213520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->endBox();
213620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          }
2137050b28a593350047845a45a14cc5026221ac1620James Dong
2138050b28a593350047845a45a14cc5026221ac1620James Dong          mOwner->beginBox("dinf");
2139050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->beginBox("dref");
2140050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->writeInt32(0);  // version=0, flags=0
21411acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong              mOwner->writeInt32(1);  // entry count (either url or urn)
21421acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong              // The table index here refers to the sample description index
21431acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong              // in the sample table entries.
2144050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->beginBox("url ");
21451acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                mOwner->writeInt32(1);  // version=0, flags=1 (self-contained)
2146050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->endBox();  // url
2147050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->endBox();  // dref
2148050b28a593350047845a45a14cc5026221ac1620James Dong          mOwner->endBox();  // dinf
2149050b28a593350047845a45a14cc5026221ac1620James Dong
215020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("stbl");
215120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
215220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stsd");
215320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);               // version=0, flags=0
215420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(1);               // entry count
21551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (mIsAudio) {
215625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                const char *fourcc = NULL;
215718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) {
215825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    fourcc = "samr";
215918291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
216025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    fourcc = "sawb";
2161050b28a593350047845a45a14cc5026221ac1620James Dong                } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
2162050b28a593350047845a45a14cc5026221ac1620James Dong                    fourcc = "mp4a";
216325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                } else {
216425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    LOGE("Unknown mime type '%s'.", mime);
216525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    CHECK(!"should not be here, unknown mime type.");
216625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                }
216725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
216825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                mOwner->beginBox(fourcc);          // audio format
216920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
217020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
2171050b28a593350047845a45a14cc5026221ac1620James Dong                  mOwner->writeInt16(0x1);         // data ref index
217220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
217320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
2174050b28a593350047845a45a14cc5026221ac1620James Dong                  int32_t nChannels;
2175050b28a593350047845a45a14cc5026221ac1620James Dong                  CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels));
2176050b28a593350047845a45a14cc5026221ac1620James Dong                  mOwner->writeInt16(nChannels);   // channel count
217720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(16);          // sample size
217820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // predefined
217920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
218020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
218120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  int32_t samplerate;
218220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  bool success = mMeta->findInt32(kKeySampleRate, &samplerate);
21830c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                  CHECK(success);
218420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(samplerate << 16);
2185050b28a593350047845a45a14cc5026221ac1620James Dong                  if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
2186050b28a593350047845a45a14cc5026221ac1620James Dong                    mOwner->beginBox("esds");
218751dfe6d646ddcc5fc252aa4c19c9936d32af8ad7James Dong                        CHECK(mCodecSpecificData);
218851dfe6d646ddcc5fc252aa4c19c9936d32af8ad7James Dong                        CHECK(mCodecSpecificDataSize > 0);
2189050b28a593350047845a45a14cc5026221ac1620James Dong
2190050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt32(0);     // version=0, flags=0
2191050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x03);   // ES_DescrTag
2192050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(23 + mCodecSpecificDataSize);
2193050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt16(0x0000);// ES_ID
2194050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x00);
2195050b28a593350047845a45a14cc5026221ac1620James Dong
2196050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x04);   // DecoderConfigDescrTag
2197050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(15 + mCodecSpecificDataSize);
2198050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x40);   // objectTypeIndication ISO/IEC 14492-2
2199050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x15);   // streamType AudioStream
2200050b28a593350047845a45a14cc5026221ac1620James Dong
2201050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt16(0x03);  // XXX
2202050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x00);   // buffer size 24-bit
2203050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt32(96000); // max bit rate
2204050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt32(96000); // avg bit rate
2205050b28a593350047845a45a14cc5026221ac1620James Dong
2206050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x05);   // DecoderSpecificInfoTag
2207050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(mCodecSpecificDataSize);
2208050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
2209050b28a593350047845a45a14cc5026221ac1620James Dong
2210050b28a593350047845a45a14cc5026221ac1620James Dong                        static const uint8_t kData2[] = {
2211050b28a593350047845a45a14cc5026221ac1620James Dong                            0x06,  // SLConfigDescriptorTag
2212050b28a593350047845a45a14cc5026221ac1620James Dong                            0x01,
2213050b28a593350047845a45a14cc5026221ac1620James Dong                            0x02
2214050b28a593350047845a45a14cc5026221ac1620James Dong                        };
2215050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->write(kData2, sizeof(kData2));
2216050b28a593350047845a45a14cc5026221ac1620James Dong
2217050b28a593350047845a45a14cc5026221ac1620James Dong                    mOwner->endBox();  // esds
22185aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                  } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) ||
22195aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                             !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
22205aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                    // 3gpp2 Spec AMRSampleEntry fields
22215aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                    mOwner->beginBox("damr");
22225aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                      mOwner->writeCString("   ");  // vendor: 4 bytes
22235aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                      mOwner->writeInt8(0);         // decoder version
22245aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                      mOwner->writeInt16(0x83FF);   // mode set: all enabled
22255aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                      mOwner->writeInt8(0);         // mode change period
22265aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                      mOwner->writeInt8(1);         // frames per sample
22275aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                    mOwner->endBox();
2228050b28a593350047845a45a14cc5026221ac1620James Dong                  }
222920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mOwner->endBox();
223020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
223118291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
223220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    mOwner->beginBox("mp4v");
223318291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
223420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    mOwner->beginBox("s263");
223530ab66297501757d745b9ae10da61adcd891f497Andreas Huber                } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
223630ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    mOwner->beginBox("avc1");
223720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                } else {
223825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    LOGE("Unknown mime type '%s'.", mime);
22390c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                    CHECK(!"should not be here, unknown mime type.");
224020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
224120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
224220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
224320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
22441acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                  mOwner->writeInt16(1);           // data ref index
224520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // predefined
224620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
224720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // predefined
224820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // predefined
224920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // predefined
225020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
225120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  int32_t width, height;
225220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  bool success = mMeta->findInt32(kKeyWidth, &width);
225320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  success = success && mMeta->findInt32(kKeyHeight, &height);
22540c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                  CHECK(success);
225520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
225620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(width);
225720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(height);
225820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0x480000);    // horiz resolution
225920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0x480000);    // vert resolution
226020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
226120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(1);           // frame count
226220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->write("                                ", 32);
226320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0x18);        // depth
226420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(-1);          // predefined
226520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
22660c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                  CHECK(23 + mCodecSpecificDataSize < 128);
226720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
226818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                  if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
2269a37923e9a57d489e7bed2129369219039fa5f12cJames Dong                      CHECK(mCodecSpecificData);
2270a37923e9a57d489e7bed2129369219039fa5f12cJames Dong                      CHECK(mCodecSpecificDataSize > 0);
227120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->beginBox("esds");
227220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
227320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt32(0);           // version=0, flags=0
227420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
227520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x03);  // ES_DescrTag
227620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(23 + mCodecSpecificDataSize);
227720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt16(0x0000);  // ES_ID
227820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x1f);
227920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
228020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x04);  // DecoderConfigDescrTag
228120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(15 + mCodecSpecificDataSize);
228220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x20);  // objectTypeIndication ISO/IEC 14492-2
228320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x11);  // streamType VisualStream
228420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
228520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        static const uint8_t kData[] = {
228620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x01, 0x77, 0x00,
228720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x00, 0x03, 0xe8, 0x00,
228820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x00, 0x03, 0xe8, 0x00
228920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        };
229020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->write(kData, sizeof(kData));
2291050b28a593350047845a45a14cc5026221ac1620James Dong
229220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x05);  // DecoderSpecificInfoTag
229320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
229420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(mCodecSpecificDataSize);
229520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
229620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
229720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        static const uint8_t kData2[] = {
229820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x06,  // SLConfigDescriptorTag
229920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x01,
230020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x02
230120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        };
230220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->write(kData2, sizeof(kData2));
230320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
230420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->endBox();  // esds
230518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                  } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
230620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->beginBox("d263");
230720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
230820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt32(0);  // vendor
230920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt8(0);   // decoder version
231020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt8(10);  // level: 10
231120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt8(0);   // profile: 0
231220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
231320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->endBox();  // d263
231430ab66297501757d745b9ae10da61adcd891f497Andreas Huber                  } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
231551dfe6d646ddcc5fc252aa4c19c9936d32af8ad7James Dong                      CHECK(mCodecSpecificData);
231695fcef25b48e35b625899288971ab628efbf8584Andreas Huber                      CHECK(mCodecSpecificDataSize >= 5);
231795fcef25b48e35b625899288971ab628efbf8584Andreas Huber
231895fcef25b48e35b625899288971ab628efbf8584Andreas Huber                      // Patch avcc's lengthSize field to match the number
231995fcef25b48e35b625899288971ab628efbf8584Andreas Huber                      // of bytes we use to indicate the size of a nal unit.
232095fcef25b48e35b625899288971ab628efbf8584Andreas Huber                      uint8_t *ptr = (uint8_t *)mCodecSpecificData;
232195fcef25b48e35b625899288971ab628efbf8584Andreas Huber                      ptr[4] =
232295fcef25b48e35b625899288971ab628efbf8584Andreas Huber                          (ptr[4] & 0xfc)
232395fcef25b48e35b625899288971ab628efbf8584Andreas Huber                            | (mOwner->useNalLengthFour() ? 3 : 1);
232495fcef25b48e35b625899288971ab628efbf8584Andreas Huber
232530ab66297501757d745b9ae10da61adcd891f497Andreas Huber                      mOwner->beginBox("avcC");
232630ab66297501757d745b9ae10da61adcd891f497Andreas Huber                        mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
232730ab66297501757d745b9ae10da61adcd891f497Andreas Huber                      mOwner->endBox();  // avcC
232820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  }
232930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
23301acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                  mOwner->beginBox("pasp");
23311acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                    // This is useful if the pixel is not square
23321acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                    mOwner->writeInt32(1 << 16);  // hspacing
23331acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                    mOwner->writeInt32(1 << 16);  // vspacing
23341acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                  mOwner->endBox();  // pasp
233530ab66297501757d745b9ae10da61adcd891f497Andreas Huber                mOwner->endBox();  // mp4v, s263 or avc1
233620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
233720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stsd
233820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
233920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stts");
234020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
23411f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            mOwner->writeInt32(mNumSttsTableEntries);
2342c059860c73678a202bfa33062723e8f82fb779d9James Dong            int64_t prevTimestampUs = 0;
2343be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin();
2344be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                 it != mSttsTableEntries.end(); ++it) {
2345be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mOwner->writeInt32(it->sampleCount);
2346c059860c73678a202bfa33062723e8f82fb779d9James Dong
2347c059860c73678a202bfa33062723e8f82fb779d9James Dong                // Make sure that we are calculating the sample duration the exactly
2348c059860c73678a202bfa33062723e8f82fb779d9James Dong                // same way as we made decision on how to create stts entries.
2349c059860c73678a202bfa33062723e8f82fb779d9James Dong                int64_t currTimestampUs = prevTimestampUs + it->sampleDurationUs;
2350c059860c73678a202bfa33062723e8f82fb779d9James Dong                int32_t dur = ((currTimestampUs * mTimeScale + 500000LL) / 1000000LL -
2351c059860c73678a202bfa33062723e8f82fb779d9James Dong                               (prevTimestampUs * mTimeScale + 500000LL) / 1000000LL);
2352c059860c73678a202bfa33062723e8f82fb779d9James Dong                prevTimestampUs += (it->sampleCount * it->sampleDurationUs);
2353c059860c73678a202bfa33062723e8f82fb779d9James Dong
23548f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong                mOwner->writeInt32(dur);
235520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
235620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stts
235720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
23581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong          if (!mIsAudio) {
2359050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->beginBox("stss");
2360050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->writeInt32(0);  // version=0, flags=0
23611f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong              mOwner->writeInt32(mNumStssTableEntries);  // number of sync frames
2362050b28a593350047845a45a14cc5026221ac1620James Dong              for (List<int32_t>::iterator it = mStssTableEntries.begin();
2363050b28a593350047845a45a14cc5026221ac1620James Dong                   it != mStssTableEntries.end(); ++it) {
2364050b28a593350047845a45a14cc5026221ac1620James Dong                  mOwner->writeInt32(*it);
2365050b28a593350047845a45a14cc5026221ac1620James Dong              }
2366050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->endBox();  // stss
2367050b28a593350047845a45a14cc5026221ac1620James Dong          }
2368050b28a593350047845a45a14cc5026221ac1620James Dong
236920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stsz");
237020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
2371be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            if (mSamplesHaveSameSize) {
23728644c14618d30d9e57a69df40ed939986ebf02c4James Dong                List<size_t>::iterator it = mSampleSizes.begin();
23738644c14618d30d9e57a69df40ed939986ebf02c4James Dong                mOwner->writeInt32(*it);  // default sample size
2374be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            } else {
2375be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mOwner->writeInt32(0);
2376be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
2377ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong            mOwner->writeInt32(mNumSamples);
2378be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            if (!mSamplesHaveSameSize) {
23798644c14618d30d9e57a69df40ed939986ebf02c4James Dong                for (List<size_t>::iterator it = mSampleSizes.begin();
23808644c14618d30d9e57a69df40ed939986ebf02c4James Dong                     it != mSampleSizes.end(); ++it) {
23818644c14618d30d9e57a69df40ed939986ebf02c4James Dong                    mOwner->writeInt32(*it);
2382be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                }
238320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
238420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stsz
238520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
238620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stsc");
238720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
23881f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            mOwner->writeInt32(mNumStscTableEntries);
238913aec890216948b0c364f8f92792129d0335f506James Dong            for (List<StscTableEntry>::iterator it = mStscTableEntries.begin();
239013aec890216948b0c364f8f92792129d0335f506James Dong                 it != mStscTableEntries.end(); ++it) {
239113aec890216948b0c364f8f92792129d0335f506James Dong                mOwner->writeInt32(it->firstChunk);
239213aec890216948b0c364f8f92792129d0335f506James Dong                mOwner->writeInt32(it->samplesPerChunk);
239313aec890216948b0c364f8f92792129d0335f506James Dong                mOwner->writeInt32(it->sampleDescriptionId);
239420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
239520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stsc
23961acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          mOwner->beginBox(use32BitOffset? "stco": "co64");
239720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
23981f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            mOwner->writeInt32(mNumStcoTableEntries);
239913aec890216948b0c364f8f92792129d0335f506James Dong            for (List<off_t>::iterator it = mChunkOffsets.begin();
240013aec890216948b0c364f8f92792129d0335f506James Dong                 it != mChunkOffsets.end(); ++it) {
24011acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                if (use32BitOffset) {
24021acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                    mOwner->writeInt32(static_cast<int32_t>(*it));
24031acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                } else {
24041acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                    mOwner->writeInt64((*it));
24051acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                }
240620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
24078f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong          mOwner->endBox();  // stco or co64
240820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
240920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->endBox();  // stbl
24101acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong       mOwner->endBox();  // minf
241120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->endBox();  // mdia
241220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOwner->endBox();  // trak
241320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
241420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
241520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
2416