MPEG4Writer.cpp revision 985f838934510983d8a887461e98dca60a6e858f
120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber/*
220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Copyright (C) 2009 The Android Open Source Project
320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * you may not use this file except in compliance with the License.
620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * You may obtain a copy of the License at
720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
1020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Unless required by applicable law or agreed to in writing, software
1120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
1220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * See the License for the specific language governing permissions and
1420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * limitations under the License.
1520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber */
1620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
17050b28a593350047845a45a14cc5026221ac1620James Dong//#define LOG_NDEBUG 0
18050b28a593350047845a45a14cc5026221ac1620James Dong#define LOG_TAG "MPEG4Writer"
19050b28a593350047845a45a14cc5026221ac1620James Dong#include <utils/Log.h>
20050b28a593350047845a45a14cc5026221ac1620James Dong
2120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <arpa/inet.h>
2220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <pthread.h>
24a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong#include <sys/prctl.h>
25a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong#include <sys/resource.h>
2620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MPEG4Writer.h>
2820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBuffer.h>
2920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h>
300c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber#include <media/stagefright/MediaDebug.h>
3118291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h>
3203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#include <media/stagefright/MediaErrors.h>
3320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaSource.h>
3420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/Utils.h>
35d599cd4573b5a2d5914c5040e0565ef866749b77James Dong#include <media/mediarecorder.h>
36674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong#include <sys/types.h>
37674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong#include <sys/stat.h>
38674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong#include <fcntl.h>
39674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong#include <unistd.h>
4020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber#include "include/ESDS.h"
4219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
4320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android {
4420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
451f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongstatic const int64_t kMax32BitFileSize = 0x007fffffffLL;
463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypeSeqParamSet = 0x07;
473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypePicParamSet = 0x08;
485b6a01e65aa4129a9226667536d1bc1dad5980d8James Dong
495b6a01e65aa4129a9226667536d1bc1dad5980d8James Dong// Using longer adjustment period to suppress fluctuations in
505b6a01e65aa4129a9226667536d1bc1dad5980d8James Dong// the audio encoding paths
515b6a01e65aa4129a9226667536d1bc1dad5980d8James Dongstatic const int64_t kVideoMediaTimeAdjustPeriodTimeUs = 600000000LL;  // 10 minutes
523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
5320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Writer::Track {
5420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic:
5525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    Track(MPEG4Writer *owner, const sp<MediaSource> &source);
568f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
5720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    ~Track();
5820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t start(MetaData *params);
6037187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t stop();
6137187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t pause();
6225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool reachedEOS();
6320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
643b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber    int64_t getDurationUs() const;
65d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t getEstimatedTrackSizeBytes() const;
661acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    void writeTrackHeader(int32_t trackID, bool use32BitOffset = true);
671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void bufferChunk(int64_t timestampUs);
681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isAvc() const { return mIsAvc; }
691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isAudio() const { return mIsAudio; }
701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isMPEG4() const { return mIsMPEG4; }
71c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    void addChunkOffset(off64_t offset);
72dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    status_t dump(int fd, const Vector<String16>& args) const;
7320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate:
7520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Writer *mOwner;
7620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MetaData> mMeta;
77693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    sp<MediaSource> mSource;
7820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    volatile bool mDone;
79a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mPaused;
80a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mResumed;
811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAvc;
821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAudio;
831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsMPEG4;
84c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    int64_t mTrackDurationUs;
85e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
86e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    // For realtime applications, we need to adjust the media clock
87e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    // for video track based on the audio media clock
88e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    bool mIsRealTimeRecording;
89e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    int64_t mMaxTimeStampUs;
90d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t mEstimatedTrackSizeBytes;
911f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    int64_t mMdatSizeBytes;
928f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int32_t mTimeScale;
9320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_t mThread;
9520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
96ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    // mNumSamples is used to track how many samples in mSampleSizes List.
97ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    // This is to reduce the cost associated with mSampleSizes.size() call,
98ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    // since it is O(n). Ideally, the fix should be in List class.
99ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    size_t              mNumSamples;
1008644c14618d30d9e57a69df40ed939986ebf02c4James Dong    List<size_t>        mSampleSizes;
101be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    bool                mSamplesHaveSameSize;
102be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
10313aec890216948b0c364f8f92792129d0335f506James Dong    List<MediaBuffer *> mChunkSamples;
1041f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1051f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    size_t              mNumStcoTableEntries;
106c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    List<off64_t>         mChunkOffsets;
10713aec890216948b0c364f8f92792129d0335f506James Dong
1081f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    size_t              mNumStscTableEntries;
10913aec890216948b0c364f8f92792129d0335f506James Dong    struct StscTableEntry {
11013aec890216948b0c364f8f92792129d0335f506James Dong
11113aec890216948b0c364f8f92792129d0335f506James Dong        StscTableEntry(uint32_t chunk, uint32_t samples, uint32_t id)
11213aec890216948b0c364f8f92792129d0335f506James Dong            : firstChunk(chunk),
11313aec890216948b0c364f8f92792129d0335f506James Dong              samplesPerChunk(samples),
11413aec890216948b0c364f8f92792129d0335f506James Dong              sampleDescriptionId(id) {}
11513aec890216948b0c364f8f92792129d0335f506James Dong
11613aec890216948b0c364f8f92792129d0335f506James Dong        uint32_t firstChunk;
11713aec890216948b0c364f8f92792129d0335f506James Dong        uint32_t samplesPerChunk;
11813aec890216948b0c364f8f92792129d0335f506James Dong        uint32_t sampleDescriptionId;
11913aec890216948b0c364f8f92792129d0335f506James Dong    };
12013aec890216948b0c364f8f92792129d0335f506James Dong    List<StscTableEntry> mStscTableEntries;
12120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1221f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    size_t        mNumStssTableEntries;
123050b28a593350047845a45a14cc5026221ac1620James Dong    List<int32_t> mStssTableEntries;
124050b28a593350047845a45a14cc5026221ac1620James Dong
1251f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    size_t        mNumSttsTableEntries;
126be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    struct SttsTableEntry {
127be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
1288f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        SttsTableEntry(uint32_t count, uint32_t durationUs)
1298f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            : sampleCount(count), sampleDurationUs(durationUs) {}
130be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
131be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        uint32_t sampleCount;
1328f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        uint32_t sampleDurationUs;
133be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    };
134be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    List<SttsTableEntry> mSttsTableEntries;
135be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
1363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Sequence parameter set or picture parameter set
1373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    struct AVCParamSet {
1383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        AVCParamSet(uint16_t length, const uint8_t *data)
1393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            : mLength(length), mData(data) {}
1403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
1413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t mLength;
1423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *mData;
1433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    };
1443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    List<AVCParamSet> mSeqParamSets;
1453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    List<AVCParamSet> mPicParamSets;
1463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mProfileIdc;
1473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mProfileCompatible;
1483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mLevelIdc;
1493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
15020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *mCodecSpecificData;
15120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t mCodecSpecificDataSize;
152548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    bool mGotAllCodecSpecificData;
15393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    bool mTrackingProgressStatus;
15420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
15525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool mReachedEOS;
1563c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    int64_t mStartTimestampUs;
15793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mPreviousTrackTimeUs;
15893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mTrackEveryTimeDurationUs;
15925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
160872a481558350634a3fd5cb67939de288af00ecbJames Dong    // Has the media time adjustment for video started?
161872a481558350634a3fd5cb67939de288af00ecbJames Dong    bool    mIsMediaTimeAdjustmentOn;
162872a481558350634a3fd5cb67939de288af00ecbJames Dong    // The time stamp when previous media time adjustment period starts
163872a481558350634a3fd5cb67939de288af00ecbJames Dong    int64_t mPrevMediaTimeAdjustTimestampUs;
164872a481558350634a3fd5cb67939de288af00ecbJames Dong    // Number of vidoe frames whose time stamp may be adjusted
165872a481558350634a3fd5cb67939de288af00ecbJames Dong    int64_t mMediaTimeAdjustNumFrames;
166872a481558350634a3fd5cb67939de288af00ecbJames Dong    // The sample number when previous meida time adjustmnet period starts
167872a481558350634a3fd5cb67939de288af00ecbJames Dong    int64_t mPrevMediaTimeAdjustSample;
168872a481558350634a3fd5cb67939de288af00ecbJames Dong    // The total accumulated drift time within a period of
169872a481558350634a3fd5cb67939de288af00ecbJames Dong    // kVideoMediaTimeAdjustPeriodTimeUs.
170872a481558350634a3fd5cb67939de288af00ecbJames Dong    int64_t mTotalDriftTimeToAdjustUs;
171872a481558350634a3fd5cb67939de288af00ecbJames Dong    // The total accumalated drift time since the start of the recording
172872a481558350634a3fd5cb67939de288af00ecbJames Dong    // excluding the current time adjustment period
173872a481558350634a3fd5cb67939de288af00ecbJames Dong    int64_t mPrevTotalAccumDriftTimeUs;
174872a481558350634a3fd5cb67939de288af00ecbJames Dong
175872a481558350634a3fd5cb67939de288af00ecbJames Dong    // Update the audio track's drift information.
176872a481558350634a3fd5cb67939de288af00ecbJames Dong    void updateDriftTime(const sp<MetaData>& meta);
177872a481558350634a3fd5cb67939de288af00ecbJames Dong
178872a481558350634a3fd5cb67939de288af00ecbJames Dong    // Adjust the time stamp of the video track according to
179872a481558350634a3fd5cb67939de288af00ecbJames Dong    // the drift time information from the audio track.
180872a481558350634a3fd5cb67939de288af00ecbJames Dong    void adjustMediaTime(int64_t *timestampUs);
181872a481558350634a3fd5cb67939de288af00ecbJames Dong
18220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    static void *ThreadWrapper(void *me);
18337187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t threadEntry();
18420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *parseParamSet(
1863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen);
1873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
18803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    status_t makeAVCCodecSpecificData(
18903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            const uint8_t *data, size_t size);
1903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    status_t copyAVCCodecSpecificData(
1913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            const uint8_t *data, size_t size);
1923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    status_t parseAVCCodecSpecificData(
1933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            const uint8_t *data, size_t size);
194215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong
195215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    // Track authoring progress status
196faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    void trackProgressStatus(int64_t timeUs, status_t err = OK);
19793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    void initTrackingProgressStatus(MetaData *params);
19803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
19919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    void getCodecSpecificDataFromInputFormatIfPossible();
20019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
201c059860c73678a202bfa33062723e8f82fb779d9James Dong    // Determine the track time scale
202c059860c73678a202bfa33062723e8f82fb779d9James Dong    // If it is an audio track, try to use the sampling rate as
203c059860c73678a202bfa33062723e8f82fb779d9James Dong    // the time scale; however, if user chooses the overwrite
204c059860c73678a202bfa33062723e8f82fb779d9James Dong    // value, the user-supplied time scale will be used.
205c059860c73678a202bfa33062723e8f82fb779d9James Dong    void setTimeScale();
206c059860c73678a202bfa33062723e8f82fb779d9James Dong
207690f546b0ee548dbfe997df36418e5302ec2d786James Dong    // Simple validation on the codec specific data
208690f546b0ee548dbfe997df36418e5302ec2d786James Dong    status_t checkCodecSpecificData() const;
20913f6284305e4b27395a23db7882d670bdb1bcae1James Dong    int32_t mRotation;
210690f546b0ee548dbfe997df36418e5302ec2d786James Dong
2111f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void updateTrackSizeEstimate();
2121f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void addOneStscTableEntry(size_t chunkId, size_t sampleId);
2131f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void addOneStssTableEntry(size_t sampleId);
2141f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void addOneSttsTableEntry(size_t sampleCount, int64_t durationUs);
2151f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
21620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track(const Track &);
21720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track &operator=(const Track &);
21820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
21920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
22020111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::MPEG4Writer(const char *filename)
221674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    : mFd(-1),
222674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong      mInitCheck(NO_INIT),
223b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong      mUse4ByteNalLength(true),
2241acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong      mUse32BitOffset(true),
225a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong      mIsFileSizeLimitExplicitlyRequested(false),
226a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
227a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mStarted(false),
22820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOffset(0),
22913aec890216948b0c364f8f92792129d0335f506James Dong      mMdatOffset(0),
2307837c17063a4c50bc856ba59418516fdab731de7James Dong      mEstimatedMoovBoxSize(0),
231f01528f435e6b1f02d118fcd8305a148c27a89f1James Dong      mInterleaveDurationUs(1000000) {
232674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong
233674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    mFd = open(filename, O_CREAT | O_LARGEFILE | O_TRUNC);
234674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mFd >= 0) {
235674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        mInitCheck = OK;
236674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    }
23720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
23820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
23930ab66297501757d745b9ae10da61adcd891f497Andreas HuberMPEG4Writer::MPEG4Writer(int fd)
240674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    : mFd(dup(fd)),
241674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong      mInitCheck(mFd < 0? NO_INIT: OK),
242b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong      mUse4ByteNalLength(true),
2431acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong      mUse32BitOffset(true),
244a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong      mIsFileSizeLimitExplicitlyRequested(false),
245a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
246a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mStarted(false),
24730ab66297501757d745b9ae10da61adcd891f497Andreas Huber      mOffset(0),
24813aec890216948b0c364f8f92792129d0335f506James Dong      mMdatOffset(0),
2497837c17063a4c50bc856ba59418516fdab731de7James Dong      mEstimatedMoovBoxSize(0),
250f01528f435e6b1f02d118fcd8305a148c27a89f1James Dong      mInterleaveDurationUs(1000000) {
25130ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
25230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
25320111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() {
25420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    stop();
25520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2561f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    while (!mTracks.empty()) {
2571f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        List<Track *>::iterator it = mTracks.begin();
25820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        delete *it;
2591f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        (*it) = NULL;
2601f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mTracks.erase(it);
26120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
26220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.clear();
26320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
26420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
265dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::dump(
266dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        int fd, const Vector<String16>& args) {
267dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    const size_t SIZE = 256;
268dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    char buffer[SIZE];
269dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    String8 result;
270dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "   MPEG4Writer %p\n", this);
271dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
272dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "     mStarted: %s\n", mStarted? "true": "false");
273dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
274dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    ::write(fd, result.string(), result.size());
275dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    for (List<Track *>::iterator it = mTracks.begin();
276dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong         it != mTracks.end(); ++it) {
277dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        (*it)->dump(fd, args);
278dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    }
279dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    return OK;
280dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong}
281dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong
282dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::Track::dump(
283dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        int fd, const Vector<String16>& args) const {
284dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    const size_t SIZE = 256;
285dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    char buffer[SIZE];
286dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    String8 result;
287dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "     %s track\n", mIsAudio? "Audio": "Video");
288dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
289dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "       reached EOS: %s\n",
290dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong            mReachedEOS? "true": "false");
291dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
292dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    ::write(fd, result.string(), result.size());
293dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    return OK;
294dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong}
295dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong
2962dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huberstatus_t MPEG4Writer::addSource(const sp<MediaSource> &source) {
29725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    Track *track = new Track(this, source);
29820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.push_back(track);
2992dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
3002dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    return OK;
30120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
30220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
30393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::startTracks(MetaData *params) {
304a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
305a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
30693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        status_t err = (*it)->start(params);
307a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
308a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (err != OK) {
309a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            for (List<Track *>::iterator it2 = mTracks.begin();
310a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                 it2 != it; ++it2) {
311a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                (*it2)->stop();
312a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            }
313a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
314a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            return err;
315a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
316a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
317a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    return OK;
318a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
319a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
3202dec2b5be2056c6d9428897dc672185872d30d17James Dongint64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) {
3212dec2b5be2056c6d9428897dc672185872d30d17James Dong    // This implementation is highly experimental/heurisitic.
3222dec2b5be2056c6d9428897dc672185872d30d17James Dong    //
3232dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Statistical analysis shows that metadata usually accounts
3242dec2b5be2056c6d9428897dc672185872d30d17James Dong    // for a small portion of the total file size, usually < 0.6%.
3252dec2b5be2056c6d9428897dc672185872d30d17James Dong
32678a1a286f736888ae7af8860b2c424af0d978848James Dong    // The default MIN_MOOV_BOX_SIZE is set to 0.6% x 1MB / 2,
3272dec2b5be2056c6d9428897dc672185872d30d17James Dong    // where 1MB is the common file size limit for MMS application.
32878a1a286f736888ae7af8860b2c424af0d978848James Dong    // The default MAX _MOOV_BOX_SIZE value is based on about 3
3292dec2b5be2056c6d9428897dc672185872d30d17James Dong    // minute video recording with a bit rate about 3 Mbps, because
3302dec2b5be2056c6d9428897dc672185872d30d17James Dong    // statistics also show that most of the video captured are going
3312dec2b5be2056c6d9428897dc672185872d30d17James Dong    // to be less than 3 minutes.
3322dec2b5be2056c6d9428897dc672185872d30d17James Dong
3332dec2b5be2056c6d9428897dc672185872d30d17James Dong    // If the estimation is wrong, we will pay the price of wasting
3342dec2b5be2056c6d9428897dc672185872d30d17James Dong    // some reserved space. This should not happen so often statistically.
3352dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int32_t factor = mUse32BitOffset? 1: 2;
33678a1a286f736888ae7af8860b2c424af0d978848James Dong    static const int64_t MIN_MOOV_BOX_SIZE = 3 * 1024;  // 3 KB
3372dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000);
3382dec2b5be2056c6d9428897dc672185872d30d17James Dong    int64_t size = MIN_MOOV_BOX_SIZE;
3392dec2b5be2056c6d9428897dc672185872d30d17James Dong
34078a1a286f736888ae7af8860b2c424af0d978848James Dong    // Max file size limit is set
341a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
34278a1a286f736888ae7af8860b2c424af0d978848James Dong        size = mMaxFileSizeLimitBytes * 6 / 1000;
34378a1a286f736888ae7af8860b2c424af0d978848James Dong    }
34478a1a286f736888ae7af8860b2c424af0d978848James Dong
34578a1a286f736888ae7af8860b2c424af0d978848James Dong    // Max file duration limit is set
34678a1a286f736888ae7af8860b2c424af0d978848James Dong    if (mMaxFileDurationLimitUs != 0) {
34778a1a286f736888ae7af8860b2c424af0d978848James Dong        if (bitRate > 0) {
34878a1a286f736888ae7af8860b2c424af0d978848James Dong            int64_t size2 =
34978a1a286f736888ae7af8860b2c424af0d978848James Dong                ((mMaxFileDurationLimitUs * bitRate * 6) / 1000 / 8000000);
35078a1a286f736888ae7af8860b2c424af0d978848James Dong            if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
35178a1a286f736888ae7af8860b2c424af0d978848James Dong                // When both file size and duration limits are set,
35278a1a286f736888ae7af8860b2c424af0d978848James Dong                // we use the smaller limit of the two.
35378a1a286f736888ae7af8860b2c424af0d978848James Dong                if (size > size2) {
35478a1a286f736888ae7af8860b2c424af0d978848James Dong                    size = size2;
35578a1a286f736888ae7af8860b2c424af0d978848James Dong                }
35678a1a286f736888ae7af8860b2c424af0d978848James Dong            } else {
35778a1a286f736888ae7af8860b2c424af0d978848James Dong                // Only max file duration limit is set
35878a1a286f736888ae7af8860b2c424af0d978848James Dong                size = size2;
35978a1a286f736888ae7af8860b2c424af0d978848James Dong            }
3602dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
3612dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
36278a1a286f736888ae7af8860b2c424af0d978848James Dong
3632dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size < MIN_MOOV_BOX_SIZE) {
3642dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MIN_MOOV_BOX_SIZE;
3652dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
3662dec2b5be2056c6d9428897dc672185872d30d17James Dong
3672dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Any long duration recording will be probably end up with
3682dec2b5be2056c6d9428897dc672185872d30d17James Dong    // non-streamable mp4 file.
3692dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size > MAX_MOOV_BOX_SIZE) {
3702dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MAX_MOOV_BOX_SIZE;
3712dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
3722dec2b5be2056c6d9428897dc672185872d30d17James Dong
373a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    LOGI("limits: %lld/%lld bytes/us, bit rate: %d bps and the estimated"
3742dec2b5be2056c6d9428897dc672185872d30d17James Dong         " moov size %lld bytes",
3752dec2b5be2056c6d9428897dc672185872d30d17James Dong         mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size);
3762dec2b5be2056c6d9428897dc672185872d30d17James Dong    return factor * size;
3772dec2b5be2056c6d9428897dc672185872d30d17James Dong}
3782dec2b5be2056c6d9428897dc672185872d30d17James Dong
3792dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t MPEG4Writer::start(MetaData *param) {
380674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
38125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return UNKNOWN_ERROR;
38220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
38320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
384a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    /*
385a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * Check mMaxFileSizeLimitBytes at the beginning
386a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * since mMaxFileSizeLimitBytes may be implicitly
387a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * changed later for 32-bit file offset even if
388a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * user does not ask to set it explicitly.
389a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     */
390a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    if (mMaxFileSizeLimitBytes != 0) {
391a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong        mIsFileSizeLimitExplicitlyRequested = true;
392a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    }
393a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong
3942dec2b5be2056c6d9428897dc672185872d30d17James Dong    int32_t use64BitOffset;
3952dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (param &&
3962dec2b5be2056c6d9428897dc672185872d30d17James Dong        param->findInt32(kKey64BitFileOffset, &use64BitOffset) &&
3972dec2b5be2056c6d9428897dc672185872d30d17James Dong        use64BitOffset) {
3982dec2b5be2056c6d9428897dc672185872d30d17James Dong        mUse32BitOffset = false;
3992dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
4002dec2b5be2056c6d9428897dc672185872d30d17James Dong
4011f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    if (mUse32BitOffset) {
4021f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // Implicit 32 bit file size limit
4031f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        if (mMaxFileSizeLimitBytes == 0) {
4041f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            mMaxFileSizeLimitBytes = kMax32BitFileSize;
4051f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        }
4061f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
4071f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // If file size is set to be larger than the 32 bit file
4081f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // size limit, treat it as an error.
4091f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        if (mMaxFileSizeLimitBytes > kMax32BitFileSize) {
410872a481558350634a3fd5cb67939de288af00ecbJames Dong            LOGW("32-bit file size limit (%lld bytes) too big. "
411d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong                 "It is changed to %lld bytes",
412d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong                mMaxFileSizeLimitBytes, kMax32BitFileSize);
413d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong            mMaxFileSizeLimitBytes = kMax32BitFileSize;
4141f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        }
4151f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    }
4161f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
417b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    int32_t use2ByteNalLength;
418b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (param &&
419b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        param->findInt32(kKey2ByteNalLength, &use2ByteNalLength) &&
420b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        use2ByteNalLength) {
421b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mUse4ByteNalLength = false;
4222dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
4232dec2b5be2056c6d9428897dc672185872d30d17James Dong
424065d1aff96818df54456053f1574aec8a234d0deJames Dong    mStartTimestampUs = -1;
42593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
426a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (mStarted) {
427a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused) {
428a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mPaused = false;
42993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            return startTracks(param);
430a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
431a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
432a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
433a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
4348f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    if (!param ||
4358f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        !param->findInt32(kKeyTimeScale, &mTimeScale)) {
4368f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        mTimeScale = 1000;
4378f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    }
4388f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    CHECK(mTimeScale > 0);
4398f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    LOGV("movie time scale: %d", mTimeScale);
4408f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
4417837c17063a4c50bc856ba59418516fdab731de7James Dong    mStreamableFile = true;
4427837c17063a4c50bc856ba59418516fdab731de7James Dong    mWriteMoovBoxToMemory = false;
4437837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBuffer = NULL;
4447837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
4457837c17063a4c50bc856ba59418516fdab731de7James Dong
44620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    beginBox("ftyp");
44793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong      {
44893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        int32_t fileType;
44993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (param && param->findInt32(kKeyFileType, &fileType) &&
45093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            fileType != OUTPUT_FORMAT_MPEG_4) {
45193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            writeFourcc("3gp4");
45293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        } else {
45393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            writeFourcc("isom");
45493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
45593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong      }
45620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      writeInt32(0);
45720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      writeFourcc("isom");
45893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong      writeFourcc("3gp4");
45920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    endBox();
46020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4617837c17063a4c50bc856ba59418516fdab731de7James Dong    mFreeBoxOffset = mOffset;
46220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4637837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mEstimatedMoovBoxSize == 0) {
4642dec2b5be2056c6d9428897dc672185872d30d17James Dong        int32_t bitRate = -1;
4652dec2b5be2056c6d9428897dc672185872d30d17James Dong        if (param) {
4662dec2b5be2056c6d9428897dc672185872d30d17James Dong            param->findInt32(kKeyBitRate, &bitRate);
4672dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
4682dec2b5be2056c6d9428897dc672185872d30d17James Dong        mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate);
4697837c17063a4c50bc856ba59418516fdab731de7James Dong    }
4707837c17063a4c50bc856ba59418516fdab731de7James Dong    CHECK(mEstimatedMoovBoxSize >= 8);
471c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    lseek64(mFd, mFreeBoxOffset, SEEK_SET);
4727837c17063a4c50bc856ba59418516fdab731de7James Dong    writeInt32(mEstimatedMoovBoxSize);
4737837c17063a4c50bc856ba59418516fdab731de7James Dong    write("free", 4);
4747837c17063a4c50bc856ba59418516fdab731de7James Dong
4757837c17063a4c50bc856ba59418516fdab731de7James Dong    mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize;
4767837c17063a4c50bc856ba59418516fdab731de7James Dong    mOffset = mMdatOffset;
477c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    lseek64(mFd, mMdatOffset, SEEK_SET);
4781acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
4791acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("????mdat", 8);
4801acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
4811acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("\x00\x00\x00\x01mdat????????", 16);
4821acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
4831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
4841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    status_t err = startWriterThread();
4851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (err != OK) {
4861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        return err;
4871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
4881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
4891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    err = startTracks(param);
490a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (err != OK) {
491a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return err;
49220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
4931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
494a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mStarted = true;
49525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
49620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
49720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4981f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongbool MPEG4Writer::use32BitFileOffset() const {
4991f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    return mUse32BitOffset;
5001f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
5011f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
50237187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::pause() {
503674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
50437187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
505a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
506a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
50737187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = OK;
508a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
509a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
51037187916a486504acaf83bea30147eb5fbf46ae5James Dong        status_t status = (*it)->pause();
51137187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (status != OK) {
51237187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
51337187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
514a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
51537187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
516a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
517a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
5181c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::stopWriterThread() {
519cb09c03450bb09304ad5afd2d223254bf2e6e38cJames Dong    LOGD("Stopping writer thread");
5201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
5211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    {
5221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        Mutex::Autolock autolock(mLock);
5231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
5241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mDone = true;
5251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkReadyCondition.signal();
5261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
5271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
5281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void *dummy;
5291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_join(mThread, &dummy);
530cb09c03450bb09304ad5afd2d223254bf2e6e38cJames Dong    LOGD("Writer thread stopped");
5311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
5321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
53313f6284305e4b27395a23db7882d670bdb1bcae1James Dong/*
53413f6284305e4b27395a23db7882d670bdb1bcae1James Dong * MP4 file standard defines a composition matrix:
53513f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | a  b  u |
53613f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | c  d  v |
53713f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | x  y  w |
53813f6284305e4b27395a23db7882d670bdb1bcae1James Dong *
53913f6284305e4b27395a23db7882d670bdb1bcae1James Dong * the element in the matrix is stored in the following
54013f6284305e4b27395a23db7882d670bdb1bcae1James Dong * order: {a, b, u, c, d, v, x, y, w},
54113f6284305e4b27395a23db7882d670bdb1bcae1James Dong * where a, b, c, d, x, and y is in 16.16 format, while
54213f6284305e4b27395a23db7882d670bdb1bcae1James Dong * u, v and w is in 2.30 format.
54313f6284305e4b27395a23db7882d670bdb1bcae1James Dong */
54413f6284305e4b27395a23db7882d670bdb1bcae1James Dongvoid MPEG4Writer::writeCompositionMatrix(int degrees) {
54513f6284305e4b27395a23db7882d670bdb1bcae1James Dong    LOGV("writeCompositionMatrix");
54613f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t a = 0x00010000;
54713f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t b = 0;
54813f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t c = 0;
54913f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t d = 0x00010000;
55013f6284305e4b27395a23db7882d670bdb1bcae1James Dong    switch (degrees) {
55113f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 0:
55213f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
55313f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 90:
55413f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0;
55513f6284305e4b27395a23db7882d670bdb1bcae1James Dong            b = 0x00010000;
55613f6284305e4b27395a23db7882d670bdb1bcae1James Dong            c = 0xFFFF0000;
55713f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0;
55813f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
55913f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 180:
56013f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0xFFFF0000;
56113f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0xFFFF0000;
56213f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
56313f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 270:
56413f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0;
56513f6284305e4b27395a23db7882d670bdb1bcae1James Dong            b = 0xFFFF0000;
56613f6284305e4b27395a23db7882d670bdb1bcae1James Dong            c = 0x00010000;
56713f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0;
56813f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
56913f6284305e4b27395a23db7882d670bdb1bcae1James Dong        default:
57013f6284305e4b27395a23db7882d670bdb1bcae1James Dong            CHECK(!"Should never reach this unknown rotation");
57113f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
57213f6284305e4b27395a23db7882d670bdb1bcae1James Dong    }
57313f6284305e4b27395a23db7882d670bdb1bcae1James Dong
57413f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(a);           // a
57513f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(b);           // b
57613f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // u
57713f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(c);           // c
57813f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(d);           // d
57913f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // v
58013f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // x
58113f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // y
58213f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0x40000000);  // w
58313f6284305e4b27395a23db7882d670bdb1bcae1James Dong}
58413f6284305e4b27395a23db7882d670bdb1bcae1James Dong
58513f6284305e4b27395a23db7882d670bdb1bcae1James Dong
58637187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::stop() {
587674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
58837187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
58920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
59020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
59137187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = OK;
5928f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t maxDurationUs = 0;
59320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
59420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber         it != mTracks.end(); ++it) {
59537187916a486504acaf83bea30147eb5fbf46ae5James Dong        status_t status = (*it)->stop();
59637187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (err == OK && status != OK) {
59737187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
59837187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
59920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6008f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int64_t durationUs = (*it)->getDurationUs();
6018f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        if (durationUs > maxDurationUs) {
6028f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            maxDurationUs = durationUs;
60320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
60420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
60520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    stopWriterThread();
6077837c17063a4c50bc856ba59418516fdab731de7James Dong
60837187916a486504acaf83bea30147eb5fbf46ae5James Dong    // Do not write out movie header on error.
60937187916a486504acaf83bea30147eb5fbf46ae5James Dong    if (err != OK) {
610674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        close(mFd);
611674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        mFd = -1;
612674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        mInitCheck = NO_INIT;
61337187916a486504acaf83bea30147eb5fbf46ae5James Dong        mStarted = false;
61437187916a486504acaf83bea30147eb5fbf46ae5James Dong        return err;
61537187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
61637187916a486504acaf83bea30147eb5fbf46ae5James Dong
61720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // Fix up the size of the 'mdat' chunk.
6181acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
619c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mMdatOffset, SEEK_SET);
6201acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        int32_t size = htonl(static_cast<int32_t>(mOffset - mMdatOffset));
621c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &size, 4);
6221acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
623c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mMdatOffset + 8, SEEK_SET);
6241acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        int64_t size = mOffset - mMdatOffset;
6251acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        size = hton64(size);
626c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &size, 8);
6271acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
628c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    lseek64(mFd, mOffset, SEEK_SET);
62920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
63020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    time_t now = time(NULL);
631c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    const off64_t moovOffset = mOffset;
6327837c17063a4c50bc856ba59418516fdab731de7James Dong    mWriteMoovBoxToMemory = true;
6337837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize);
6347837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
6357837c17063a4c50bc856ba59418516fdab731de7James Dong    CHECK(mMoovBoxBuffer != NULL);
636c059860c73678a202bfa33062723e8f82fb779d9James Dong    int32_t duration = (maxDurationUs * mTimeScale + 5E5) / 1E6;
63720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
63820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    beginBox("moov");
63920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
64020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      beginBox("mvhd");
64120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // version=0, flags=0
64220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(now);           // creation time
64320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(now);           // modification time
6448f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        writeInt32(mTimeScale);    // mvhd timescale
6451acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        writeInt32(duration);
6461acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        writeInt32(0x10000);       // rate: 1.0
64720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt16(0x100);         // volume
64820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt16(0);             // reserved
64920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // reserved
65020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // reserved
65113f6284305e4b27395a23db7882d670bdb1bcae1James Dong        writeCompositionMatrix(0); // matrix
65220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
65320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
65420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
65520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
65620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
65720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
65820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(mTracks.size() + 1);  // nextTrackID
65920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      endBox();  // mvhd
66020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
66120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      int32_t id = 1;
66220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      for (List<Track *>::iterator it = mTracks.begin();
66320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber           it != mTracks.end(); ++it, ++id) {
6641acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          (*it)->writeTrackHeader(id, mUse32BitOffset);
66520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      }
66620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    endBox();  // moov
66720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6687837c17063a4c50bc856ba59418516fdab731de7James Dong    mWriteMoovBoxToMemory = false;
6697837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mStreamableFile) {
6707837c17063a4c50bc856ba59418516fdab731de7James Dong        CHECK(mMoovBoxBufferOffset + 8 <= mEstimatedMoovBoxSize);
6717837c17063a4c50bc856ba59418516fdab731de7James Dong
6727837c17063a4c50bc856ba59418516fdab731de7James Dong        // Moov box
673c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mFreeBoxOffset, SEEK_SET);
6747837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset = mFreeBoxOffset;
675674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset);
6767837c17063a4c50bc856ba59418516fdab731de7James Dong
6777837c17063a4c50bc856ba59418516fdab731de7James Dong        // Free box
678c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mOffset, SEEK_SET);
6797837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset);
6807837c17063a4c50bc856ba59418516fdab731de7James Dong        write("free", 4);
6817837c17063a4c50bc856ba59418516fdab731de7James Dong
6827837c17063a4c50bc856ba59418516fdab731de7James Dong        // Free temp memory
6837837c17063a4c50bc856ba59418516fdab731de7James Dong        free(mMoovBoxBuffer);
6847837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBuffer = NULL;
6857837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBufferOffset = 0;
6862dec2b5be2056c6d9428897dc672185872d30d17James Dong    } else {
6872dec2b5be2056c6d9428897dc672185872d30d17James Dong        LOGI("The mp4 file will not be streamable.");
6887837c17063a4c50bc856ba59418516fdab731de7James Dong    }
6897837c17063a4c50bc856ba59418516fdab731de7James Dong
6900c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(mBoxes.empty());
69120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
692674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    close(mFd);
693674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    mFd = -1;
694674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    mInitCheck = NO_INIT;
695a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mStarted = false;
69637187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
69720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
69820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
69913aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) {
70013aec890216948b0c364f8f92792129d0335f506James Dong    mInterleaveDurationUs = durationUs;
70113aec890216948b0c364f8f92792129d0335f506James Dong    return OK;
70213aec890216948b0c364f8f92792129d0335f506James Dong}
70313aec890216948b0c364f8f92792129d0335f506James Dong
70413aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() {
70513aec890216948b0c364f8f92792129d0335f506James Dong    mLock.lock();
70613aec890216948b0c364f8f92792129d0335f506James Dong}
70713aec890216948b0c364f8f92792129d0335f506James Dong
70813aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() {
70913aec890216948b0c364f8f92792129d0335f506James Dong    mLock.unlock();
71013aec890216948b0c364f8f92792129d0335f506James Dong}
71120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
712c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addSample_l(MediaBuffer *buffer) {
713c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t old_offset = mOffset;
71420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
715c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    ::write(mFd,
716c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong          (const uint8_t *)buffer->data() + buffer->range_offset(),
717c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong          buffer->range_length());
71820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
71920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += buffer->range_length();
72020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
72120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return old_offset;
72220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
72320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
72403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) {
72503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (buffer->range_length() < 4) {
72603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return;
72703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
72803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
72903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    const uint8_t *ptr =
73003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        (const uint8_t *)buffer->data() + buffer->range_offset();
73103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
73203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) {
73303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        buffer->set_range(
73403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                buffer->range_offset() + 4, buffer->range_length() - 4);
73503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
73603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
73703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
738c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) {
739c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t old_offset = mOffset;
74030ab66297501757d745b9ae10da61adcd891f497Andreas Huber
74130ab66297501757d745b9ae10da61adcd891f497Andreas Huber    size_t length = buffer->range_length();
74203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
743b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (mUse4ByteNalLength) {
744b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        uint8_t x = length >> 24;
745c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
746b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = (length >> 16) & 0xff;
747c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
748b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = (length >> 8) & 0xff;
749c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
750b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = length & 0xff;
751c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
752c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong
753c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd,
754c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong              (const uint8_t *)buffer->data() + buffer->range_offset(),
755c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong              length);
756b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong
757b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mOffset += length + 4;
758b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    } else {
759b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        CHECK(length < 65536);
76030ab66297501757d745b9ae10da61adcd891f497Andreas Huber
761b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        uint8_t x = length >> 8;
762c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
763b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = length & 0xff;
764c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
765c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, (const uint8_t *)buffer->data() + buffer->range_offset(), length);
766b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mOffset += length + 2;
767b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    }
76830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
76930ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return old_offset;
77030ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
77130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
7727837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write(
773674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        const void *ptr, size_t size, size_t nmemb) {
7747837c17063a4c50bc856ba59418516fdab731de7James Dong
7757837c17063a4c50bc856ba59418516fdab731de7James Dong    const size_t bytes = size * nmemb;
7767837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
777674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        // This happens only when we write the moov box at the end of
778674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        // recording, not for each output video/audio frame we receive.
779c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes;
7801acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        if (moovBoxSize > mEstimatedMoovBoxSize) {
781c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            for (List<off64_t>::iterator it = mBoxes.begin();
7827837c17063a4c50bc856ba59418516fdab731de7James Dong                 it != mBoxes.end(); ++it) {
7837837c17063a4c50bc856ba59418516fdab731de7James Dong                (*it) += mOffset;
7847837c17063a4c50bc856ba59418516fdab731de7James Dong            }
785674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong            lseek64(mFd, mOffset, SEEK_SET);
786674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong            ::write(mFd, mMoovBoxBuffer, mMoovBoxBufferOffset);
787674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong            ::write(mFd, ptr, size * nmemb);
7887837c17063a4c50bc856ba59418516fdab731de7James Dong            mOffset += (bytes + mMoovBoxBufferOffset);
7897837c17063a4c50bc856ba59418516fdab731de7James Dong            free(mMoovBoxBuffer);
7907837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBuffer = NULL;
7917837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset = 0;
7927837c17063a4c50bc856ba59418516fdab731de7James Dong            mWriteMoovBoxToMemory = false;
7937837c17063a4c50bc856ba59418516fdab731de7James Dong            mStreamableFile = false;
7947837c17063a4c50bc856ba59418516fdab731de7James Dong        } else {
7957837c17063a4c50bc856ba59418516fdab731de7James Dong            memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes);
7967837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset += bytes;
7977837c17063a4c50bc856ba59418516fdab731de7James Dong        }
7987837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
799674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        ::write(mFd, ptr, size * nmemb);
8007837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset += bytes;
8017837c17063a4c50bc856ba59418516fdab731de7James Dong    }
8027837c17063a4c50bc856ba59418516fdab731de7James Dong    return bytes;
8037837c17063a4c50bc856ba59418516fdab731de7James Dong}
8047837c17063a4c50bc856ba59418516fdab731de7James Dong
80520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) {
8060c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(fourcc), 4);
80720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8087837c17063a4c50bc856ba59418516fdab731de7James Dong    mBoxes.push_back(mWriteMoovBoxToMemory?
8097837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset: mOffset);
81020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
81120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeInt32(0);
81220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeFourcc(fourcc);
81320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
81420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
81520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() {
8160c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(!mBoxes.empty());
81720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
818c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t offset = *--mBoxes.end();
81920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mBoxes.erase(--mBoxes.end());
82020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8217837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
8227837c17063a4c50bc856ba59418516fdab731de7James Dong       int32_t x = htonl(mMoovBoxBufferOffset - offset);
8237837c17063a4c50bc856ba59418516fdab731de7James Dong       memcpy(mMoovBoxBuffer + offset, &x, 4);
8247837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
825c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, offset, SEEK_SET);
8267837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mOffset - offset);
8277837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset -= 4;
828c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mOffset, SEEK_SET);
8297837c17063a4c50bc856ba59418516fdab731de7James Dong    }
83020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
83120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
83220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) {
833674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 1);
83420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
83520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
83620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) {
83720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htons(x);
838674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 2);
83920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
84020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
84120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) {
84220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htonl(x);
843674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 4);
84420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
84520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
84620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) {
84720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = hton64(x);
848674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 8);
84920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
85020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
85120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) {
85220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t n = strlen(s);
853674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(s, 1, n + 1);
85420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
85520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
85620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) {
8570c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(s), 4);
858674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(s, 1, 4);
85920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
86020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
86120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) {
862674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(data, 1, size);
86320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
86420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
86578a1a286f736888ae7af8860b2c424af0d978848James Dongbool MPEG4Writer::isFileStreamable() const {
86678a1a286f736888ae7af8860b2c424af0d978848James Dong    return mStreamableFile;
86778a1a286f736888ae7af8860b2c424af0d978848James Dong}
86878a1a286f736888ae7af8860b2c424af0d978848James Dong
869d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() {
870d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
871d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileSizeLimitBytes == 0) {
872d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
873d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
874d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
875956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize);
876d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
877d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
878d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes();
879d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
8801f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
881acd234bba9f048971d66890009eeff9a8db94be3James Dong    // Be conservative in the estimate: do not exceed 95% of
882acd234bba9f048971d66890009eeff9a8db94be3James Dong    // the target file limit. For small target file size limit, though,
883acd234bba9f048971d66890009eeff9a8db94be3James Dong    // this will not help.
884acd234bba9f048971d66890009eeff9a8db94be3James Dong    return (nTotalBytesEstimate >= (95 * mMaxFileSizeLimitBytes) / 100);
885d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
886d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
887d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() {
888d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
889d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileDurationLimitUs == 0) {
890d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
891d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
892d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
893d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
894d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
895d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) {
896d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            return true;
897d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
898d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
899d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return false;
900d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
901d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
90225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() {
90325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool allDone = true;
90425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
90525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber         it != mTracks.end(); ++it) {
90625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        if (!(*it)->reachedEOS()) {
90725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            allDone = false;
90825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            break;
90925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        }
91025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
91125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
91225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return allDone;
91325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
91425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
915f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) {
916f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    LOGI("setStartTimestampUs: %lld", timeUs);
917f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    CHECK(timeUs >= 0);
9183c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
919065d1aff96818df54456053f1574aec8a234d0deJames Dong    if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) {
920f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mStartTimestampUs = timeUs;
921f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        LOGI("Earliest track starting time: %lld", mStartTimestampUs);
9223c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    }
9233c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
9243c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
925f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() {
9263c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
9273c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    return mStartTimestampUs;
9283c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
9293c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
93058ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() {
93158ae9c530247668f8af36e30d228c716c226b3d4James Dong    Mutex::Autolock autolock(mLock);
93258ae9c530247668f8af36e30d228c716c226b3d4James Dong    return mTracks.size();
93358ae9c530247668f8af36e30d228c716c226b3d4James Dong}
93458ae9c530247668f8af36e30d228c716c226b3d4James Dong
93520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
93620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
93720111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track(
93825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        MPEG4Writer *owner, const sp<MediaSource> &source)
93920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mOwner(owner),
94025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mMeta(source->getFormat()),
94120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSource(source),
94220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDone(false),
943a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
944a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mResumed(false),
945c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong      mTrackDurationUs(0),
946956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      mEstimatedTrackSizeBytes(0),
947be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong      mSamplesHaveSameSize(true),
94820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCodecSpecificData(NULL),
94925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mCodecSpecificDataSize(0),
950548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber      mGotAllCodecSpecificData(false),
95113f6284305e4b27395a23db7882d670bdb1bcae1James Dong      mReachedEOS(false),
95213f6284305e4b27395a23db7882d670bdb1bcae1James Dong      mRotation(0) {
95319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    getCodecSpecificDataFromInputFormatIfPossible();
9548f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
9551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    const char *mime;
9561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mMeta->findCString(kKeyMIMEType, &mime);
9571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
9581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAudio = !strncasecmp(mime, "audio/", 6);
9591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
9601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong               !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC);
9611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
962c059860c73678a202bfa33062723e8f82fb779d9James Dong    setTimeScale();
963c059860c73678a202bfa33062723e8f82fb779d9James Dong}
964c059860c73678a202bfa33062723e8f82fb779d9James Dong
9651f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::updateTrackSizeEstimate() {
9661f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
9671f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    int64_t stcoBoxSizeBytes = mOwner->use32BitFileOffset()
9681f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                                ? mNumStcoTableEntries * 4
9691f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                                : mNumStcoTableEntries * 8;
9701f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
9711f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mNumSamples * 4);
9721f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
97378a1a286f736888ae7af8860b2c424af0d978848James Dong    mEstimatedTrackSizeBytes = mMdatSizeBytes;  // media data size
97478a1a286f736888ae7af8860b2c424af0d978848James Dong    if (!mOwner->isFileStreamable()) {
97578a1a286f736888ae7af8860b2c424af0d978848James Dong        // Reserved free space is not large enough to hold
97678a1a286f736888ae7af8860b2c424af0d978848James Dong        // all meta data and thus wasted.
97778a1a286f736888ae7af8860b2c424af0d978848James Dong        mEstimatedTrackSizeBytes += mNumStscTableEntries * 12 +  // stsc box size
97878a1a286f736888ae7af8860b2c424af0d978848James Dong                                    mNumStssTableEntries * 4 +   // stss box size
97978a1a286f736888ae7af8860b2c424af0d978848James Dong                                    mNumSttsTableEntries * 8 +   // stts box size
98078a1a286f736888ae7af8860b2c424af0d978848James Dong                                    stcoBoxSizeBytes +           // stco box size
98178a1a286f736888ae7af8860b2c424af0d978848James Dong                                    stszBoxSizeBytes;            // stsz box size
98278a1a286f736888ae7af8860b2c424af0d978848James Dong    }
9831f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
9841f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
9851f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStscTableEntry(
9861f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        size_t chunkId, size_t sampleId) {
9871f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
9881f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        StscTableEntry stscEntry(chunkId, sampleId, 1);
9891f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mStscTableEntries.push_back(stscEntry);
9901f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        ++mNumStscTableEntries;
9911f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
9921f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
9931f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) {
9941f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mStssTableEntries.push_back(sampleId);
9951f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    ++mNumStssTableEntries;
9961f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
9971f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
9981f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneSttsTableEntry(
9991f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        size_t sampleCount, int64_t durationUs) {
10001f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
10011f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    SttsTableEntry sttsEntry(sampleCount, durationUs);
10021f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mSttsTableEntries.push_back(sttsEntry);
10031f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    ++mNumSttsTableEntries;
10041f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
10051f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1006c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongvoid MPEG4Writer::Track::addChunkOffset(off64_t offset) {
10071f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    ++mNumStcoTableEntries;
10081f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mChunkOffsets.push_back(offset);
10091f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
10101f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1011c059860c73678a202bfa33062723e8f82fb779d9James Dongvoid MPEG4Writer::Track::setTimeScale() {
1012c059860c73678a202bfa33062723e8f82fb779d9James Dong    LOGV("setTimeScale");
1013c059860c73678a202bfa33062723e8f82fb779d9James Dong    // Default time scale
1014c059860c73678a202bfa33062723e8f82fb779d9James Dong    mTimeScale = 90000;
1015c059860c73678a202bfa33062723e8f82fb779d9James Dong
1016c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mIsAudio) {
1017c059860c73678a202bfa33062723e8f82fb779d9James Dong        // Use the sampling rate as the default time scale for audio track.
1018c059860c73678a202bfa33062723e8f82fb779d9James Dong        int32_t sampleRate;
1019c059860c73678a202bfa33062723e8f82fb779d9James Dong        bool success = mMeta->findInt32(kKeySampleRate, &sampleRate);
1020c059860c73678a202bfa33062723e8f82fb779d9James Dong        CHECK(success);
1021c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = sampleRate;
1022c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
1023c059860c73678a202bfa33062723e8f82fb779d9James Dong
1024c059860c73678a202bfa33062723e8f82fb779d9James Dong    // If someone would like to overwrite the timescale, use user-supplied value.
1025c059860c73678a202bfa33062723e8f82fb779d9James Dong    int32_t timeScale;
1026c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mMeta->findInt32(kKeyTimeScale, &timeScale)) {
1027c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = timeScale;
1028c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
1029c059860c73678a202bfa33062723e8f82fb779d9James Dong
10308f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    CHECK(mTimeScale > 0);
103119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber}
103219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
103319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Hubervoid MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() {
103419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    const char *mime;
103519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
103619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
103719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
103819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        uint32_t type;
103919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        const void *data;
104019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        size_t size;
104119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        if (mMeta->findData(kKeyAVCC, &type, &data, &size)) {
104219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mCodecSpecificData = malloc(size);
104319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mCodecSpecificDataSize = size;
104419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            memcpy(mCodecSpecificData, data, size);
104519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mGotAllCodecSpecificData = true;
104619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        }
104719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
104819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
104919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        uint32_t type;
105019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        const void *data;
105119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        size_t size;
105219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        if (mMeta->findData(kKeyESDS, &type, &data, &size)) {
105319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            ESDS esds(data, size);
105419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            if (esds.getCodecSpecificInfo(&data, &size) == OK) {
105519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mCodecSpecificData = malloc(size);
105619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mCodecSpecificDataSize = size;
105719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                memcpy(mCodecSpecificData, data, size);
105819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mGotAllCodecSpecificData = true;
105919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            }
106019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        }
106119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
106220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
106320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
106420111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() {
106520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    stop();
106620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
106720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mCodecSpecificData != NULL) {
106820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        free(mCodecSpecificData);
106920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mCodecSpecificData = NULL;
107020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
107120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
107220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
107393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) {
107493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    LOGV("initTrackingProgressStatus");
107593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mPreviousTrackTimeUs = -1;
107693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackingProgressStatus = false;
107793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackEveryTimeDurationUs = 0;
107893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    {
107993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        int64_t timeUs;
108093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) {
108193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            LOGV("Receive request to track progress status for every %lld us", timeUs);
108293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackEveryTimeDurationUs = timeUs;
108393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackingProgressStatus = true;
108493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
108593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
108693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
108793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
10881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong// static
10891c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid *MPEG4Writer::ThreadWrapper(void *me) {
10901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("ThreadWrapper: %p", me);
10911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    MPEG4Writer *writer = static_cast<MPEG4Writer *>(me);
10921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    writer->threadFunc();
10931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return NULL;
10941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
10951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
10961c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::bufferChunk(const Chunk& chunk) {
10971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("bufferChunk: %p", chunk.mTrack);
10981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Mutex::Autolock autolock(mLock);
10991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    CHECK_EQ(mDone, false);
11001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
11011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
11021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
11031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
11041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (chunk.mTrack == it->mTrack) {  // Found owner
11051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            it->mChunks.push_back(chunk);
11061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.signal();
11071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            return;
11081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
11091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
11101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
11111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    CHECK("Received a chunk for a unknown track" == 0);
11121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
11131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
11141c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::writeFirstChunk(ChunkInfo* info) {
11151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("writeFirstChunk: %p", info->mTrack);
11161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
11171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    List<Chunk>::iterator chunkIt = info->mChunks.begin();
11181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<MediaBuffer *>::iterator it = chunkIt->mSamples.begin();
11191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != chunkIt->mSamples.end(); ++it) {
11201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1121c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t offset = info->mTrack->isAvc()
11221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                            ? addLengthPrefixedSample_l(*it)
11231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                            : addSample_l(*it);
11241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (it == chunkIt->mSamples.begin()) {
11251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            info->mTrack->addChunkOffset(offset);
11261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
11271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
11281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
11291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    // Done with the current chunk.
11301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    // Release all the samples in this chunk.
11311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    while (!chunkIt->mSamples.empty()) {
11321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        List<MediaBuffer *>::iterator it = chunkIt->mSamples.begin();
11331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it)->release();
11341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it) = NULL;
11351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        chunkIt->mSamples.erase(it);
11361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
11371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    chunkIt->mSamples.clear();
11381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    info->mChunks.erase(chunkIt);
11391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
11401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
11411c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::writeChunks() {
11421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("writeChunks");
11431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    size_t outstandingChunks = 0;
11441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    while (!mChunkInfos.empty()) {
11451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        List<ChunkInfo>::iterator it = mChunkInfos.begin();
11461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        while (!it->mChunks.empty()) {
11471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            CHECK_EQ(OK, writeOneChunk());
11481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            ++outstandingChunks;
11491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
11501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        it->mTrack = NULL;
11511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkInfos.erase(it);
11521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
11531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mChunkInfos.clear();
11541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGD("%d chunks are written in the last batch", outstandingChunks);
11551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
11561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
11571c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::writeOneChunk() {
11581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("writeOneChunk");
11591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
11601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    // Find the smallest timestamp, and write that chunk out
11611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    // XXX: What if some track is just too slow?
11621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL;
11631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Track *track = NULL;
11641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
11651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
11661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (!it->mChunks.empty()) {
11671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            List<Chunk>::iterator chunkIt = it->mChunks.begin();
11681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (chunkIt->mTimeStampUs < minTimestampUs) {
11691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                minTimestampUs = chunkIt->mTimeStampUs;
11701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                track = it->mTrack;
11711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            }
11721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
11731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
11741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
11751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (track == NULL) {
11761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        LOGV("Nothing to be written after all");
11771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        return OK;
11781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
11791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
11801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (mIsFirstChunk) {
11811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsFirstChunk = false;
11821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
11831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
11841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
11851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (it->mTrack == track) {
11861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            writeFirstChunk(&(*it));
11871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
11881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
11891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return OK;
11901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
11911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
11921c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::threadFunc() {
11931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("threadFunc");
11941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1195a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    prctl(PR_SET_NAME, (unsigned long)"MPEG4Writer", 0, 0, 0);
11961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    while (!mDone) {
11971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        {
11981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            Mutex::Autolock autolock(mLock);
11991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.wait(mLock);
12001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            CHECK_EQ(writeOneChunk(), OK);
12011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
12021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
12031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
12041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    {
12051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        // Write ALL samples
12061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        Mutex::Autolock autolock(mLock);
12071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        writeChunks();
12081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
12091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
12101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
12111c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::startWriterThread() {
12121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("startWriterThread");
12131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
12141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mDone = false;
12151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsFirstChunk = true;
1216e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    mDriftTimeUs = 0;
12171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<Track *>::iterator it = mTracks.begin();
12181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mTracks.end(); ++it) {
12191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        ChunkInfo info;
12201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        info.mTrack = *it;
12211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkInfos.push_back(info);
12221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
12231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
12241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_t attr;
12251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_init(&attr);
12261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
12271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_create(&mThread, &attr, ThreadWrapper, this);
12281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_destroy(&attr);
12291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return OK;
12301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
12311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
12321f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
123393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) {
1234a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (!mDone && mPaused) {
1235a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mPaused = false;
1236a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mResumed = true;
1237a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
1238a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
123925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
124093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t startTimeUs;
124119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) {
124219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        startTimeUs = 0;
124319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
124419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
124513f6284305e4b27395a23db7882d670bdb1bcae1James Dong    int32_t rotationDegrees;
124613f6284305e4b27395a23db7882d670bdb1bcae1James Dong    if (!mIsAudio && params && params->findInt32(kKeyRotation, &rotationDegrees)) {
124713f6284305e4b27395a23db7882d670bdb1bcae1James Dong        mRotation = rotationDegrees;
124813f6284305e4b27395a23db7882d670bdb1bcae1James Dong    }
124913f6284305e4b27395a23db7882d670bdb1bcae1James Dong
12505b6a01e65aa4129a9226667536d1bc1dad5980d8James Dong    mIsRealTimeRecording = true;
1251e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    {
1252e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        int32_t isNotRealTime;
1253e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        if (params && params->findInt32(kKeyNotRealTime, &isNotRealTime)) {
1254e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            mIsRealTimeRecording = (isNotRealTime == 0);
1255e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        }
1256e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    }
1257e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
125893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    initTrackingProgressStatus(params);
125993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
1260f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    sp<MetaData> meta = new MetaData;
1261f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    meta->setInt64(kKeyTime, startTimeUs);
1262f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    status_t err = mSource->start(meta.get());
126325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    if (err != OK) {
126425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        mDone = mReachedEOS = true;
126525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return err;
126625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
126720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
126820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_t attr;
126920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_init(&attr);
127020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
127120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
127220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = false;
1273c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs = 0;
127425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = false;
1275956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    mEstimatedTrackSizeBytes = 0;
12761f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mNumStcoTableEntries = 0;
12771f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mNumStssTableEntries = 0;
12781f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mNumStscTableEntries = 0;
12791f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mNumSttsTableEntries = 0;
12801f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mMdatSizeBytes = 0;
1281872a481558350634a3fd5cb67939de288af00ecbJames Dong    mIsMediaTimeAdjustmentOn = false;
1282872a481558350634a3fd5cb67939de288af00ecbJames Dong    mPrevMediaTimeAdjustTimestampUs = 0;
1283872a481558350634a3fd5cb67939de288af00ecbJames Dong    mMediaTimeAdjustNumFrames = 0;
1284872a481558350634a3fd5cb67939de288af00ecbJames Dong    mPrevMediaTimeAdjustSample = 0;
1285872a481558350634a3fd5cb67939de288af00ecbJames Dong    mTotalDriftTimeToAdjustUs = 0;
1286872a481558350634a3fd5cb67939de288af00ecbJames Dong    mPrevTotalAccumDriftTimeUs = 0;
128720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
128825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    pthread_create(&mThread, &attr, ThreadWrapper, this);
128920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_destroy(&attr);
129025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
129125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
129220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
129320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
129437187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::pause() {
1295a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
129637187916a486504acaf83bea30147eb5fbf46ae5James Dong    return OK;
1297a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
1298a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
129937187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::stop() {
1300cb09c03450bb09304ad5afd2d223254bf2e6e38cJames Dong    LOGD("Stopping %s track", mIsAudio? "Audio": "Video");
130120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mDone) {
130237187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
130320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
130420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
130520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = true;
130620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
130720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *dummy;
130820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_join(mThread, &dummy);
130920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
131037187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = (status_t) dummy;
131137187916a486504acaf83bea30147eb5fbf46ae5James Dong
1312cb09c03450bb09304ad5afd2d223254bf2e6e38cJames Dong    LOGD("Stopping %s track source", mIsAudio? "Audio": "Video");
131337187916a486504acaf83bea30147eb5fbf46ae5James Dong    {
131437187916a486504acaf83bea30147eb5fbf46ae5James Dong        status_t status = mSource->stop();
131537187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (err == OK && status != OK && status != ERROR_END_OF_STREAM) {
131637187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
131737187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
131837187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
131937187916a486504acaf83bea30147eb5fbf46ae5James Dong
1320cb09c03450bb09304ad5afd2d223254bf2e6e38cJames Dong    LOGD("%s track stopped", mIsAudio? "Audio": "Video");
132137187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
132220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
132320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
132425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() {
132525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return mReachedEOS;
132625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
132725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
132820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static
132920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) {
133020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = static_cast<Track *>(me);
133120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
133237187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = track->threadEntry();
133337187916a486504acaf83bea30147eb5fbf46ae5James Dong    return (void *) err;
133420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
133520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
13363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic void getNalUnitType(uint8_t byte, uint8_t* type) {
13373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    LOGV("getNalUnitType: %d", byte);
13383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // nal_unit_type: 5-bit unsigned integer
13403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *type = (byte & 0x1F);
13413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
13423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t *findNextStartCode(
13443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length) {
13453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    LOGV("findNextStartCode: %p %d", data, length);
13473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t bytesLeft = length;
13493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    while (bytesLeft > 4  &&
13503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            memcmp("\x00\x00\x00\x01", &data[length - bytesLeft], 4)) {
13513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        --bytesLeft;
13523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
13533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (bytesLeft <= 4) {
13543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        bytesLeft = 0; // Last parameter set
13553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
13563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return &data[length - bytesLeft];
13573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
13583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongconst uint8_t *MPEG4Writer::Track::parseParamSet(
13603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen) {
13613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    LOGV("parseParamSet");
13633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    CHECK(type == kNalUnitTypeSeqParamSet ||
13643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong          type == kNalUnitTypePicParamSet);
13653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *nextStartCode = findNextStartCode(data, length);
13673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *paramSetLen = nextStartCode - data;
13683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (*paramSetLen == 0) {
13693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        LOGE("Param set is malformed, since its length is 0");
13703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return NULL;
13713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
13723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    AVCParamSet paramSet(*paramSetLen, data);
13743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (type == kNalUnitTypeSeqParamSet) {
13753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (*paramSetLen < 4) {
13763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Seq parameter set malformed");
13773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return NULL;
13783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
13793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mSeqParamSets.empty()) {
13803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc = data[1];
13813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileCompatible = data[2];
13823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mLevelIdc = data[3];
13833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
13843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (mProfileIdc != data[1] ||
13853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mProfileCompatible != data[2] ||
13863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mLevelIdc != data[3]) {
13873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                LOGE("Inconsistent profile/level found in seq parameter sets");
13883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return NULL;
13893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
13903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
13913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mSeqParamSets.push_back(paramSet);
13923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    } else {
13933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mPicParamSets.push_back(paramSet);
13943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
13953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return nextStartCode;
13963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
13973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::copyAVCCodecSpecificData(
13993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
14003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    LOGV("copyAVCCodecSpecificData");
14013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
14023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 2 bytes for each of the parameter set length field
14033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // plus the 7 bytes for the header
14043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (size < 4 + 7) {
14053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        LOGE("Codec specific data length too short: %d", size);
14063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return ERROR_MALFORMED;
14073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
14083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
14093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize = size;
14103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificData = malloc(size);
14113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    memcpy(mCodecSpecificData, data, size);
14123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
14133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
14143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
14153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::parseAVCCodecSpecificData(
14163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
14173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
14183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    LOGV("parseAVCCodecSpecificData");
14193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data starts with a start code.
14203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // SPS and PPS are separated with start codes.
14213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Also, SPS must come before PPS
14223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t type = kNalUnitTypeSeqParamSet;
14233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotSps = false;
14243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotPps = false;
14253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *tmp = data;
14263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *nextStartCode = data;
14273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t bytesLeft = size;
14283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t paramSetLen = 0;
14293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize = 0;
14303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) {
14313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        getNalUnitType(*(tmp + 4), &type);
14323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (type == kNalUnitTypeSeqParamSet) {
14333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (gotPps) {
14343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                LOGE("SPS must come before PPS");
14353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
14363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
14373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
14383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotSps = true;
14393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
14403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
14413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else if (type == kNalUnitTypePicParamSet) {
14423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
14433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                LOGE("SPS must come before PPS");
14443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
14453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
14463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotPps) {
14473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotPps = true;
14483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
14493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
14503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
14513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Only SPS and PPS Nal units are expected");
14523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
14533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
14543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
14553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nextStartCode == NULL) {
14563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
14573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
14583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
14593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Move on to find the next parameter set
14603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        bytesLeft -= nextStartCode - tmp;
14613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        tmp = nextStartCode;
14623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mCodecSpecificDataSize += (2 + paramSetLen);
14633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
14643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
14653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
14663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of seq parameter sets
14673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nSeqParamSets = mSeqParamSets.size();
14683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets == 0) {
14693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Cound not find sequence parameter set");
14703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
14713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
14723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
14733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets > 0x1F) {
14743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Too many seq parameter sets (%d) found", nSeqParamSets);
14753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
14763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
14773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
14783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
14793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
14803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of pic parameter sets
14813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nPicParamSets = mPicParamSets.size();
14823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets == 0) {
14833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Cound not find picture parameter set");
14843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
14853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
14863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets > 0xFF) {
14873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Too many pic parameter sets (%d) found", nPicParamSets);
14883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
14893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
14903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
14913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
14923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
14933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the profiles
14943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // These profiles requires additional parameter set extensions
14953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mProfileIdc == 100 || mProfileIdc == 110 ||
14963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc == 122 || mProfileIdc == 144) {
14973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Sorry, no support for profile_idc: %d!", mProfileIdc);
14983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return BAD_VALUE;
14993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
15003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
15013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
15023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
15033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
1504548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
150503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData(
150603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        const uint8_t *data, size_t size) {
1507548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
150803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (mCodecSpecificData != NULL) {
1509548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        LOGE("Already have codec specific data");
151003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
151103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
151203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
15133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (size < 4) {
15143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        LOGE("Codec specific data length too short: %d", size);
151503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
151603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
151703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
15183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data is in the form of AVCCodecSpecificData
15193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (memcmp("\x00\x00\x00\x01", data, 4)) {
15203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return copyAVCCodecSpecificData(data, size);
152103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
152203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
15233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (parseAVCCodecSpecificData(data, size) != OK) {
152403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
152503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
152603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
15273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // ISO 14496-15: AVC file format
15283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize += 7;  // 7 more bytes in the header
152903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    mCodecSpecificData = malloc(mCodecSpecificDataSize);
153003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    uint8_t *header = (uint8_t *)mCodecSpecificData;
15313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = 1;                     // version
15323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[1] = mProfileIdc;           // profile indication
15333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[2] = mProfileCompatible;    // profile compatibility
15343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[3] = mLevelIdc;
153503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
15363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne
1537b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (mOwner->useNalLengthFour()) {
1538b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        header[4] = 0xfc | 3;  // length size == 4 bytes
1539b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    } else {
1540b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        header[4] = 0xfc | 1;  // length size == 2 bytes
1541b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    }
154203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
15433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 3-bit '111' followed by 5-bit numSequenceParameterSets
15443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nSequenceParamSets = mSeqParamSets.size();
15453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[5] = 0xe0 | nSequenceParamSets;
15463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 6;
15473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mSeqParamSets.begin();
15483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mSeqParamSets.end(); ++it) {
15493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit sequence parameter set length
15503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t seqParamSetLength = it->mLength;
15513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = seqParamSetLength >> 8;
15523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = seqParamSetLength & 0xff;
15533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
15543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // SPS NAL unit (sequence parameter length bytes)
15553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, seqParamSetLength);
15563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + seqParamSetLength);
15573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
15583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
15593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 8-bit nPictureParameterSets
15603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nPictureParamSets = mPicParamSets.size();
15613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = nPictureParamSets;
15623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 1;
15633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mPicParamSets.begin();
15643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mPicParamSets.end(); ++it) {
15653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit picture parameter set length
15663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t picParamSetLength = it->mLength;
15673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = picParamSetLength >> 8;
15683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = picParamSetLength & 0xff;
15693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
15703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // PPS Nal unit (picture parameter set length bytes)
15713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, picParamSetLength);
15723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + picParamSetLength);
15733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
157403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
157503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    return OK;
157603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
157703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
1578872a481558350634a3fd5cb67939de288af00ecbJames Dong/*
1579872a481558350634a3fd5cb67939de288af00ecbJames Dong* The video track's media time adjustment for real-time applications
1580872a481558350634a3fd5cb67939de288af00ecbJames Dong* is described as follows:
1581872a481558350634a3fd5cb67939de288af00ecbJames Dong*
1582872a481558350634a3fd5cb67939de288af00ecbJames Dong* First, the media time adjustment is done for every period of
1583872a481558350634a3fd5cb67939de288af00ecbJames Dong* kVideoMediaTimeAdjustPeriodTimeUs. kVideoMediaTimeAdjustPeriodTimeUs
1584872a481558350634a3fd5cb67939de288af00ecbJames Dong* is currently a fixed value chosen heuristically. The value of
1585872a481558350634a3fd5cb67939de288af00ecbJames Dong* kVideoMediaTimeAdjustPeriodTimeUs should not be very large or very small
1586872a481558350634a3fd5cb67939de288af00ecbJames Dong* for two considerations: on one hand, a relatively large value
1587872a481558350634a3fd5cb67939de288af00ecbJames Dong* helps reduce large fluctuation of drift time in the audio encoding
1588872a481558350634a3fd5cb67939de288af00ecbJames Dong* path; while on the other hand, a relatively small value helps keep
1589872a481558350634a3fd5cb67939de288af00ecbJames Dong* restoring synchronization in audio/video more frequently. Note for the
1590872a481558350634a3fd5cb67939de288af00ecbJames Dong* very first period of kVideoMediaTimeAdjustPeriodTimeUs, there is
1591872a481558350634a3fd5cb67939de288af00ecbJames Dong* no media time adjustment for the video track.
1592872a481558350634a3fd5cb67939de288af00ecbJames Dong*
1593872a481558350634a3fd5cb67939de288af00ecbJames Dong* Second, the total accumulated audio track time drift found
1594872a481558350634a3fd5cb67939de288af00ecbJames Dong* in a period of kVideoMediaTimeAdjustPeriodTimeUs is distributed
1595872a481558350634a3fd5cb67939de288af00ecbJames Dong* over a stream of incoming video frames. The number of video frames
1596872a481558350634a3fd5cb67939de288af00ecbJames Dong* affected is determined based on the number of recorded video frames
1597872a481558350634a3fd5cb67939de288af00ecbJames Dong* within the past kVideoMediaTimeAdjustPeriodTimeUs period.
1598872a481558350634a3fd5cb67939de288af00ecbJames Dong* We choose to distribute the drift time over only a portion
1599872a481558350634a3fd5cb67939de288af00ecbJames Dong* (rather than all) of the total number of recorded video frames
1600872a481558350634a3fd5cb67939de288af00ecbJames Dong* in order to make sure that the video track media time adjustment is
1601872a481558350634a3fd5cb67939de288af00ecbJames Dong* completed for the current period before the next video track media
1602872a481558350634a3fd5cb67939de288af00ecbJames Dong* time adjustment period starts. Currently, the portion chosen is a
1603872a481558350634a3fd5cb67939de288af00ecbJames Dong* half (0.5).
1604872a481558350634a3fd5cb67939de288af00ecbJames Dong*
1605872a481558350634a3fd5cb67939de288af00ecbJames Dong* Last, various additional checks are performed to ensure that
1606872a481558350634a3fd5cb67939de288af00ecbJames Dong* the actual audio encoding path does not have too much drift.
1607872a481558350634a3fd5cb67939de288af00ecbJames Dong* In particular, 1) we want to limit the average incremental time
1608872a481558350634a3fd5cb67939de288af00ecbJames Dong* adjustment for each video frame to be less than a threshold
1609872a481558350634a3fd5cb67939de288af00ecbJames Dong* for a single period of kVideoMediaTimeAdjustPeriodTimeUs.
1610872a481558350634a3fd5cb67939de288af00ecbJames Dong* Currently, the threshold is set to 5 ms. If the average incremental
1611872a481558350634a3fd5cb67939de288af00ecbJames Dong* media time adjustment for a video frame is larger than the
1612872a481558350634a3fd5cb67939de288af00ecbJames Dong* threshold, the audio encoding path has too much time drift.
1613872a481558350634a3fd5cb67939de288af00ecbJames Dong* 2) We also want to limit the total time drift in the audio
1614872a481558350634a3fd5cb67939de288af00ecbJames Dong* encoding path to be less than a threshold for a period of
1615872a481558350634a3fd5cb67939de288af00ecbJames Dong* kVideoMediaTimeAdjustPeriodTimeUs. Currently, the threshold
1616872a481558350634a3fd5cb67939de288af00ecbJames Dong* is 0.5% of kVideoMediaTimeAdjustPeriodTimeUs. If the time drift of
1617872a481558350634a3fd5cb67939de288af00ecbJames Dong* the audio encoding path is larger than the threshold, the audio
1618872a481558350634a3fd5cb67939de288af00ecbJames Dong* encoding path has too much time drift. We treat the large time
1619872a481558350634a3fd5cb67939de288af00ecbJames Dong* drift of the audio encoding path as errors, since there is no
1620872a481558350634a3fd5cb67939de288af00ecbJames Dong* way to keep audio/video in synchronization for real-time
1621872a481558350634a3fd5cb67939de288af00ecbJames Dong* applications if the time drift is too large unless we drop some
1622872a481558350634a3fd5cb67939de288af00ecbJames Dong* video frames, which has its own problems that we don't want
1623872a481558350634a3fd5cb67939de288af00ecbJames Dong* to get into for the time being.
1624872a481558350634a3fd5cb67939de288af00ecbJames Dong*/
1625872a481558350634a3fd5cb67939de288af00ecbJames Dongvoid MPEG4Writer::Track::adjustMediaTime(int64_t *timestampUs) {
1626872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (*timestampUs - mPrevMediaTimeAdjustTimestampUs >=
1627872a481558350634a3fd5cb67939de288af00ecbJames Dong        kVideoMediaTimeAdjustPeriodTimeUs) {
1628872a481558350634a3fd5cb67939de288af00ecbJames Dong
1629872a481558350634a3fd5cb67939de288af00ecbJames Dong        LOGV("New media time adjustment period at %lld us", *timestampUs);
1630872a481558350634a3fd5cb67939de288af00ecbJames Dong        mIsMediaTimeAdjustmentOn = true;
1631872a481558350634a3fd5cb67939de288af00ecbJames Dong        mMediaTimeAdjustNumFrames =
1632872a481558350634a3fd5cb67939de288af00ecbJames Dong                (mNumSamples - mPrevMediaTimeAdjustSample) >> 1;
1633872a481558350634a3fd5cb67939de288af00ecbJames Dong
1634872a481558350634a3fd5cb67939de288af00ecbJames Dong        mPrevMediaTimeAdjustTimestampUs = *timestampUs;
1635872a481558350634a3fd5cb67939de288af00ecbJames Dong        mPrevMediaTimeAdjustSample = mNumSamples;
1636872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t totalAccumDriftTimeUs = mOwner->getDriftTimeUs();
1637872a481558350634a3fd5cb67939de288af00ecbJames Dong        mTotalDriftTimeToAdjustUs =
1638872a481558350634a3fd5cb67939de288af00ecbJames Dong                totalAccumDriftTimeUs - mPrevTotalAccumDriftTimeUs;
1639872a481558350634a3fd5cb67939de288af00ecbJames Dong
1640872a481558350634a3fd5cb67939de288af00ecbJames Dong        mPrevTotalAccumDriftTimeUs = totalAccumDriftTimeUs;
1641872a481558350634a3fd5cb67939de288af00ecbJames Dong
1642872a481558350634a3fd5cb67939de288af00ecbJames Dong        // Check on incremental adjusted time per frame
1643872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t adjustTimePerFrameUs =
1644872a481558350634a3fd5cb67939de288af00ecbJames Dong                mTotalDriftTimeToAdjustUs / mMediaTimeAdjustNumFrames;
1645872a481558350634a3fd5cb67939de288af00ecbJames Dong
1646872a481558350634a3fd5cb67939de288af00ecbJames Dong        if (adjustTimePerFrameUs < 0) {
1647872a481558350634a3fd5cb67939de288af00ecbJames Dong            adjustTimePerFrameUs = -adjustTimePerFrameUs;
1648872a481558350634a3fd5cb67939de288af00ecbJames Dong        }
1649872a481558350634a3fd5cb67939de288af00ecbJames Dong        if (adjustTimePerFrameUs >= 5000) {
1650872a481558350634a3fd5cb67939de288af00ecbJames Dong            LOGE("Adjusted time per video frame is %lld us",
1651872a481558350634a3fd5cb67939de288af00ecbJames Dong                adjustTimePerFrameUs);
1652872a481558350634a3fd5cb67939de288af00ecbJames Dong            CHECK(!"Video frame time adjustment is too large!");
1653872a481558350634a3fd5cb67939de288af00ecbJames Dong        }
1654872a481558350634a3fd5cb67939de288af00ecbJames Dong
1655872a481558350634a3fd5cb67939de288af00ecbJames Dong        // Check on total accumulated time drift within a period of
1656872a481558350634a3fd5cb67939de288af00ecbJames Dong        // kVideoMediaTimeAdjustPeriodTimeUs.
1657872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t driftPercentage = (mTotalDriftTimeToAdjustUs * 1000)
1658872a481558350634a3fd5cb67939de288af00ecbJames Dong                / kVideoMediaTimeAdjustPeriodTimeUs;
1659872a481558350634a3fd5cb67939de288af00ecbJames Dong
1660872a481558350634a3fd5cb67939de288af00ecbJames Dong        if (driftPercentage < 0) {
1661872a481558350634a3fd5cb67939de288af00ecbJames Dong            driftPercentage = -driftPercentage;
1662872a481558350634a3fd5cb67939de288af00ecbJames Dong        }
1663872a481558350634a3fd5cb67939de288af00ecbJames Dong        if (driftPercentage > 5) {
1664872a481558350634a3fd5cb67939de288af00ecbJames Dong            LOGE("Audio track has time drift %lld us over %lld us",
1665872a481558350634a3fd5cb67939de288af00ecbJames Dong                mTotalDriftTimeToAdjustUs,
1666872a481558350634a3fd5cb67939de288af00ecbJames Dong                kVideoMediaTimeAdjustPeriodTimeUs);
1667872a481558350634a3fd5cb67939de288af00ecbJames Dong
1668872a481558350634a3fd5cb67939de288af00ecbJames Dong            CHECK(!"The audio track media time drifts too much!");
1669872a481558350634a3fd5cb67939de288af00ecbJames Dong        }
1670872a481558350634a3fd5cb67939de288af00ecbJames Dong
1671872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
1672872a481558350634a3fd5cb67939de288af00ecbJames Dong
1673872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (mIsMediaTimeAdjustmentOn) {
1674872a481558350634a3fd5cb67939de288af00ecbJames Dong        if (mNumSamples - mPrevMediaTimeAdjustSample <=
1675872a481558350634a3fd5cb67939de288af00ecbJames Dong            mMediaTimeAdjustNumFrames) {
1676872a481558350634a3fd5cb67939de288af00ecbJames Dong
1677872a481558350634a3fd5cb67939de288af00ecbJames Dong            // Do media time incremental adjustment
1678872a481558350634a3fd5cb67939de288af00ecbJames Dong            int64_t incrementalAdjustTimeUs =
1679872a481558350634a3fd5cb67939de288af00ecbJames Dong                        (mTotalDriftTimeToAdjustUs *
1680872a481558350634a3fd5cb67939de288af00ecbJames Dong                            (mNumSamples - mPrevMediaTimeAdjustSample))
1681872a481558350634a3fd5cb67939de288af00ecbJames Dong                                / mMediaTimeAdjustNumFrames;
1682872a481558350634a3fd5cb67939de288af00ecbJames Dong
1683872a481558350634a3fd5cb67939de288af00ecbJames Dong            *timestampUs +=
1684872a481558350634a3fd5cb67939de288af00ecbJames Dong                (incrementalAdjustTimeUs + mPrevTotalAccumDriftTimeUs);
1685872a481558350634a3fd5cb67939de288af00ecbJames Dong
1686872a481558350634a3fd5cb67939de288af00ecbJames Dong            LOGV("Incremental video frame media time adjustment: %lld us",
1687872a481558350634a3fd5cb67939de288af00ecbJames Dong                (incrementalAdjustTimeUs + mPrevTotalAccumDriftTimeUs));
1688872a481558350634a3fd5cb67939de288af00ecbJames Dong        } else {
1689872a481558350634a3fd5cb67939de288af00ecbJames Dong            // Within the remaining adjustment period,
1690872a481558350634a3fd5cb67939de288af00ecbJames Dong            // no incremental adjustment is needed.
1691872a481558350634a3fd5cb67939de288af00ecbJames Dong            *timestampUs +=
1692872a481558350634a3fd5cb67939de288af00ecbJames Dong                (mTotalDriftTimeToAdjustUs + mPrevTotalAccumDriftTimeUs);
1693872a481558350634a3fd5cb67939de288af00ecbJames Dong
1694872a481558350634a3fd5cb67939de288af00ecbJames Dong            LOGV("Fixed video frame media time adjustment: %lld us",
1695872a481558350634a3fd5cb67939de288af00ecbJames Dong                (mTotalDriftTimeToAdjustUs + mPrevTotalAccumDriftTimeUs));
1696872a481558350634a3fd5cb67939de288af00ecbJames Dong        }
1697872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
1698872a481558350634a3fd5cb67939de288af00ecbJames Dong}
1699872a481558350634a3fd5cb67939de288af00ecbJames Dong
1700872a481558350634a3fd5cb67939de288af00ecbJames Dong/*
1701872a481558350634a3fd5cb67939de288af00ecbJames Dong * Updates the drift time from the audio track so that
1702872a481558350634a3fd5cb67939de288af00ecbJames Dong * the video track can get the updated drift time information
1703872a481558350634a3fd5cb67939de288af00ecbJames Dong * from the file writer. The fluctuation of the drift time of the audio
1704872a481558350634a3fd5cb67939de288af00ecbJames Dong * encoding path is smoothed out with a simple filter by giving a larger
1705872a481558350634a3fd5cb67939de288af00ecbJames Dong * weight to more recently drift time. The filter coefficients, 0.5 and 0.5,
1706872a481558350634a3fd5cb67939de288af00ecbJames Dong * are heuristically determined.
1707872a481558350634a3fd5cb67939de288af00ecbJames Dong */
1708872a481558350634a3fd5cb67939de288af00ecbJames Dongvoid MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) {
1709872a481558350634a3fd5cb67939de288af00ecbJames Dong    int64_t driftTimeUs = 0;
1710872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) {
1711872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t prevDriftTimeUs = mOwner->getDriftTimeUs();
1712872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1;
1713872a481558350634a3fd5cb67939de288af00ecbJames Dong        mOwner->setDriftTimeUs(timeUs);
1714872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
1715872a481558350634a3fd5cb67939de288af00ecbJames Dong}
1716872a481558350634a3fd5cb67939de288af00ecbJames Dong
171737187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::threadEntry() {
171830ab66297501757d745b9ae10da61adcd891f497Andreas Huber    int32_t count = 0;
171913aec890216948b0c364f8f92792129d0335f506James Dong    const int64_t interleaveDurationUs = mOwner->interleaveDuration();
172013aec890216948b0c364f8f92792129d0335f506James Dong    int64_t chunkTimestampUs = 0;
172113aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nChunks = 0;
172213aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nZeroLengthFrames = 0;
17238f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t lastTimestampUs = 0;  // Previous sample time stamp in ms
17248f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t lastDurationUs = 0;   // Between the previous two samples in ms
1725c059860c73678a202bfa33062723e8f82fb779d9James Dong    int64_t currDurationTicks = 0;  // Timescale based ticks
1726c059860c73678a202bfa33062723e8f82fb779d9James Dong    int64_t lastDurationTicks = 0;  // Timescale based ticks
17278f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int32_t sampleCount = 1;      // Sample count in the current stts table entry
1728be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    uint32_t previousSampleSize = 0;  // Size of the previous sample
1729a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    int64_t previousPausedDurationUs = 0;
17301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    int64_t timestampUs;
1731e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
1732a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    if (mIsAudio) {
1733a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong        prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0);
1734a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    } else {
1735a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong        prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0);
1736a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    }
1737985f838934510983d8a887461e98dca60a6e858fJames Dong    setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1738985f838934510983d8a887461e98dca60a6e858fJames Dong
1739d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong    sp<MetaData> meta_data;
174020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1741ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    mNumSamples = 0;
174293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t err = OK;
174320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBuffer *buffer;
174493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    while (!mDone && (err = mSource->read(&buffer)) == OK) {
174520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (buffer->range_length() == 0) {
174620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer->release();
174720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer = NULL;
174813aec890216948b0c364f8f92792129d0335f506James Dong            ++nZeroLengthFrames;
174920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            continue;
175020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
175120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1752a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // If the codec specific data has not been received yet, delay pause.
1753a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // After the codec specific data is received, discard what we received
1754a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // when the track is to be paused.
1755a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused && !mResumed) {
1756a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer->release();
1757a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer = NULL;
1758a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            continue;
1759a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
1760a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
176130ab66297501757d745b9ae10da61adcd891f497Andreas Huber        ++count;
176230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
176303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        int32_t isCodecConfig;
176403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig)
176503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                && isCodecConfig) {
1766548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            CHECK(!mGotAllCodecSpecificData);
1767548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
17681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (mIsAvc) {
176903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                status_t err = makeAVCCodecSpecificData(
177003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        (const uint8_t *)buffer->data()
177103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                            + buffer->range_offset(),
177203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        buffer->range_length());
1773be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                CHECK_EQ(OK, err);
17741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            } else if (mIsMPEG4) {
177503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificDataSize = buffer->range_length();
177603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificData = malloc(mCodecSpecificDataSize);
177703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                memcpy(mCodecSpecificData,
177803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        (const uint8_t *)buffer->data()
177903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                            + buffer->range_offset(),
178003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                       buffer->range_length());
178130ab66297501757d745b9ae10da61adcd891f497Andreas Huber            }
178230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
178330ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer->release();
178430ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer = NULL;
178530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
1786548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            mGotAllCodecSpecificData = true;
178730ab66297501757d745b9ae10da61adcd891f497Andreas Huber            continue;
1788a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
1789a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
1790d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // Make a deep copy of the MediaBuffer and Metadata and release
1791d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // the original as soon as we can
1792d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        MediaBuffer *copy = new MediaBuffer(buffer->range_length());
1793d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(),
1794d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong                buffer->range_length());
1795d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        copy->set_range(0, buffer->range_length());
1796d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data = new MetaData(*buffer->meta_data().get());
1797d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer->release();
1798d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer = NULL;
1799d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
18001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (mIsAvc) StripStartcode(copy);
1801e136c3bb38e88315bf8797a464ebf2c788296b22James Dong
1802b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        size_t sampleSize = copy->range_length();
1803b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        if (mIsAvc) {
1804b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            if (mOwner->useNalLengthFour()) {
1805b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                sampleSize += 4;
1806b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            } else {
1807b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                sampleSize += 2;
1808b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            }
1809b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        }
1810050b28a593350047845a45a14cc5026221ac1620James Dong
1811d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        // Max file size or duration handling
18121f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mMdatSizeBytes += sampleSize;
18131f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        updateTrackSizeEstimate();
18141f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1815d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileSizeLimit()) {
1816d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
1817d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
1818d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
1819d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileDurationLimit()) {
1820d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
1821d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
1822d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
1823d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1824050b28a593350047845a45a14cc5026221ac1620James Dong
1825d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        int32_t isSync = false;
1826d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data->findInt32(kKeyIsSyncFrame, &isSync);
1827d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
18288428af5381e835cc783b7ecb0d71cb60961c99c2James Dong        /*
18298428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * The original timestamp found in the data buffer will be modified as below:
18308428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         *
18318428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * There is a playback offset into this track if the track's start time
18328428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * is not the same as the movie start time, which will be recorded in edst
18338428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * box of the output file. The playback offset is to make sure that the
18348428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * starting time of the audio/video tracks are synchronized. Although the
18358428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * track's media timestamp may be subject to various modifications
18368428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * as outlined below, the track's playback offset time remains unchanged
18378428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * once the first data buffer of the track is received.
18388428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         *
18398428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * The media time stamp will be calculated by subtracting the playback offset
18408428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * (and potential pause durations) from the original timestamp in the buffer.
18418428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         *
18428428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * If this track is a video track for a real-time recording application with
18438428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * both audio and video tracks, its media timestamp will subject to further
18448428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * modification based on the media clock of the audio track. This modification
18458428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * is needed for the purpose of maintaining good audio/video synchronization.
18468428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         *
18478428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * If the recording session is paused and resumed multiple times, the track
18488428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * media timestamp will be modified as if the  recording session had never been
18498428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * paused at all during playback of the recorded output file. In other words,
18508428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         * the output file will have no memory of pause/resume durations.
18518428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         *
18528428af5381e835cc783b7ecb0d71cb60961c99c2James Dong         */
1853d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        CHECK(meta_data->findInt64(kKeyTime, &timestampUs));
18548428af5381e835cc783b7ecb0d71cb60961c99c2James Dong        LOGV("%s timestampUs: %lld", mIsAudio? "Audio": "Video", timestampUs);
1855d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
1856d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong////////////////////////////////////////////////////////////////////////////////
18578644c14618d30d9e57a69df40ed939986ebf02c4James Dong        if (mSampleSizes.empty()) {
1858f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mStartTimestampUs = timestampUs;
1859f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mOwner->setStartTimestampUs(mStartTimestampUs);
18608428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            previousPausedDurationUs = mStartTimestampUs;
18613c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        }
186248c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber
1863a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mResumed) {
18648428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs;
18658428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            CHECK(durExcludingEarlierPausesUs >= 0);
18668428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs;
18678428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            CHECK(pausedDurationUs >= lastDurationUs);
18688428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            previousPausedDurationUs += pausedDurationUs - lastDurationUs;
1869a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mResumed = false;
1870a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
1871a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
1872a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        timestampUs -= previousPausedDurationUs;
18738428af5381e835cc783b7ecb0d71cb60961c99c2James Dong        CHECK(timestampUs >= 0);
1874872a481558350634a3fd5cb67939de288af00ecbJames Dong
1875872a481558350634a3fd5cb67939de288af00ecbJames Dong        // Media time adjustment for real-time applications
1876872a481558350634a3fd5cb67939de288af00ecbJames Dong        if (mIsRealTimeRecording) {
1877872a481558350634a3fd5cb67939de288af00ecbJames Dong            if (mIsAudio) {
1878872a481558350634a3fd5cb67939de288af00ecbJames Dong                updateDriftTime(meta_data);
1879872a481558350634a3fd5cb67939de288af00ecbJames Dong            } else {
1880872a481558350634a3fd5cb67939de288af00ecbJames Dong                adjustMediaTime(&timestampUs);
1881e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            }
1882e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        }
1883872a481558350634a3fd5cb67939de288af00ecbJames Dong
1884e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        CHECK(timestampUs >= 0);
1885e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        if (mNumSamples > 1) {
1886e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            if (timestampUs <= lastTimestampUs) {
18874f86a980fee1880dca61b828599fa6d76755a485James Dong                LOGW("Frame arrives too late!");
18884f86a980fee1880dca61b828599fa6d76755a485James Dong                // Don't drop the late frame, since dropping a frame may cause
18894f86a980fee1880dca61b828599fa6d76755a485James Dong                // problems later during playback
18904f86a980fee1880dca61b828599fa6d76755a485James Dong
18914f86a980fee1880dca61b828599fa6d76755a485James Dong                // The idea here is to avoid having two or more samples with the
18924f86a980fee1880dca61b828599fa6d76755a485James Dong                // same timestamp in the output file.
18934f86a980fee1880dca61b828599fa6d76755a485James Dong                if (mTimeScale >= 1000000LL) {
189440e9940fadf22daa64c1e766fa8a855c7b149c17James Dong                    timestampUs = lastTimestampUs + 1;
18954f86a980fee1880dca61b828599fa6d76755a485James Dong                } else {
189640e9940fadf22daa64c1e766fa8a855c7b149c17James Dong                    timestampUs = lastTimestampUs + (1000000LL + (mTimeScale >> 1)) / mTimeScale;
18974f86a980fee1880dca61b828599fa6d76755a485James Dong                }
1898e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            }
1899e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        }
1900e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
19018428af5381e835cc783b7ecb0d71cb60961c99c2James Dong        LOGV("%s media time stamp: %lld and previous paused duration %lld",
19028428af5381e835cc783b7ecb0d71cb60961c99c2James Dong                mIsAudio? "Audio": "Video", timestampUs, previousPausedDurationUs);
1903c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong        if (timestampUs > mTrackDurationUs) {
1904c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong            mTrackDurationUs = timestampUs;
19053b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber        }
19063b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber
19078644c14618d30d9e57a69df40ed939986ebf02c4James Dong        mSampleSizes.push_back(sampleSize);
1908ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong        ++mNumSamples;
1909ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong        if (mNumSamples > 2) {
1910c059860c73678a202bfa33062723e8f82fb779d9James Dong            // We need to use the time scale based ticks, rather than the
1911c059860c73678a202bfa33062723e8f82fb779d9James Dong            // timestamp itself to determine whether we have to use a new
1912c059860c73678a202bfa33062723e8f82fb779d9James Dong            // stts entry, since we may have rounding errors.
1913c059860c73678a202bfa33062723e8f82fb779d9James Dong            // The calculation is intended to reduce the accumulated
1914c059860c73678a202bfa33062723e8f82fb779d9James Dong            // rounding errors.
1915c059860c73678a202bfa33062723e8f82fb779d9James Dong            currDurationTicks =
1916c059860c73678a202bfa33062723e8f82fb779d9James Dong                     ((timestampUs * mTimeScale + 500000LL) / 1000000LL -
1917c059860c73678a202bfa33062723e8f82fb779d9James Dong                     (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL);
1918c059860c73678a202bfa33062723e8f82fb779d9James Dong
1919c059860c73678a202bfa33062723e8f82fb779d9James Dong            if (currDurationTicks != lastDurationTicks) {
19201f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                addOneSttsTableEntry(sampleCount, lastDurationUs);
1921be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                sampleCount = 1;
1922be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            } else {
1923be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                ++sampleCount;
1924be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
1925be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
1926be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        if (mSamplesHaveSameSize) {
1927ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong            if (mNumSamples >= 2 && previousSampleSize != sampleSize) {
1928be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mSamplesHaveSameSize = false;
1929be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
19308644c14618d30d9e57a69df40ed939986ebf02c4James Dong            previousSampleSize = sampleSize;
1931be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
19328644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastDurationUs = timestampUs - lastTimestampUs;
1933c059860c73678a202bfa33062723e8f82fb779d9James Dong        lastDurationTicks = currDurationTicks;
19348644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastTimestampUs = timestampUs;
193520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1936d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        if (isSync != 0) {
19371f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            addOneStssTableEntry(mNumSamples);
1938d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        }
1939d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
194093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (mTrackingProgressStatus) {
194193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            if (mPreviousTrackTimeUs <= 0) {
194293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong                mPreviousTrackTimeUs = mStartTimestampUs;
194393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            }
1944faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong            trackProgressStatus(timestampUs);
194593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
194658ae9c530247668f8af36e30d228c716c226b3d4James Dong        if (mOwner->numTracks() == 1) {
1947c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t offset = mIsAvc? mOwner->addLengthPrefixedSample_l(copy)
194858ae9c530247668f8af36e30d228c716c226b3d4James Dong                                 : mOwner->addSample_l(copy);
194958ae9c530247668f8af36e30d228c716c226b3d4James Dong            if (mChunkOffsets.empty()) {
19501f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                addChunkOffset(offset);
195158ae9c530247668f8af36e30d228c716c226b3d4James Dong            }
195258ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy->release();
195358ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy = NULL;
195458ae9c530247668f8af36e30d228c716c226b3d4James Dong            continue;
195558ae9c530247668f8af36e30d228c716c226b3d4James Dong        }
195613aec890216948b0c364f8f92792129d0335f506James Dong
195713aec890216948b0c364f8f92792129d0335f506James Dong        mChunkSamples.push_back(copy);
195813aec890216948b0c364f8f92792129d0335f506James Dong        if (interleaveDurationUs == 0) {
19591f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            addOneStscTableEntry(++nChunks, 1);
19601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            bufferChunk(timestampUs);
196113aec890216948b0c364f8f92792129d0335f506James Dong        } else {
196213aec890216948b0c364f8f92792129d0335f506James Dong            if (chunkTimestampUs == 0) {
196313aec890216948b0c364f8f92792129d0335f506James Dong                chunkTimestampUs = timestampUs;
196413aec890216948b0c364f8f92792129d0335f506James Dong            } else {
196513aec890216948b0c364f8f92792129d0335f506James Dong                if (timestampUs - chunkTimestampUs > interleaveDurationUs) {
196613aec890216948b0c364f8f92792129d0335f506James Dong                    ++nChunks;
196713aec890216948b0c364f8f92792129d0335f506James Dong                    if (nChunks == 1 ||  // First chunk
196813aec890216948b0c364f8f92792129d0335f506James Dong                        (--(mStscTableEntries.end()))->samplesPerChunk !=
196913aec890216948b0c364f8f92792129d0335f506James Dong                         mChunkSamples.size()) {
19701f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                        addOneStscTableEntry(nChunks, mChunkSamples.size());
197113aec890216948b0c364f8f92792129d0335f506James Dong                    }
19721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                    bufferChunk(timestampUs);
197313aec890216948b0c364f8f92792129d0335f506James Dong                    chunkTimestampUs = timestampUs;
197413aec890216948b0c364f8f92792129d0335f506James Dong                }
197513aec890216948b0c364f8f92792129d0335f506James Dong            }
197613aec890216948b0c364f8f92792129d0335f506James Dong        }
197713aec890216948b0c364f8f92792129d0335f506James Dong
197820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
197925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
1980a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong    if (mSampleSizes.empty() ||                      // no samples written
1981a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong        (!mIsAudio && mNumStssTableEntries == 0) ||  // no sync frames for video
1982a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong        (OK != checkCodecSpecificData())) {          // no codec specific data
1983690f546b0ee548dbfe997df36418e5302ec2d786James Dong        err = ERROR_MALFORMED;
1984f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong    }
1985faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    mOwner->trackProgressStatus(this, -1, err);
1986be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
198713aec890216948b0c364f8f92792129d0335f506James Dong    // Last chunk
198858ae9c530247668f8af36e30d228c716c226b3d4James Dong    if (mOwner->numTracks() == 1) {
19891f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        addOneStscTableEntry(1, mNumSamples);
199058ae9c530247668f8af36e30d228c716c226b3d4James Dong    } else if (!mChunkSamples.empty()) {
19911f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        addOneStscTableEntry(++nChunks, mChunkSamples.size());
19921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        bufferChunk(timestampUs);
199313aec890216948b0c364f8f92792129d0335f506James Dong    }
199413aec890216948b0c364f8f92792129d0335f506James Dong
1995be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // We don't really know how long the last frame lasts, since
1996be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // there is no frame time after it, just repeat the previous
1997be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // frame's duration.
1998ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    if (mNumSamples == 1) {
19998f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        lastDurationUs = 0;  // A single sample's duration
2000be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    } else {
2001be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        ++sampleCount;  // Count for the last sample
2002be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    }
20031f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    addOneSttsTableEntry(sampleCount, lastDurationUs);
2004c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs += lastDurationUs;
200525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = true;
20061f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    LOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s",
20071f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            count, nZeroLengthFrames, mNumSamples, mIsAudio? "audio": "video");
2008872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (mIsAudio) {
2009872a481558350634a3fd5cb67939de288af00ecbJames Dong        LOGI("Audio track drift time: %lld us", mOwner->getDriftTimeUs());
2010872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
2011365a963142093a1cd8efdcea76b5f65096a5b115James Dong
201237187916a486504acaf83bea30147eb5fbf46ae5James Dong    if (err == ERROR_END_OF_STREAM) {
201337187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
201437187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
201537187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
2016365a963142093a1cd8efdcea76b5f65096a5b115James Dong}
2017365a963142093a1cd8efdcea76b5f65096a5b115James Dong
2018faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) {
2019faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    LOGV("trackProgressStatus: %lld us", timeUs);
2020215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    if (mTrackEveryTimeDurationUs > 0 &&
2021215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) {
202293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        LOGV("Fire time tracking progress status at %lld us", timeUs);
2023faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        mOwner->trackProgressStatus(this, timeUs - mPreviousTrackTimeUs, err);
202493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        mPreviousTrackTimeUs = timeUs;
202593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
202693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
202793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
2028faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::trackProgressStatus(
2029faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        const MPEG4Writer::Track* track, int64_t timeUs, status_t err) {
2030faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    Mutex::Autolock lock(mLock);
2031faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    int32_t nTracks = mTracks.size();
2032faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    CHECK(nTracks >= 1);
2033faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    CHECK(nTracks < 64);  // Arbitrary number
2034faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
2035faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    int32_t trackNum = 0;
2036faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    CHECK(trackNum < nTracks);
2037faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    trackNum <<= 16;
2038faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
2039faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Error notification
2040faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Do not consider ERROR_END_OF_STREAM an error
2041faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (err != OK && err != ERROR_END_OF_STREAM) {
2042faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        notify(MEDIA_RECORDER_EVENT_ERROR,
2043faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               trackNum | MEDIA_RECORDER_ERROR_UNKNOWN,
2044faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
2045faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        return;
2046faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
2047faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
2048faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (timeUs == -1) {
2049faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send completion notification
2050faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        notify(MEDIA_RECORDER_EVENT_INFO,
2051faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               trackNum | MEDIA_RECORDER_INFO_COMPLETION_STATUS,
2052faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
2053faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        return;
2054faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    } else {
2055faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send progress status
2056faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        notify(MEDIA_RECORDER_EVENT_INFO,
2057faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               trackNum | MEDIA_RECORDER_INFO_PROGRESS_TIME_STATUS,
2058faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               timeUs / 1000);
2059faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
2060faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong}
2061faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
2062d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dongvoid MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) {
2063d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong    LOGV("setDriftTimeUs: %lld us", driftTimeUs);
2064e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
2065d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong    mDriftTimeUs = driftTimeUs;
2066e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
2067e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
2068e259531ce59ab1f31de5a23124b22536f6a5a767James Dongint64_t MPEG4Writer::getDriftTimeUs() {
2069e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    LOGV("getDriftTimeUs: %lld us", mDriftTimeUs);
2070e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
2071e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    return mDriftTimeUs;
2072e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
2073e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
2074b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dongbool MPEG4Writer::useNalLengthFour() {
2075b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    return mUse4ByteNalLength;
2076b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong}
2077b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong
20781c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::Track::bufferChunk(int64_t timestampUs) {
20791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("bufferChunk");
20801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
20811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Chunk chunk(this, timestampUs, mChunkSamples);
20821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mOwner->bufferChunk(chunk);
208313aec890216948b0c364f8f92792129d0335f506James Dong    mChunkSamples.clear();
208420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
208520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
20863b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const {
2087c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    return mTrackDurationUs;
208820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
208920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2090d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const {
2091d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return mEstimatedTrackSizeBytes;
2092d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
2093d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
2094690f546b0ee548dbfe997df36418e5302ec2d786James Dongstatus_t MPEG4Writer::Track::checkCodecSpecificData() const {
2095690f546b0ee548dbfe997df36418e5302ec2d786James Dong    const char *mime;
2096690f546b0ee548dbfe997df36418e5302ec2d786James Dong    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
2097690f546b0ee548dbfe997df36418e5302ec2d786James Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) ||
2098690f546b0ee548dbfe997df36418e5302ec2d786James Dong        !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) ||
2099690f546b0ee548dbfe997df36418e5302ec2d786James Dong        !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
2100690f546b0ee548dbfe997df36418e5302ec2d786James Dong        if (!mCodecSpecificData ||
2101690f546b0ee548dbfe997df36418e5302ec2d786James Dong            mCodecSpecificDataSize <= 0) {
2102a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong            LOGE("Missing codec specific data");
2103690f546b0ee548dbfe997df36418e5302ec2d786James Dong            return ERROR_MALFORMED;
2104690f546b0ee548dbfe997df36418e5302ec2d786James Dong        }
2105690f546b0ee548dbfe997df36418e5302ec2d786James Dong    } else {
2106690f546b0ee548dbfe997df36418e5302ec2d786James Dong        if (mCodecSpecificData ||
2107690f546b0ee548dbfe997df36418e5302ec2d786James Dong            mCodecSpecificDataSize > 0) {
2108a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong            LOGE("Unexepected codec specific data found");
2109690f546b0ee548dbfe997df36418e5302ec2d786James Dong            return ERROR_MALFORMED;
2110690f546b0ee548dbfe997df36418e5302ec2d786James Dong        }
2111690f546b0ee548dbfe997df36418e5302ec2d786James Dong    }
2112690f546b0ee548dbfe997df36418e5302ec2d786James Dong    return OK;
2113690f546b0ee548dbfe997df36418e5302ec2d786James Dong}
2114690f546b0ee548dbfe997df36418e5302ec2d786James Dong
21151acfe8649f8169caf2ff098c2dc2de880d9a3760James Dongvoid MPEG4Writer::Track::writeTrackHeader(
21161acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        int32_t trackID, bool use32BitOffset) {
211720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const char *mime;
211820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool success = mMeta->findCString(kKeyMIMEType, &mime);
21190c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(success);
212020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
21218f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    LOGV("%s track time scale: %d",
21221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsAudio? "Audio": "Video", mTimeScale);
21238f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
212420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    time_t now = time(NULL);
21258f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int32_t mvhdTimeScale = mOwner->getTimeScale();
21268f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t trakDurationUs = getDurationUs();
212720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
212820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOwner->beginBox("trak");
212920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
213020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->beginBox("tkhd");
21311acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        // Flags = 7 to indicate that the track is enabled, and
21321acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        // part of the presentation
21331acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        mOwner->writeInt32(0x07);          // version=0, flags=7
213420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(now);           // creation time
213520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(now);           // modification time
213620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(trackID);
213720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);             // reserved
21388f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int32_t tkhdDuration =
21398f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
21408f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        mOwner->writeInt32(tkhdDuration);  // in mvhd timescale
214120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);             // reserved
214220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);             // reserved
214320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt16(0);             // layer
214420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt16(0);             // alternate group
21451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mOwner->writeInt16(mIsAudio ? 0x100 : 0);  // volume
214620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt16(0);             // reserved
214720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
214813f6284305e4b27395a23db7882d670bdb1bcae1James Dong        mOwner->writeCompositionMatrix(mRotation);       // matrix
214920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
21501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (mIsAudio) {
215120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);
215220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);
215320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        } else {
215420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            int32_t width, height;
215520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            bool success = mMeta->findInt32(kKeyWidth, &width);
215620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            success = success && mMeta->findInt32(kKeyHeight, &height);
21570c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber            CHECK(success);
215820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2159050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->writeInt32(width << 16);   // 32-bit fixed-point value
2160050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->writeInt32(height << 16);  // 32-bit fixed-point value
216120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
216220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->endBox();  // tkhd
216320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2164f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong      int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
2165f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong      if (mStartTimestampUs != moovStartTimeUs) {
21663c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        mOwner->beginBox("edts");
21673c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong          mOwner->beginBox("elst");
21681acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong            mOwner->writeInt32(0);           // version=0, flags=0: 32-bit time
21691acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong            mOwner->writeInt32(2);           // never ends with an empty list
21708f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
21718f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            // First elst entry: specify the starting time offset
21728f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            int64_t offsetUs = mStartTimestampUs - moovStartTimeUs;
21738428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            LOGV("OffsetUs: %lld", offsetUs);
21748f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            int32_t seg = (offsetUs * mvhdTimeScale + 5E5) / 1E6;
21758f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            mOwner->writeInt32(seg);         // in mvhd timecale
21768f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            mOwner->writeInt32(-1);          // starting time offset
21778f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            mOwner->writeInt32(1 << 16);     // rate = 1.0
21788f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
21798f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            // Second elst entry: specify the track duration
21808f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            seg = (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
21818f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            mOwner->writeInt32(seg);         // in mvhd timescale
21821acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong            mOwner->writeInt32(0);
21831acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong            mOwner->writeInt32(1 << 16);
21843c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong          mOwner->endBox();
21853c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        mOwner->endBox();
21863c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong      }
21873c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
218820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->beginBox("mdia");
218920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
219020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("mdhd");
219120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // version=0, flags=0
219220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(now);           // creation time
219320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(now);           // modification time
21948f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong          mOwner->writeInt32(mTimeScale);    // media timescale
21958f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong          int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6;
21968f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong          mOwner->writeInt32(mdhdDuration);  // use media timescale
21971acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // Language follows the three letter standard ISO-639-2/T
21981acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // 'e', 'n', 'g' for "English", for instance.
21991acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // Each character is packed as the difference between its ASCII value and 0x60.
22001acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // For "English", these are 00101, 01110, 00111.
22011acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // XXX: Where is the padding bit located: 0x15C7?
22021acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          mOwner->writeInt16(0);             // language code
220320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt16(0);             // predefined
220420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->endBox();
220520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
220620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("hdlr");
220720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // version=0, flags=0
2208050b28a593350047845a45a14cc5026221ac1620James Dong          mOwner->writeInt32(0);             // component type: should be mhlr
22091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong          mOwner->writeFourcc(mIsAudio ? "soun" : "vide");  // component subtype
221020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // reserved
221120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // reserved
221220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // reserved
22131acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // Removing "r" for the name string just makes the string 4 byte aligned
22141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong          mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle");  // name
221520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->endBox();
221620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
221720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("minf");
22181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong          if (mIsAudio) {
221920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->beginBox("smhd");
222020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt32(0);           // version=0, flags=0
222120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // balance
222220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // reserved
222320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->endBox();
222420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          } else {
222520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->beginBox("vmhd");
22261acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong              mOwner->writeInt32(0x01);        // version=0, flags=1
222720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // graphics mode
222820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // opcolor
222920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);
223020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);
223120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->endBox();
223220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          }
2233050b28a593350047845a45a14cc5026221ac1620James Dong
2234050b28a593350047845a45a14cc5026221ac1620James Dong          mOwner->beginBox("dinf");
2235050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->beginBox("dref");
2236050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->writeInt32(0);  // version=0, flags=0
22371acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong              mOwner->writeInt32(1);  // entry count (either url or urn)
22381acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong              // The table index here refers to the sample description index
22391acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong              // in the sample table entries.
2240050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->beginBox("url ");
22411acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                mOwner->writeInt32(1);  // version=0, flags=1 (self-contained)
2242050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->endBox();  // url
2243050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->endBox();  // dref
2244050b28a593350047845a45a14cc5026221ac1620James Dong          mOwner->endBox();  // dinf
2245050b28a593350047845a45a14cc5026221ac1620James Dong
224620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("stbl");
224720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
224820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stsd");
224920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);               // version=0, flags=0
225020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(1);               // entry count
22511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (mIsAudio) {
225225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                const char *fourcc = NULL;
225318291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) {
225425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    fourcc = "samr";
225518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
225625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    fourcc = "sawb";
2257050b28a593350047845a45a14cc5026221ac1620James Dong                } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
2258050b28a593350047845a45a14cc5026221ac1620James Dong                    fourcc = "mp4a";
225925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                } else {
226025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    LOGE("Unknown mime type '%s'.", mime);
226125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    CHECK(!"should not be here, unknown mime type.");
226225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                }
226325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
226425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                mOwner->beginBox(fourcc);          // audio format
226520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
226620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
2267050b28a593350047845a45a14cc5026221ac1620James Dong                  mOwner->writeInt16(0x1);         // data ref index
226820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
226920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
2270050b28a593350047845a45a14cc5026221ac1620James Dong                  int32_t nChannels;
2271050b28a593350047845a45a14cc5026221ac1620James Dong                  CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels));
2272050b28a593350047845a45a14cc5026221ac1620James Dong                  mOwner->writeInt16(nChannels);   // channel count
227320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(16);          // sample size
227420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // predefined
227520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
227620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
227720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  int32_t samplerate;
227820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  bool success = mMeta->findInt32(kKeySampleRate, &samplerate);
22790c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                  CHECK(success);
228020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(samplerate << 16);
2281050b28a593350047845a45a14cc5026221ac1620James Dong                  if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
2282050b28a593350047845a45a14cc5026221ac1620James Dong                    mOwner->beginBox("esds");
228351dfe6d646ddcc5fc252aa4c19c9936d32af8ad7James Dong                        CHECK(mCodecSpecificData);
228451dfe6d646ddcc5fc252aa4c19c9936d32af8ad7James Dong                        CHECK(mCodecSpecificDataSize > 0);
2285050b28a593350047845a45a14cc5026221ac1620James Dong
22865f995b0e72ed6f186cb0ab2a525c4cfce614f3a9Andreas Huber                        // Make sure all sizes encode to a single byte.
22875f995b0e72ed6f186cb0ab2a525c4cfce614f3a9Andreas Huber                        CHECK(mCodecSpecificDataSize + 23 < 128);
22885f995b0e72ed6f186cb0ab2a525c4cfce614f3a9Andreas Huber
2289050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt32(0);     // version=0, flags=0
2290050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x03);   // ES_DescrTag
2291050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(23 + mCodecSpecificDataSize);
2292050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt16(0x0000);// ES_ID
2293050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x00);
2294050b28a593350047845a45a14cc5026221ac1620James Dong
2295050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x04);   // DecoderConfigDescrTag
2296050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(15 + mCodecSpecificDataSize);
2297050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x40);   // objectTypeIndication ISO/IEC 14492-2
2298050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x15);   // streamType AudioStream
2299050b28a593350047845a45a14cc5026221ac1620James Dong
2300050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt16(0x03);  // XXX
2301050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x00);   // buffer size 24-bit
2302050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt32(96000); // max bit rate
2303050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt32(96000); // avg bit rate
2304050b28a593350047845a45a14cc5026221ac1620James Dong
2305050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x05);   // DecoderSpecificInfoTag
2306050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(mCodecSpecificDataSize);
2307050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
2308050b28a593350047845a45a14cc5026221ac1620James Dong
2309050b28a593350047845a45a14cc5026221ac1620James Dong                        static const uint8_t kData2[] = {
2310050b28a593350047845a45a14cc5026221ac1620James Dong                            0x06,  // SLConfigDescriptorTag
2311050b28a593350047845a45a14cc5026221ac1620James Dong                            0x01,
2312050b28a593350047845a45a14cc5026221ac1620James Dong                            0x02
2313050b28a593350047845a45a14cc5026221ac1620James Dong                        };
2314050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->write(kData2, sizeof(kData2));
2315050b28a593350047845a45a14cc5026221ac1620James Dong
2316050b28a593350047845a45a14cc5026221ac1620James Dong                    mOwner->endBox();  // esds
23175aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                  } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) ||
23185aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                             !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
23195aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                    // 3gpp2 Spec AMRSampleEntry fields
23205aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                    mOwner->beginBox("damr");
23215aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                      mOwner->writeCString("   ");  // vendor: 4 bytes
23225aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                      mOwner->writeInt8(0);         // decoder version
23235aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                      mOwner->writeInt16(0x83FF);   // mode set: all enabled
23245aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                      mOwner->writeInt8(0);         // mode change period
23255aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                      mOwner->writeInt8(1);         // frames per sample
23265aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                    mOwner->endBox();
2327050b28a593350047845a45a14cc5026221ac1620James Dong                  }
232820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mOwner->endBox();
232920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
233018291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
233120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    mOwner->beginBox("mp4v");
233218291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
233320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    mOwner->beginBox("s263");
233430ab66297501757d745b9ae10da61adcd891f497Andreas Huber                } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
233530ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    mOwner->beginBox("avc1");
233620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                } else {
233725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    LOGE("Unknown mime type '%s'.", mime);
23380c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                    CHECK(!"should not be here, unknown mime type.");
233920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
234020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
234120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
234220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
23431acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                  mOwner->writeInt16(1);           // data ref index
234420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // predefined
234520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
234620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // predefined
234720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // predefined
234820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // predefined
234920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
235020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  int32_t width, height;
235120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  bool success = mMeta->findInt32(kKeyWidth, &width);
235220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  success = success && mMeta->findInt32(kKeyHeight, &height);
23530c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                  CHECK(success);
235420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
235520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(width);
235620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(height);
235720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0x480000);    // horiz resolution
235820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0x480000);    // vert resolution
235920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
236020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(1);           // frame count
236120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->write("                                ", 32);
236220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0x18);        // depth
236320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(-1);          // predefined
236420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
23650c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                  CHECK(23 + mCodecSpecificDataSize < 128);
236620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
236718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                  if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
2368a37923e9a57d489e7bed2129369219039fa5f12cJames Dong                      CHECK(mCodecSpecificData);
2369a37923e9a57d489e7bed2129369219039fa5f12cJames Dong                      CHECK(mCodecSpecificDataSize > 0);
237020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->beginBox("esds");
237120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
237220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt32(0);           // version=0, flags=0
237320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
237420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x03);  // ES_DescrTag
237520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(23 + mCodecSpecificDataSize);
237620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt16(0x0000);  // ES_ID
237720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x1f);
237820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
237920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x04);  // DecoderConfigDescrTag
238020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(15 + mCodecSpecificDataSize);
238120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x20);  // objectTypeIndication ISO/IEC 14492-2
238220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x11);  // streamType VisualStream
238320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
238420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        static const uint8_t kData[] = {
238520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x01, 0x77, 0x00,
238620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x00, 0x03, 0xe8, 0x00,
238720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x00, 0x03, 0xe8, 0x00
238820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        };
238920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->write(kData, sizeof(kData));
2390050b28a593350047845a45a14cc5026221ac1620James Dong
239120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x05);  // DecoderSpecificInfoTag
239220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
239320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(mCodecSpecificDataSize);
239420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
239520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
239620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        static const uint8_t kData2[] = {
239720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x06,  // SLConfigDescriptorTag
239820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x01,
239920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x02
240020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        };
240120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->write(kData2, sizeof(kData2));
240220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
240320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->endBox();  // esds
240418291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                  } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
240520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->beginBox("d263");
240620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
240720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt32(0);  // vendor
240820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt8(0);   // decoder version
240920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt8(10);  // level: 10
241020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt8(0);   // profile: 0
241120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
241220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->endBox();  // d263
241330ab66297501757d745b9ae10da61adcd891f497Andreas Huber                  } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
241451dfe6d646ddcc5fc252aa4c19c9936d32af8ad7James Dong                      CHECK(mCodecSpecificData);
241595fcef25b48e35b625899288971ab628efbf8584Andreas Huber                      CHECK(mCodecSpecificDataSize >= 5);
241695fcef25b48e35b625899288971ab628efbf8584Andreas Huber
241795fcef25b48e35b625899288971ab628efbf8584Andreas Huber                      // Patch avcc's lengthSize field to match the number
241895fcef25b48e35b625899288971ab628efbf8584Andreas Huber                      // of bytes we use to indicate the size of a nal unit.
241995fcef25b48e35b625899288971ab628efbf8584Andreas Huber                      uint8_t *ptr = (uint8_t *)mCodecSpecificData;
242095fcef25b48e35b625899288971ab628efbf8584Andreas Huber                      ptr[4] =
242195fcef25b48e35b625899288971ab628efbf8584Andreas Huber                          (ptr[4] & 0xfc)
242295fcef25b48e35b625899288971ab628efbf8584Andreas Huber                            | (mOwner->useNalLengthFour() ? 3 : 1);
242395fcef25b48e35b625899288971ab628efbf8584Andreas Huber
242430ab66297501757d745b9ae10da61adcd891f497Andreas Huber                      mOwner->beginBox("avcC");
242530ab66297501757d745b9ae10da61adcd891f497Andreas Huber                        mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
242630ab66297501757d745b9ae10da61adcd891f497Andreas Huber                      mOwner->endBox();  // avcC
242720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  }
242830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
24291acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                  mOwner->beginBox("pasp");
24301acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                    // This is useful if the pixel is not square
24311acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                    mOwner->writeInt32(1 << 16);  // hspacing
24321acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                    mOwner->writeInt32(1 << 16);  // vspacing
24331acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                  mOwner->endBox();  // pasp
243430ab66297501757d745b9ae10da61adcd891f497Andreas Huber                mOwner->endBox();  // mp4v, s263 or avc1
243520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
243620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stsd
243720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
243820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stts");
243920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
24401f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            mOwner->writeInt32(mNumSttsTableEntries);
2441c059860c73678a202bfa33062723e8f82fb779d9James Dong            int64_t prevTimestampUs = 0;
2442be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin();
2443be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                 it != mSttsTableEntries.end(); ++it) {
2444be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mOwner->writeInt32(it->sampleCount);
2445c059860c73678a202bfa33062723e8f82fb779d9James Dong
2446c059860c73678a202bfa33062723e8f82fb779d9James Dong                // Make sure that we are calculating the sample duration the exactly
2447c059860c73678a202bfa33062723e8f82fb779d9James Dong                // same way as we made decision on how to create stts entries.
2448c059860c73678a202bfa33062723e8f82fb779d9James Dong                int64_t currTimestampUs = prevTimestampUs + it->sampleDurationUs;
2449c059860c73678a202bfa33062723e8f82fb779d9James Dong                int32_t dur = ((currTimestampUs * mTimeScale + 500000LL) / 1000000LL -
2450c059860c73678a202bfa33062723e8f82fb779d9James Dong                               (prevTimestampUs * mTimeScale + 500000LL) / 1000000LL);
2451c059860c73678a202bfa33062723e8f82fb779d9James Dong                prevTimestampUs += (it->sampleCount * it->sampleDurationUs);
2452c059860c73678a202bfa33062723e8f82fb779d9James Dong
24538f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong                mOwner->writeInt32(dur);
245420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
245520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stts
245620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
24571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong          if (!mIsAudio) {
2458050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->beginBox("stss");
2459050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->writeInt32(0);  // version=0, flags=0
24601f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong              mOwner->writeInt32(mNumStssTableEntries);  // number of sync frames
2461050b28a593350047845a45a14cc5026221ac1620James Dong              for (List<int32_t>::iterator it = mStssTableEntries.begin();
2462050b28a593350047845a45a14cc5026221ac1620James Dong                   it != mStssTableEntries.end(); ++it) {
2463050b28a593350047845a45a14cc5026221ac1620James Dong                  mOwner->writeInt32(*it);
2464050b28a593350047845a45a14cc5026221ac1620James Dong              }
2465050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->endBox();  // stss
2466050b28a593350047845a45a14cc5026221ac1620James Dong          }
2467050b28a593350047845a45a14cc5026221ac1620James Dong
246820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stsz");
246920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
2470be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            if (mSamplesHaveSameSize) {
24718644c14618d30d9e57a69df40ed939986ebf02c4James Dong                List<size_t>::iterator it = mSampleSizes.begin();
24728644c14618d30d9e57a69df40ed939986ebf02c4James Dong                mOwner->writeInt32(*it);  // default sample size
2473be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            } else {
2474be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mOwner->writeInt32(0);
2475be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
2476ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong            mOwner->writeInt32(mNumSamples);
2477be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            if (!mSamplesHaveSameSize) {
24788644c14618d30d9e57a69df40ed939986ebf02c4James Dong                for (List<size_t>::iterator it = mSampleSizes.begin();
24798644c14618d30d9e57a69df40ed939986ebf02c4James Dong                     it != mSampleSizes.end(); ++it) {
24808644c14618d30d9e57a69df40ed939986ebf02c4James Dong                    mOwner->writeInt32(*it);
2481be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                }
248220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
248320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stsz
248420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
248520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stsc");
248620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
24871f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            mOwner->writeInt32(mNumStscTableEntries);
248813aec890216948b0c364f8f92792129d0335f506James Dong            for (List<StscTableEntry>::iterator it = mStscTableEntries.begin();
248913aec890216948b0c364f8f92792129d0335f506James Dong                 it != mStscTableEntries.end(); ++it) {
249013aec890216948b0c364f8f92792129d0335f506James Dong                mOwner->writeInt32(it->firstChunk);
249113aec890216948b0c364f8f92792129d0335f506James Dong                mOwner->writeInt32(it->samplesPerChunk);
249213aec890216948b0c364f8f92792129d0335f506James Dong                mOwner->writeInt32(it->sampleDescriptionId);
249320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
249420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stsc
24951acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          mOwner->beginBox(use32BitOffset? "stco": "co64");
249620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
24971f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            mOwner->writeInt32(mNumStcoTableEntries);
2498c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            for (List<off64_t>::iterator it = mChunkOffsets.begin();
249913aec890216948b0c364f8f92792129d0335f506James Dong                 it != mChunkOffsets.end(); ++it) {
25001acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                if (use32BitOffset) {
25011acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                    mOwner->writeInt32(static_cast<int32_t>(*it));
25021acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                } else {
25031acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                    mOwner->writeInt64((*it));
25041acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                }
250520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
25068f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong          mOwner->endBox();  // stco or co64
250720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
250820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->endBox();  // stbl
25091acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong       mOwner->endBox();  // minf
251020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->endBox();  // mdia
251120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOwner->endBox();  // trak
251220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
251320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
251420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
2515