MPEG4Writer.cpp revision c059860c73678a202bfa33062723e8f82fb779d9
120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber/*
220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Copyright (C) 2009 The Android Open Source Project
320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * you may not use this file except in compliance with the License.
620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * You may obtain a copy of the License at
720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
1020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Unless required by applicable law or agreed to in writing, software
1120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
1220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * See the License for the specific language governing permissions and
1420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * limitations under the License.
1520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber */
1620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
17050b28a593350047845a45a14cc5026221ac1620James Dong//#define LOG_NDEBUG 0
18050b28a593350047845a45a14cc5026221ac1620James Dong#define LOG_TAG "MPEG4Writer"
19050b28a593350047845a45a14cc5026221ac1620James Dong#include <utils/Log.h>
20050b28a593350047845a45a14cc5026221ac1620James Dong
2120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <arpa/inet.h>
2220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <ctype.h>
2420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <pthread.h>
2520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MPEG4Writer.h>
2720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBuffer.h>
2820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h>
290c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber#include <media/stagefright/MediaDebug.h>
3018291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h>
3103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#include <media/stagefright/MediaErrors.h>
3220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaSource.h>
3320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/Utils.h>
34d599cd4573b5a2d5914c5040e0565ef866749b77James Dong#include <media/mediarecorder.h>
35365a963142093a1cd8efdcea76b5f65096a5b115James Dong#include <cutils/properties.h>
3620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber#include "include/ESDS.h"
3819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
3920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android {
4020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypeSeqParamSet = 0x07;
423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypePicParamSet = 0x08;
433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
4420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Writer::Track {
4520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic:
4625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    Track(MPEG4Writer *owner, const sp<MediaSource> &source);
478f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
4820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    ~Track();
4920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t start(MetaData *params);
5120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void stop();
52a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    void pause();
5325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool reachedEOS();
5420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
553b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber    int64_t getDurationUs() const;
56d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t getEstimatedTrackSizeBytes() const;
571acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    void writeTrackHeader(int32_t trackID, bool use32BitOffset = true);
581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void bufferChunk(int64_t timestampUs);
591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isAvc() const { return mIsAvc; }
601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isAudio() const { return mIsAudio; }
611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isMPEG4() const { return mIsMPEG4; }
621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void addChunkOffset(off_t offset) { mChunkOffsets.push_back(offset); }
6320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate:
6520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Writer *mOwner;
6620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MetaData> mMeta;
67693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    sp<MediaSource> mSource;
6820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    volatile bool mDone;
69a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mPaused;
70a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mResumed;
711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAvc;
721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAudio;
731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsMPEG4;
74c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    int64_t mTrackDurationUs;
75e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
76e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    // For realtime applications, we need to adjust the media clock
77e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    // for video track based on the audio media clock
78e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    bool mIsRealTimeRecording;
79e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    int64_t mMaxTimeStampUs;
80d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t mEstimatedTrackSizeBytes;
811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    int64_t mMaxWriteTimeUs;
828f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int32_t mTimeScale;
8320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_t mThread;
8520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
86ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    // mNumSamples is used to track how many samples in mSampleSizes List.
87ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    // This is to reduce the cost associated with mSampleSizes.size() call,
88ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    // since it is O(n). Ideally, the fix should be in List class.
89ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    size_t              mNumSamples;
908644c14618d30d9e57a69df40ed939986ebf02c4James Dong    List<size_t>        mSampleSizes;
91be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    bool                mSamplesHaveSameSize;
92be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
9313aec890216948b0c364f8f92792129d0335f506James Dong    List<MediaBuffer *> mChunkSamples;
9413aec890216948b0c364f8f92792129d0335f506James Dong    List<off_t>         mChunkOffsets;
9513aec890216948b0c364f8f92792129d0335f506James Dong
9613aec890216948b0c364f8f92792129d0335f506James Dong    struct StscTableEntry {
9713aec890216948b0c364f8f92792129d0335f506James Dong
9813aec890216948b0c364f8f92792129d0335f506James Dong        StscTableEntry(uint32_t chunk, uint32_t samples, uint32_t id)
9913aec890216948b0c364f8f92792129d0335f506James Dong            : firstChunk(chunk),
10013aec890216948b0c364f8f92792129d0335f506James Dong              samplesPerChunk(samples),
10113aec890216948b0c364f8f92792129d0335f506James Dong              sampleDescriptionId(id) {}
10213aec890216948b0c364f8f92792129d0335f506James Dong
10313aec890216948b0c364f8f92792129d0335f506James Dong        uint32_t firstChunk;
10413aec890216948b0c364f8f92792129d0335f506James Dong        uint32_t samplesPerChunk;
10513aec890216948b0c364f8f92792129d0335f506James Dong        uint32_t sampleDescriptionId;
10613aec890216948b0c364f8f92792129d0335f506James Dong    };
10713aec890216948b0c364f8f92792129d0335f506James Dong    List<StscTableEntry> mStscTableEntries;
10820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
109050b28a593350047845a45a14cc5026221ac1620James Dong    List<int32_t> mStssTableEntries;
110365a963142093a1cd8efdcea76b5f65096a5b115James Dong    List<int64_t> mChunkDurations;
111050b28a593350047845a45a14cc5026221ac1620James Dong
112be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    struct SttsTableEntry {
113be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
1148f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        SttsTableEntry(uint32_t count, uint32_t durationUs)
1158f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            : sampleCount(count), sampleDurationUs(durationUs) {}
116be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
117be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        uint32_t sampleCount;
1188f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        uint32_t sampleDurationUs;
119be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    };
120be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    List<SttsTableEntry> mSttsTableEntries;
121be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
1223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Sequence parameter set or picture parameter set
1233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    struct AVCParamSet {
1243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        AVCParamSet(uint16_t length, const uint8_t *data)
1253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            : mLength(length), mData(data) {}
1263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
1273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t mLength;
1283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *mData;
1293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    };
1303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    List<AVCParamSet> mSeqParamSets;
1313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    List<AVCParamSet> mPicParamSets;
1323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mProfileIdc;
1333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mProfileCompatible;
1343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mLevelIdc;
1353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *mCodecSpecificData;
13720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t mCodecSpecificDataSize;
138548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    bool mGotAllCodecSpecificData;
13993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    bool mTrackingProgressStatus;
14020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool mReachedEOS;
1423c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    int64_t mStartTimestampUs;
14393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mPreviousTrackTimeUs;
14493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mTrackEveryTimeDurationUs;
14525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
14620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    static void *ThreadWrapper(void *me);
14720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void threadEntry();
14820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *parseParamSet(
1503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen);
1513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
15203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    status_t makeAVCCodecSpecificData(
15303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            const uint8_t *data, size_t size);
1543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    status_t copyAVCCodecSpecificData(
1553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            const uint8_t *data, size_t size);
1563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    status_t parseAVCCodecSpecificData(
1573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            const uint8_t *data, size_t size);
158215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong
159215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    // Track authoring progress status
160faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    void trackProgressStatus(int64_t timeUs, status_t err = OK);
16193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    void initTrackingProgressStatus(MetaData *params);
16203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
163215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    // Utilities for collecting statistical data
164215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    void logStatisticalData(bool isAudio);
165215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    void findMinAvgMaxSampleDurationMs(
166215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong            int32_t *min, int32_t *avg, int32_t *max);
167215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    void findMinMaxChunkDurations(int64_t *min, int64_t *max);
168215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong
16919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    void getCodecSpecificDataFromInputFormatIfPossible();
17019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
171c059860c73678a202bfa33062723e8f82fb779d9James Dong    // Determine the track time scale
172c059860c73678a202bfa33062723e8f82fb779d9James Dong    // If it is an audio track, try to use the sampling rate as
173c059860c73678a202bfa33062723e8f82fb779d9James Dong    // the time scale; however, if user chooses the overwrite
174c059860c73678a202bfa33062723e8f82fb779d9James Dong    // value, the user-supplied time scale will be used.
175c059860c73678a202bfa33062723e8f82fb779d9James Dong    void setTimeScale();
176c059860c73678a202bfa33062723e8f82fb779d9James Dong
17720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track(const Track &);
17820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track &operator=(const Track &);
17920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
18020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
18103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#define USE_NALLEN_FOUR         1
18203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
18320111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::MPEG4Writer(const char *filename)
18420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mFile(fopen(filename, "wb")),
1851acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong      mUse32BitOffset(true),
186a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
187a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mStarted(false),
18820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOffset(0),
18913aec890216948b0c364f8f92792129d0335f506James Dong      mMdatOffset(0),
1907837c17063a4c50bc856ba59418516fdab731de7James Dong      mEstimatedMoovBoxSize(0),
191f01528f435e6b1f02d118fcd8305a148c27a89f1James Dong      mInterleaveDurationUs(1000000) {
1920c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(mFile != NULL);
19320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
19420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
19530ab66297501757d745b9ae10da61adcd891f497Andreas HuberMPEG4Writer::MPEG4Writer(int fd)
19630ab66297501757d745b9ae10da61adcd891f497Andreas Huber    : mFile(fdopen(fd, "wb")),
1971acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong      mUse32BitOffset(true),
198a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
199a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mStarted(false),
20030ab66297501757d745b9ae10da61adcd891f497Andreas Huber      mOffset(0),
20113aec890216948b0c364f8f92792129d0335f506James Dong      mMdatOffset(0),
2027837c17063a4c50bc856ba59418516fdab731de7James Dong      mEstimatedMoovBoxSize(0),
203f01528f435e6b1f02d118fcd8305a148c27a89f1James Dong      mInterleaveDurationUs(1000000) {
20430ab66297501757d745b9ae10da61adcd891f497Andreas Huber    CHECK(mFile != NULL);
20530ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
20630ab66297501757d745b9ae10da61adcd891f497Andreas Huber
20720111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() {
20820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    stop();
20920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
21020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
21120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber         it != mTracks.end(); ++it) {
21220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        delete *it;
21320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
21420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.clear();
21520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
21620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2172dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huberstatus_t MPEG4Writer::addSource(const sp<MediaSource> &source) {
21825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    Track *track = new Track(this, source);
21920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.push_back(track);
2202dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
2212dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    return OK;
22220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
22320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
22493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::startTracks(MetaData *params) {
225a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
226a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
22793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        status_t err = (*it)->start(params);
228a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
229a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (err != OK) {
230a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            for (List<Track *>::iterator it2 = mTracks.begin();
231a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                 it2 != it; ++it2) {
232a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                (*it2)->stop();
233a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            }
234a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
235a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            return err;
236a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
237a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
238a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    return OK;
239a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
240a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
2412dec2b5be2056c6d9428897dc672185872d30d17James Dongint64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) {
2422dec2b5be2056c6d9428897dc672185872d30d17James Dong    // This implementation is highly experimental/heurisitic.
2432dec2b5be2056c6d9428897dc672185872d30d17James Dong    //
2442dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Statistical analysis shows that metadata usually accounts
2452dec2b5be2056c6d9428897dc672185872d30d17James Dong    // for a small portion of the total file size, usually < 0.6%.
2462dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Currently, lets set to 0.4% for now.
2472dec2b5be2056c6d9428897dc672185872d30d17James Dong
2482dec2b5be2056c6d9428897dc672185872d30d17James Dong    // The default MIN_MOOV_BOX_SIZE is set to 0.4% x 1MB,
2492dec2b5be2056c6d9428897dc672185872d30d17James Dong    // where 1MB is the common file size limit for MMS application.
2502dec2b5be2056c6d9428897dc672185872d30d17James Dong    // The default MAX _MOOV_BOX_SIZE value is based on about 4
2512dec2b5be2056c6d9428897dc672185872d30d17James Dong    // minute video recording with a bit rate about 3 Mbps, because
2522dec2b5be2056c6d9428897dc672185872d30d17James Dong    // statistics also show that most of the video captured are going
2532dec2b5be2056c6d9428897dc672185872d30d17James Dong    // to be less than 3 minutes.
2542dec2b5be2056c6d9428897dc672185872d30d17James Dong
2552dec2b5be2056c6d9428897dc672185872d30d17James Dong    // If the estimation is wrong, we will pay the price of wasting
2562dec2b5be2056c6d9428897dc672185872d30d17James Dong    // some reserved space. This should not happen so often statistically.
2572dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int32_t factor = mUse32BitOffset? 1: 2;
2582dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int64_t MIN_MOOV_BOX_SIZE = 4 * 1024;  // 4 KB
2592dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000);
2602dec2b5be2056c6d9428897dc672185872d30d17James Dong    int64_t size = MIN_MOOV_BOX_SIZE;
2612dec2b5be2056c6d9428897dc672185872d30d17James Dong
2622dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (mMaxFileSizeLimitBytes != 0) {
2632dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = mMaxFileSizeLimitBytes * 4 / 1000;
2642dec2b5be2056c6d9428897dc672185872d30d17James Dong    } else if (mMaxFileDurationLimitUs != 0) {
2652dec2b5be2056c6d9428897dc672185872d30d17James Dong        if (bitRate <= 0) {
2662dec2b5be2056c6d9428897dc672185872d30d17James Dong            // We could not estimate the file size since bitRate is not set.
2672dec2b5be2056c6d9428897dc672185872d30d17James Dong            size = MIN_MOOV_BOX_SIZE;
2682dec2b5be2056c6d9428897dc672185872d30d17James Dong        } else {
2692dec2b5be2056c6d9428897dc672185872d30d17James Dong            size = ((mMaxFileDurationLimitUs * bitRate * 4) / 1000 / 8000000);
2702dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
2712dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
2722dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size < MIN_MOOV_BOX_SIZE) {
2732dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MIN_MOOV_BOX_SIZE;
2742dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
2752dec2b5be2056c6d9428897dc672185872d30d17James Dong
2762dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Any long duration recording will be probably end up with
2772dec2b5be2056c6d9428897dc672185872d30d17James Dong    // non-streamable mp4 file.
2782dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size > MAX_MOOV_BOX_SIZE) {
2792dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MAX_MOOV_BOX_SIZE;
2802dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
2812dec2b5be2056c6d9428897dc672185872d30d17James Dong
2822dec2b5be2056c6d9428897dc672185872d30d17James Dong    LOGI("limits: %lld/%lld bytes/us, bit rate: %d bps and the estimated"
2832dec2b5be2056c6d9428897dc672185872d30d17James Dong         " moov size %lld bytes",
2842dec2b5be2056c6d9428897dc672185872d30d17James Dong         mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size);
2852dec2b5be2056c6d9428897dc672185872d30d17James Dong    return factor * size;
2862dec2b5be2056c6d9428897dc672185872d30d17James Dong}
2872dec2b5be2056c6d9428897dc672185872d30d17James Dong
2882dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t MPEG4Writer::start(MetaData *param) {
28920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mFile == NULL) {
29025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return UNKNOWN_ERROR;
29120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
29220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2932dec2b5be2056c6d9428897dc672185872d30d17James Dong    int32_t use64BitOffset;
2942dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (param &&
2952dec2b5be2056c6d9428897dc672185872d30d17James Dong        param->findInt32(kKey64BitFileOffset, &use64BitOffset) &&
2962dec2b5be2056c6d9428897dc672185872d30d17James Dong        use64BitOffset) {
2972dec2b5be2056c6d9428897dc672185872d30d17James Dong        mUse32BitOffset = false;
2982dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
2992dec2b5be2056c6d9428897dc672185872d30d17James Dong
3002dec2b5be2056c6d9428897dc672185872d30d17James Dong    // System property can overwrite the file offset bits parameter
3012dec2b5be2056c6d9428897dc672185872d30d17James Dong    char value[PROPERTY_VALUE_MAX];
3022dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (property_get("media.stagefright.record-64bits", value, NULL)
3032dec2b5be2056c6d9428897dc672185872d30d17James Dong        && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
3042dec2b5be2056c6d9428897dc672185872d30d17James Dong        mUse32BitOffset = false;
3052dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
3062dec2b5be2056c6d9428897dc672185872d30d17James Dong
307065d1aff96818df54456053f1574aec8a234d0deJames Dong    mStartTimestampUs = -1;
30893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
309a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (mStarted) {
310a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused) {
311a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mPaused = false;
31293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            return startTracks(param);
313a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
314a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
315a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
316a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
3178f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    if (!param ||
3188f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        !param->findInt32(kKeyTimeScale, &mTimeScale)) {
3198f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        mTimeScale = 1000;
3208f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    }
3218f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    CHECK(mTimeScale > 0);
3228f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    LOGV("movie time scale: %d", mTimeScale);
3238f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
3247837c17063a4c50bc856ba59418516fdab731de7James Dong    mStreamableFile = true;
3257837c17063a4c50bc856ba59418516fdab731de7James Dong    mWriteMoovBoxToMemory = false;
3267837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBuffer = NULL;
3277837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
3287837c17063a4c50bc856ba59418516fdab731de7James Dong
32920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    beginBox("ftyp");
33093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong      {
33193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        int32_t fileType;
33293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (param && param->findInt32(kKeyFileType, &fileType) &&
33393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            fileType != OUTPUT_FORMAT_MPEG_4) {
33493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            writeFourcc("3gp4");
33593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        } else {
33693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            writeFourcc("isom");
33793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
33893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong      }
33920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      writeInt32(0);
34020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      writeFourcc("isom");
34193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong      writeFourcc("3gp4");
34220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    endBox();
34320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3447837c17063a4c50bc856ba59418516fdab731de7James Dong    mFreeBoxOffset = mOffset;
34520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3467837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mEstimatedMoovBoxSize == 0) {
3472dec2b5be2056c6d9428897dc672185872d30d17James Dong        int32_t bitRate = -1;
3482dec2b5be2056c6d9428897dc672185872d30d17James Dong        if (param) {
3492dec2b5be2056c6d9428897dc672185872d30d17James Dong            param->findInt32(kKeyBitRate, &bitRate);
3502dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
3512dec2b5be2056c6d9428897dc672185872d30d17James Dong        mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate);
3527837c17063a4c50bc856ba59418516fdab731de7James Dong    }
3537837c17063a4c50bc856ba59418516fdab731de7James Dong    CHECK(mEstimatedMoovBoxSize >= 8);
3547837c17063a4c50bc856ba59418516fdab731de7James Dong    fseeko(mFile, mFreeBoxOffset, SEEK_SET);
3557837c17063a4c50bc856ba59418516fdab731de7James Dong    writeInt32(mEstimatedMoovBoxSize);
3567837c17063a4c50bc856ba59418516fdab731de7James Dong    write("free", 4);
3577837c17063a4c50bc856ba59418516fdab731de7James Dong
3587837c17063a4c50bc856ba59418516fdab731de7James Dong    mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize;
3597837c17063a4c50bc856ba59418516fdab731de7James Dong    mOffset = mMdatOffset;
3607837c17063a4c50bc856ba59418516fdab731de7James Dong    fseeko(mFile, mMdatOffset, SEEK_SET);
3611acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
3621acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("????mdat", 8);
3631acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
3641acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("\x00\x00\x00\x01mdat????????", 16);
3651acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
3661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
3671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    status_t err = startWriterThread();
3681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (err != OK) {
3691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        return err;
3701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
3711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
3721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    err = startTracks(param);
373a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (err != OK) {
374a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return err;
37520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
3761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
377a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mStarted = true;
37825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
37920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
38020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
381a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dongvoid MPEG4Writer::pause() {
382a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (mFile == NULL) {
383a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return;
384a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
385a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
386a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
387a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
388a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        (*it)->pause();
389a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
390a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
391a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
3921c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::stopWriterThread() {
3931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("stopWriterThread");
3941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
3951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    {
3961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        Mutex::Autolock autolock(mLock);
3971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
3981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mDone = true;
3991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkReadyCondition.signal();
4001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
4011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
4021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void *dummy;
4031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_join(mThread, &dummy);
4041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
4051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
40620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::stop() {
40720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mFile == NULL) {
40820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return;
40920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
41020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4118f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t maxDurationUs = 0;
41220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
41320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber         it != mTracks.end(); ++it) {
41420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        (*it)->stop();
41520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4168f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int64_t durationUs = (*it)->getDurationUs();
4178f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        if (durationUs > maxDurationUs) {
4188f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            maxDurationUs = durationUs;
41920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
42020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
42120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    stopWriterThread();
4237837c17063a4c50bc856ba59418516fdab731de7James Dong
42420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // Fix up the size of the 'mdat' chunk.
4251acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
4261acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        fseeko(mFile, mMdatOffset, SEEK_SET);
4271acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        int32_t size = htonl(static_cast<int32_t>(mOffset - mMdatOffset));
4281acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        fwrite(&size, 1, 4, mFile);
4291acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
4301acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        fseeko(mFile, mMdatOffset + 8, SEEK_SET);
4311acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        int64_t size = mOffset - mMdatOffset;
4321acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        size = hton64(size);
4331acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        fwrite(&size, 1, 8, mFile);
4341acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
4357837c17063a4c50bc856ba59418516fdab731de7James Dong    fseeko(mFile, mOffset, SEEK_SET);
43620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
43720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    time_t now = time(NULL);
4387837c17063a4c50bc856ba59418516fdab731de7James Dong    const off_t moovOffset = mOffset;
4397837c17063a4c50bc856ba59418516fdab731de7James Dong    mWriteMoovBoxToMemory = true;
4407837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize);
4417837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
4427837c17063a4c50bc856ba59418516fdab731de7James Dong    CHECK(mMoovBoxBuffer != NULL);
443c059860c73678a202bfa33062723e8f82fb779d9James Dong    int32_t duration = (maxDurationUs * mTimeScale + 5E5) / 1E6;
44420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
44520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    beginBox("moov");
44620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
44720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      beginBox("mvhd");
44820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // version=0, flags=0
44920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(now);           // creation time
45020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(now);           // modification time
4518f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        writeInt32(mTimeScale);    // mvhd timescale
4521acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        writeInt32(duration);
4531acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        writeInt32(0x10000);       // rate: 1.0
45420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt16(0x100);         // volume
45520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt16(0);             // reserved
45620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // reserved
45720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // reserved
45820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0x10000);       // matrix
45920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
46020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
46120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
46220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0x10000);
46320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
46420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
46520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
46620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0x40000000);
46720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
46820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
46920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
47020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
47120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
47220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
47320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(mTracks.size() + 1);  // nextTrackID
47420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      endBox();  // mvhd
47520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
47620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      int32_t id = 1;
47720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      for (List<Track *>::iterator it = mTracks.begin();
47820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber           it != mTracks.end(); ++it, ++id) {
4791acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          (*it)->writeTrackHeader(id, mUse32BitOffset);
48020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      }
48120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    endBox();  // moov
48220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4837837c17063a4c50bc856ba59418516fdab731de7James Dong    mWriteMoovBoxToMemory = false;
4847837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mStreamableFile) {
4857837c17063a4c50bc856ba59418516fdab731de7James Dong        CHECK(mMoovBoxBufferOffset + 8 <= mEstimatedMoovBoxSize);
4867837c17063a4c50bc856ba59418516fdab731de7James Dong
4877837c17063a4c50bc856ba59418516fdab731de7James Dong        // Moov box
4887837c17063a4c50bc856ba59418516fdab731de7James Dong        fseeko(mFile, mFreeBoxOffset, SEEK_SET);
4897837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset = mFreeBoxOffset;
4907837c17063a4c50bc856ba59418516fdab731de7James Dong        write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, mFile);
4917837c17063a4c50bc856ba59418516fdab731de7James Dong
4927837c17063a4c50bc856ba59418516fdab731de7James Dong        // Free box
4932dec2b5be2056c6d9428897dc672185872d30d17James Dong        fseeko(mFile, mOffset, SEEK_SET);
4947837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset);
4957837c17063a4c50bc856ba59418516fdab731de7James Dong        write("free", 4);
4967837c17063a4c50bc856ba59418516fdab731de7James Dong
4977837c17063a4c50bc856ba59418516fdab731de7James Dong        // Free temp memory
4987837c17063a4c50bc856ba59418516fdab731de7James Dong        free(mMoovBoxBuffer);
4997837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBuffer = NULL;
5007837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBufferOffset = 0;
5012dec2b5be2056c6d9428897dc672185872d30d17James Dong    } else {
5022dec2b5be2056c6d9428897dc672185872d30d17James Dong        LOGI("The mp4 file will not be streamable.");
5037837c17063a4c50bc856ba59418516fdab731de7James Dong    }
5047837c17063a4c50bc856ba59418516fdab731de7James Dong
5050c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(mBoxes.empty());
50620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5077837c17063a4c50bc856ba59418516fdab731de7James Dong    fflush(mFile);
50820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fclose(mFile);
50920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mFile = NULL;
510a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mStarted = false;
51120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
51220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
51313aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) {
51413aec890216948b0c364f8f92792129d0335f506James Dong    mInterleaveDurationUs = durationUs;
51513aec890216948b0c364f8f92792129d0335f506James Dong    return OK;
51613aec890216948b0c364f8f92792129d0335f506James Dong}
51713aec890216948b0c364f8f92792129d0335f506James Dong
51813aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() {
51913aec890216948b0c364f8f92792129d0335f506James Dong    mLock.lock();
52013aec890216948b0c364f8f92792129d0335f506James Dong}
52113aec890216948b0c364f8f92792129d0335f506James Dong
52213aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() {
52313aec890216948b0c364f8f92792129d0335f506James Dong    mLock.unlock();
52413aec890216948b0c364f8f92792129d0335f506James Dong}
52520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
52613aec890216948b0c364f8f92792129d0335f506James Dongoff_t MPEG4Writer::addSample_l(MediaBuffer *buffer) {
52720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    off_t old_offset = mOffset;
52820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
52920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fwrite((const uint8_t *)buffer->data() + buffer->range_offset(),
53020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber           1, buffer->range_length(), mFile);
53120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
53220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += buffer->range_length();
53320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
53420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return old_offset;
53520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
53620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
53703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) {
53803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (buffer->range_length() < 4) {
53903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return;
54003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
54103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
54203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    const uint8_t *ptr =
54303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        (const uint8_t *)buffer->data() + buffer->range_offset();
54403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
54503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) {
54603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        buffer->set_range(
54703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                buffer->range_offset() + 4, buffer->range_length() - 4);
54803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
54903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
55003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
55113aec890216948b0c364f8f92792129d0335f506James Dongoff_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) {
55230ab66297501757d745b9ae10da61adcd891f497Andreas Huber    off_t old_offset = mOffset;
55330ab66297501757d745b9ae10da61adcd891f497Andreas Huber
55430ab66297501757d745b9ae10da61adcd891f497Andreas Huber    size_t length = buffer->range_length();
55503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
55603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR
55703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    uint8_t x = length >> 24;
55803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    fwrite(&x, 1, 1, mFile);
55903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    x = (length >> 16) & 0xff;
56003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    fwrite(&x, 1, 1, mFile);
56103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    x = (length >> 8) & 0xff;
56203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    fwrite(&x, 1, 1, mFile);
56303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    x = length & 0xff;
56403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    fwrite(&x, 1, 1, mFile);
56503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else
56630ab66297501757d745b9ae10da61adcd891f497Andreas Huber    CHECK(length < 65536);
56730ab66297501757d745b9ae10da61adcd891f497Andreas Huber
56830ab66297501757d745b9ae10da61adcd891f497Andreas Huber    uint8_t x = length >> 8;
56930ab66297501757d745b9ae10da61adcd891f497Andreas Huber    fwrite(&x, 1, 1, mFile);
57030ab66297501757d745b9ae10da61adcd891f497Andreas Huber    x = length & 0xff;
57130ab66297501757d745b9ae10da61adcd891f497Andreas Huber    fwrite(&x, 1, 1, mFile);
57203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif
57330ab66297501757d745b9ae10da61adcd891f497Andreas Huber
57430ab66297501757d745b9ae10da61adcd891f497Andreas Huber    fwrite((const uint8_t *)buffer->data() + buffer->range_offset(),
57530ab66297501757d745b9ae10da61adcd891f497Andreas Huber           1, length, mFile);
57630ab66297501757d745b9ae10da61adcd891f497Andreas Huber
57703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR
57803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    mOffset += length + 4;
57903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else
58030ab66297501757d745b9ae10da61adcd891f497Andreas Huber    mOffset += length + 2;
58103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif
58230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
58330ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return old_offset;
58430ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
58530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
5867837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write(
5877837c17063a4c50bc856ba59418516fdab731de7James Dong        const void *ptr, size_t size, size_t nmemb, FILE *stream) {
5887837c17063a4c50bc856ba59418516fdab731de7James Dong
5897837c17063a4c50bc856ba59418516fdab731de7James Dong    const size_t bytes = size * nmemb;
5907837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
5911acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        off_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes;
5921acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        if (moovBoxSize > mEstimatedMoovBoxSize) {
5937837c17063a4c50bc856ba59418516fdab731de7James Dong            for (List<off_t>::iterator it = mBoxes.begin();
5947837c17063a4c50bc856ba59418516fdab731de7James Dong                 it != mBoxes.end(); ++it) {
5957837c17063a4c50bc856ba59418516fdab731de7James Dong                (*it) += mOffset;
5967837c17063a4c50bc856ba59418516fdab731de7James Dong            }
5977837c17063a4c50bc856ba59418516fdab731de7James Dong            fseeko(mFile, mOffset, SEEK_SET);
5987837c17063a4c50bc856ba59418516fdab731de7James Dong            fwrite(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, stream);
5997837c17063a4c50bc856ba59418516fdab731de7James Dong            fwrite(ptr, size, nmemb, stream);
6007837c17063a4c50bc856ba59418516fdab731de7James Dong            mOffset += (bytes + mMoovBoxBufferOffset);
6017837c17063a4c50bc856ba59418516fdab731de7James Dong            free(mMoovBoxBuffer);
6027837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBuffer = NULL;
6037837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset = 0;
6047837c17063a4c50bc856ba59418516fdab731de7James Dong            mWriteMoovBoxToMemory = false;
6057837c17063a4c50bc856ba59418516fdab731de7James Dong            mStreamableFile = false;
6067837c17063a4c50bc856ba59418516fdab731de7James Dong        } else {
6077837c17063a4c50bc856ba59418516fdab731de7James Dong            memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes);
6087837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset += bytes;
6097837c17063a4c50bc856ba59418516fdab731de7James Dong        }
6107837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
6117837c17063a4c50bc856ba59418516fdab731de7James Dong        fwrite(ptr, size, nmemb, stream);
6127837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset += bytes;
6137837c17063a4c50bc856ba59418516fdab731de7James Dong    }
6147837c17063a4c50bc856ba59418516fdab731de7James Dong    return bytes;
6157837c17063a4c50bc856ba59418516fdab731de7James Dong}
6167837c17063a4c50bc856ba59418516fdab731de7James Dong
61720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) {
6180c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(fourcc), 4);
61920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6207837c17063a4c50bc856ba59418516fdab731de7James Dong    mBoxes.push_back(mWriteMoovBoxToMemory?
6217837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset: mOffset);
62220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
62320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeInt32(0);
62420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeFourcc(fourcc);
62520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
62620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
62720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() {
6280c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(!mBoxes.empty());
62920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
63020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    off_t offset = *--mBoxes.end();
63120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mBoxes.erase(--mBoxes.end());
63220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6337837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
6347837c17063a4c50bc856ba59418516fdab731de7James Dong       int32_t x = htonl(mMoovBoxBufferOffset - offset);
6357837c17063a4c50bc856ba59418516fdab731de7James Dong       memcpy(mMoovBoxBuffer + offset, &x, 4);
6367837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
6377837c17063a4c50bc856ba59418516fdab731de7James Dong        fseeko(mFile, offset, SEEK_SET);
6387837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mOffset - offset);
6397837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset -= 4;
6407837c17063a4c50bc856ba59418516fdab731de7James Dong        fseeko(mFile, mOffset, SEEK_SET);
6417837c17063a4c50bc856ba59418516fdab731de7James Dong    }
64220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
64320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
64420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) {
6457837c17063a4c50bc856ba59418516fdab731de7James Dong    write(&x, 1, 1, mFile);
64620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
64720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
64820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) {
64920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htons(x);
6507837c17063a4c50bc856ba59418516fdab731de7James Dong    write(&x, 1, 2, mFile);
65120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
65220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
65320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) {
65420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htonl(x);
6557837c17063a4c50bc856ba59418516fdab731de7James Dong    write(&x, 1, 4, mFile);
65620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
65720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
65820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) {
65920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = hton64(x);
6607837c17063a4c50bc856ba59418516fdab731de7James Dong    write(&x, 1, 8, mFile);
66120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
66220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
66320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) {
66420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t n = strlen(s);
6657837c17063a4c50bc856ba59418516fdab731de7James Dong    write(s, 1, n + 1, mFile);
66620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
66720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
66820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) {
6690c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(s), 4);
6707837c17063a4c50bc856ba59418516fdab731de7James Dong    write(s, 1, 4, mFile);
67120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
67220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
67320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) {
6747837c17063a4c50bc856ba59418516fdab731de7James Dong    write(data, 1, size, mFile);
67520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
67620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
677d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() {
678d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
679d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileSizeLimitBytes == 0) {
680d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
681d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
682d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
683956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize);
684d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
685d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
686d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes();
687d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
688d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return (nTotalBytesEstimate >= mMaxFileSizeLimitBytes);
689d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
690d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
691d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() {
692d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
693d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileDurationLimitUs == 0) {
694d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
695d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
696d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
697d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
698d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
699d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) {
700d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            return true;
701d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
702d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
703d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return false;
704d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
705d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
70625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() {
70725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool allDone = true;
70825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
70925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber         it != mTracks.end(); ++it) {
71025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        if (!(*it)->reachedEOS()) {
71125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            allDone = false;
71225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            break;
71325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        }
71425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
71525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
71625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return allDone;
71725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
71825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
719f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) {
720f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    LOGI("setStartTimestampUs: %lld", timeUs);
721f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    CHECK(timeUs >= 0);
7223c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
723065d1aff96818df54456053f1574aec8a234d0deJames Dong    if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) {
724f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mStartTimestampUs = timeUs;
725f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        LOGI("Earliest track starting time: %lld", mStartTimestampUs);
7263c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    }
7273c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
7283c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
729f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() {
7303c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
7313c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    return mStartTimestampUs;
7323c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
7333c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
73458ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() {
73558ae9c530247668f8af36e30d228c716c226b3d4James Dong    Mutex::Autolock autolock(mLock);
73658ae9c530247668f8af36e30d228c716c226b3d4James Dong    return mTracks.size();
73758ae9c530247668f8af36e30d228c716c226b3d4James Dong}
73858ae9c530247668f8af36e30d228c716c226b3d4James Dong
73920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
74020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
74120111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track(
74225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        MPEG4Writer *owner, const sp<MediaSource> &source)
74320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mOwner(owner),
74425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mMeta(source->getFormat()),
74520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSource(source),
74620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDone(false),
747a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
748a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mResumed(false),
749c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong      mTrackDurationUs(0),
750956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      mEstimatedTrackSizeBytes(0),
751be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong      mSamplesHaveSameSize(true),
75220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCodecSpecificData(NULL),
75325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mCodecSpecificDataSize(0),
754548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber      mGotAllCodecSpecificData(false),
75525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mReachedEOS(false) {
75619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    getCodecSpecificDataFromInputFormatIfPossible();
7578f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
7581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    const char *mime;
7591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mMeta->findCString(kKeyMIMEType, &mime);
7601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
7611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAudio = !strncasecmp(mime, "audio/", 6);
7621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
7631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong               !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC);
7641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
765c059860c73678a202bfa33062723e8f82fb779d9James Dong    setTimeScale();
766c059860c73678a202bfa33062723e8f82fb779d9James Dong}
767c059860c73678a202bfa33062723e8f82fb779d9James Dong
768c059860c73678a202bfa33062723e8f82fb779d9James Dongvoid MPEG4Writer::Track::setTimeScale() {
769c059860c73678a202bfa33062723e8f82fb779d9James Dong    LOGV("setTimeScale");
770c059860c73678a202bfa33062723e8f82fb779d9James Dong    // Default time scale
771c059860c73678a202bfa33062723e8f82fb779d9James Dong    mTimeScale = 90000;
772c059860c73678a202bfa33062723e8f82fb779d9James Dong
773c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mIsAudio) {
774c059860c73678a202bfa33062723e8f82fb779d9James Dong        // Use the sampling rate as the default time scale for audio track.
775c059860c73678a202bfa33062723e8f82fb779d9James Dong        int32_t sampleRate;
776c059860c73678a202bfa33062723e8f82fb779d9James Dong        bool success = mMeta->findInt32(kKeySampleRate, &sampleRate);
777c059860c73678a202bfa33062723e8f82fb779d9James Dong        CHECK(success);
778c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = sampleRate;
779c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
780c059860c73678a202bfa33062723e8f82fb779d9James Dong
781c059860c73678a202bfa33062723e8f82fb779d9James Dong    // If someone would like to overwrite the timescale, use user-supplied value.
782c059860c73678a202bfa33062723e8f82fb779d9James Dong    int32_t timeScale;
783c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mMeta->findInt32(kKeyTimeScale, &timeScale)) {
784c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = timeScale;
785c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
786c059860c73678a202bfa33062723e8f82fb779d9James Dong
7878f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    CHECK(mTimeScale > 0);
78819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber}
78919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
79019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Hubervoid MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() {
79119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    const char *mime;
79219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
79319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
79419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
79519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        uint32_t type;
79619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        const void *data;
79719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        size_t size;
79819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        if (mMeta->findData(kKeyAVCC, &type, &data, &size)) {
79919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mCodecSpecificData = malloc(size);
80019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mCodecSpecificDataSize = size;
80119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            memcpy(mCodecSpecificData, data, size);
80219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mGotAllCodecSpecificData = true;
80319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        }
80419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
80519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
80619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        uint32_t type;
80719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        const void *data;
80819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        size_t size;
80919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        if (mMeta->findData(kKeyESDS, &type, &data, &size)) {
81019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            ESDS esds(data, size);
81119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            if (esds.getCodecSpecificInfo(&data, &size) == OK) {
81219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mCodecSpecificData = malloc(size);
81319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mCodecSpecificDataSize = size;
81419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                memcpy(mCodecSpecificData, data, size);
81519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mGotAllCodecSpecificData = true;
81619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            }
81719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        }
81819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
81920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
82020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
82120111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() {
82220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    stop();
82320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
82420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mCodecSpecificData != NULL) {
82520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        free(mCodecSpecificData);
82620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mCodecSpecificData = NULL;
82720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
82820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
82920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
83093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) {
83193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    LOGV("initTrackingProgressStatus");
83293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mPreviousTrackTimeUs = -1;
83393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackingProgressStatus = false;
83493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackEveryTimeDurationUs = 0;
83593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    {
83693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        int64_t timeUs;
83793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) {
83893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            LOGV("Receive request to track progress status for every %lld us", timeUs);
83993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackEveryTimeDurationUs = timeUs;
84093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackingProgressStatus = true;
84193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
84293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
84393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
84493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
8451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong// static
8461c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid *MPEG4Writer::ThreadWrapper(void *me) {
8471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("ThreadWrapper: %p", me);
8481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    MPEG4Writer *writer = static_cast<MPEG4Writer *>(me);
8491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    writer->threadFunc();
8501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return NULL;
8511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
8521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8531c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::bufferChunk(const Chunk& chunk) {
8541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("bufferChunk: %p", chunk.mTrack);
8551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Mutex::Autolock autolock(mLock);
8561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    CHECK_EQ(mDone, false);
8571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
8591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
8601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (chunk.mTrack == it->mTrack) {  // Found owner
8621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            it->mChunks.push_back(chunk);
8631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.signal();
8641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            return;
8651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
8661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
8671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    CHECK("Received a chunk for a unknown track" == 0);
8691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
8701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8711c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::writeFirstChunk(ChunkInfo* info) {
8721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("writeFirstChunk: %p", info->mTrack);
8731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    List<Chunk>::iterator chunkIt = info->mChunks.begin();
8751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<MediaBuffer *>::iterator it = chunkIt->mSamples.begin();
8761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != chunkIt->mSamples.end(); ++it) {
8771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        off_t offset = info->mTrack->isAvc()
8791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                            ? addLengthPrefixedSample_l(*it)
8801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                            : addSample_l(*it);
8811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (it == chunkIt->mSamples.begin()) {
8821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            info->mTrack->addChunkOffset(offset);
8831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
8841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
8851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    // Done with the current chunk.
8871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    // Release all the samples in this chunk.
8881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    while (!chunkIt->mSamples.empty()) {
8891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        List<MediaBuffer *>::iterator it = chunkIt->mSamples.begin();
8901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it)->release();
8911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it) = NULL;
8921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        chunkIt->mSamples.erase(it);
8931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
8941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    chunkIt->mSamples.clear();
8951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    info->mChunks.erase(chunkIt);
8961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
8971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8981c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::writeChunks() {
8991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("writeChunks");
9001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    size_t outstandingChunks = 0;
9011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    while (!mChunkInfos.empty()) {
9021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        List<ChunkInfo>::iterator it = mChunkInfos.begin();
9031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        while (!it->mChunks.empty()) {
9041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            CHECK_EQ(OK, writeOneChunk());
9051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            ++outstandingChunks;
9061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
9071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        it->mTrack = NULL;
9081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkInfos.erase(it);
9091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
9101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mChunkInfos.clear();
9111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGD("%d chunks are written in the last batch", outstandingChunks);
9121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
9131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
9141c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::writeOneChunk() {
9151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("writeOneChunk");
9161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
9171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    // Find the smallest timestamp, and write that chunk out
9181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    // XXX: What if some track is just too slow?
9191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL;
9201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Track *track = NULL;
9211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
9221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
9231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (!it->mChunks.empty()) {
9241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            List<Chunk>::iterator chunkIt = it->mChunks.begin();
9251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (chunkIt->mTimeStampUs < minTimestampUs) {
9261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                minTimestampUs = chunkIt->mTimeStampUs;
9271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                track = it->mTrack;
9281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            }
9291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
9301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
9311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
9321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (track == NULL) {
9331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        LOGV("Nothing to be written after all");
9341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        return OK;
9351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
9361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
9371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (mIsFirstChunk) {
9381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsFirstChunk = false;
9391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
9401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
9411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
9421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (it->mTrack == track) {
9431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            writeFirstChunk(&(*it));
9441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
9451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
9461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return OK;
9471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
9481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
9491c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::threadFunc() {
9501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("threadFunc");
9511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
9521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    while (!mDone) {
9531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        {
9541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            Mutex::Autolock autolock(mLock);
9551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.wait(mLock);
9561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            CHECK_EQ(writeOneChunk(), OK);
9571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
9581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
9591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
9601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    {
9611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        // Write ALL samples
9621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        Mutex::Autolock autolock(mLock);
9631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        writeChunks();
9641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
9651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
9661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
9671c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::startWriterThread() {
9681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("startWriterThread");
9691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
9701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mDone = false;
9711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsFirstChunk = true;
972e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    mDriftTimeUs = 0;
9731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<Track *>::iterator it = mTracks.begin();
9741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mTracks.end(); ++it) {
9751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        ChunkInfo info;
9761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        info.mTrack = *it;
9771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkInfos.push_back(info);
9781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
9791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
9801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_t attr;
9811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_init(&attr);
9821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
9831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_create(&mThread, &attr, ThreadWrapper, this);
9841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_destroy(&attr);
9851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return OK;
9861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
9871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
98893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) {
989a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (!mDone && mPaused) {
990a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mPaused = false;
991a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mResumed = true;
992a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
993a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
99425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
99593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t startTimeUs;
99619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) {
99719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        startTimeUs = 0;
99819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
99919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
1000e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    mIsRealTimeRecording = true;
1001e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    {
1002e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        int32_t isNotRealTime;
1003e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        if (params && params->findInt32(kKeyNotRealTime, &isNotRealTime)) {
1004e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            mIsRealTimeRecording = (isNotRealTime == 0);
1005e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        }
1006e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    }
1007e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
100893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    initTrackingProgressStatus(params);
100993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
1010f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    sp<MetaData> meta = new MetaData;
1011f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    meta->setInt64(kKeyTime, startTimeUs);
1012f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    status_t err = mSource->start(meta.get());
101325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    if (err != OK) {
101425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        mDone = mReachedEOS = true;
101525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return err;
101625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
101720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
101820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_t attr;
101920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_init(&attr);
102020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
102120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
102220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = false;
1023c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs = 0;
102425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = false;
1025956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    mEstimatedTrackSizeBytes = 0;
102620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
102725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    pthread_create(&mThread, &attr, ThreadWrapper, this);
102820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_destroy(&attr);
102925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
103025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
103120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
103220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1033a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dongvoid MPEG4Writer::Track::pause() {
1034a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
1035a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
1036a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
103720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::Track::stop() {
103820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mDone) {
103920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return;
104020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
104120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
104220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = true;
104320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
104420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *dummy;
104520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_join(mThread, &dummy);
104620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
104720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mSource->stop();
104820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
104920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
105025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() {
105125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return mReachedEOS;
105225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
105325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
105420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static
105520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) {
105620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = static_cast<Track *>(me);
105720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
105820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    track->threadEntry();
105920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
106020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return NULL;
106120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
106220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1063548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber#include <ctype.h>
1064548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huberstatic void hexdump(const void *_data, size_t size) {
1065548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    const uint8_t *data = (const uint8_t *)_data;
1066548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    size_t offset = 0;
1067548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    while (offset < size) {
1068548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        printf("0x%04x  ", offset);
1069548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
1070548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        size_t n = size - offset;
1071548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        if (n > 16) {
1072548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            n = 16;
1073548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        }
1074548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
1075548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        for (size_t i = 0; i < 16; ++i) {
1076548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            if (i == 8) {
1077548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber                printf(" ");
1078548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            }
1079548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
1080548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            if (offset + i < size) {
1081548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber                printf("%02x ", data[offset + i]);
1082548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            } else {
1083548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber                printf("   ");
1084548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            }
1085548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        }
1086548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
1087548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        printf(" ");
1088548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
1089548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        for (size_t i = 0; i < n; ++i) {
1090548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            if (isprint(data[offset + i])) {
1091548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber                printf("%c", data[offset + i]);
1092548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            } else {
1093548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber                printf(".");
1094548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            }
1095548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        }
1096548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
1097548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        printf("\n");
1098548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
1099548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        offset += 16;
1100548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    }
1101548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber}
1102548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
11033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic void getNalUnitType(uint8_t byte, uint8_t* type) {
11043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    LOGV("getNalUnitType: %d", byte);
11053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
11063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // nal_unit_type: 5-bit unsigned integer
11073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *type = (byte & 0x1F);
11083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
11093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
11103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t *findNextStartCode(
11113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length) {
11123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
11133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    LOGV("findNextStartCode: %p %d", data, length);
11143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
11153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t bytesLeft = length;
11163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    while (bytesLeft > 4  &&
11173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            memcmp("\x00\x00\x00\x01", &data[length - bytesLeft], 4)) {
11183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        --bytesLeft;
11193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
11203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (bytesLeft <= 4) {
11213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        bytesLeft = 0; // Last parameter set
11223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
11233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return &data[length - bytesLeft];
11243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
11253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
11263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongconst uint8_t *MPEG4Writer::Track::parseParamSet(
11273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen) {
11283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
11293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    LOGV("parseParamSet");
11303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    CHECK(type == kNalUnitTypeSeqParamSet ||
11313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong          type == kNalUnitTypePicParamSet);
11323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
11333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *nextStartCode = findNextStartCode(data, length);
11343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *paramSetLen = nextStartCode - data;
11353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (*paramSetLen == 0) {
11363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        LOGE("Param set is malformed, since its length is 0");
11373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return NULL;
11383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
11393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
11403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    AVCParamSet paramSet(*paramSetLen, data);
11413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (type == kNalUnitTypeSeqParamSet) {
11423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (*paramSetLen < 4) {
11433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Seq parameter set malformed");
11443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return NULL;
11453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
11463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mSeqParamSets.empty()) {
11473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc = data[1];
11483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileCompatible = data[2];
11493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mLevelIdc = data[3];
11503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
11513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (mProfileIdc != data[1] ||
11523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mProfileCompatible != data[2] ||
11533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mLevelIdc != data[3]) {
11543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                LOGE("Inconsistent profile/level found in seq parameter sets");
11553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return NULL;
11563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
11573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
11583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mSeqParamSets.push_back(paramSet);
11593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    } else {
11603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mPicParamSets.push_back(paramSet);
11613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
11623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return nextStartCode;
11633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
11643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
11653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::copyAVCCodecSpecificData(
11663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
11673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    LOGV("copyAVCCodecSpecificData");
11683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
11693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 2 bytes for each of the parameter set length field
11703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // plus the 7 bytes for the header
11713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (size < 4 + 7) {
11723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        LOGE("Codec specific data length too short: %d", size);
11733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return ERROR_MALFORMED;
11743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
11753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
11763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize = size;
11773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificData = malloc(size);
11783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    memcpy(mCodecSpecificData, data, size);
11793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
11803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
11813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
11823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::parseAVCCodecSpecificData(
11833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
11843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
11853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    LOGV("parseAVCCodecSpecificData");
11863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data starts with a start code.
11873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // SPS and PPS are separated with start codes.
11883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Also, SPS must come before PPS
11893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t type = kNalUnitTypeSeqParamSet;
11903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotSps = false;
11913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotPps = false;
11923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *tmp = data;
11933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *nextStartCode = data;
11943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t bytesLeft = size;
11953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t paramSetLen = 0;
11963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize = 0;
11973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) {
11983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        getNalUnitType(*(tmp + 4), &type);
11993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (type == kNalUnitTypeSeqParamSet) {
12003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (gotPps) {
12013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                LOGE("SPS must come before PPS");
12023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
12033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
12043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
12053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotSps = true;
12063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
12073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
12083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else if (type == kNalUnitTypePicParamSet) {
12093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
12103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                LOGE("SPS must come before PPS");
12113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
12123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
12133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotPps) {
12143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotPps = true;
12153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
12163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
12173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
12183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Only SPS and PPS Nal units are expected");
12193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
12203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
12213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
12223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nextStartCode == NULL) {
12233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
12243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
12253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
12263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Move on to find the next parameter set
12273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        bytesLeft -= nextStartCode - tmp;
12283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        tmp = nextStartCode;
12293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mCodecSpecificDataSize += (2 + paramSetLen);
12303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
12313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
12323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
12333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of seq parameter sets
12343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nSeqParamSets = mSeqParamSets.size();
12353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets == 0) {
12363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Cound not find sequence parameter set");
12373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
12383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
12393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
12403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets > 0x1F) {
12413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Too many seq parameter sets (%d) found", nSeqParamSets);
12423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
12433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
12443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
12453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
12463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
12473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of pic parameter sets
12483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nPicParamSets = mPicParamSets.size();
12493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets == 0) {
12503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Cound not find picture parameter set");
12513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
12523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
12533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets > 0xFF) {
12543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Too many pic parameter sets (%d) found", nPicParamSets);
12553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
12563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
12573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
12583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
12593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
12603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the profiles
12613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // These profiles requires additional parameter set extensions
12623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mProfileIdc == 100 || mProfileIdc == 110 ||
12633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc == 122 || mProfileIdc == 144) {
12643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Sorry, no support for profile_idc: %d!", mProfileIdc);
12653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return BAD_VALUE;
12663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
12673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
12683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
12693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
12703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
1271548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
127203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData(
127303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        const uint8_t *data, size_t size) {
1274548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    // hexdump(data, size);
1275548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
127603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (mCodecSpecificData != NULL) {
1277548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        LOGE("Already have codec specific data");
127803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
127903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
128003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
12813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (size < 4) {
12823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        LOGE("Codec specific data length too short: %d", size);
128303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
128403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
128503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
12863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data is in the form of AVCCodecSpecificData
12873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (memcmp("\x00\x00\x00\x01", data, 4)) {
12883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return copyAVCCodecSpecificData(data, size);
128903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
129003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
12913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (parseAVCCodecSpecificData(data, size) != OK) {
129203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
129303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
129403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
12953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // ISO 14496-15: AVC file format
12963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize += 7;  // 7 more bytes in the header
129703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    mCodecSpecificData = malloc(mCodecSpecificDataSize);
129803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    uint8_t *header = (uint8_t *)mCodecSpecificData;
12993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = 1;                     // version
13003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[1] = mProfileIdc;           // profile indication
13013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[2] = mProfileCompatible;    // profile compatibility
13023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[3] = mLevelIdc;
130303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
13043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne
130503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR
130603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[4] = 0xfc | 3;  // length size == 4 bytes
130703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else
130803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[4] = 0xfc | 1;  // length size == 2 bytes
130903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif
131003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
13113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 3-bit '111' followed by 5-bit numSequenceParameterSets
13123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nSequenceParamSets = mSeqParamSets.size();
13133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[5] = 0xe0 | nSequenceParamSets;
13143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 6;
13153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mSeqParamSets.begin();
13163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mSeqParamSets.end(); ++it) {
13173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit sequence parameter set length
13183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t seqParamSetLength = it->mLength;
13193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = seqParamSetLength >> 8;
13203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = seqParamSetLength & 0xff;
13213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // SPS NAL unit (sequence parameter length bytes)
13233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, seqParamSetLength);
13243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + seqParamSetLength);
13253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
13263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 8-bit nPictureParameterSets
13283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nPictureParamSets = mPicParamSets.size();
13293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = nPictureParamSets;
13303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 1;
13313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mPicParamSets.begin();
13323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mPicParamSets.end(); ++it) {
13333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit picture parameter set length
13343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t picParamSetLength = it->mLength;
13353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = picParamSetLength >> 8;
13363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = picParamSetLength & 0xff;
13373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // PPS Nal unit (picture parameter set length bytes)
13393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, picParamSetLength);
13403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + picParamSetLength);
13413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
134203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
134303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    return OK;
134403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
134503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
13468644c14618d30d9e57a69df40ed939986ebf02c4James Dongstatic bool collectStatisticalData() {
13478644c14618d30d9e57a69df40ed939986ebf02c4James Dong    char value[PROPERTY_VALUE_MAX];
13488644c14618d30d9e57a69df40ed939986ebf02c4James Dong    if (property_get("media.stagefright.record-stats", value, NULL)
13498644c14618d30d9e57a69df40ed939986ebf02c4James Dong        && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
13508644c14618d30d9e57a69df40ed939986ebf02c4James Dong        return true;
13518644c14618d30d9e57a69df40ed939986ebf02c4James Dong    }
13528644c14618d30d9e57a69df40ed939986ebf02c4James Dong    return false;
13538644c14618d30d9e57a69df40ed939986ebf02c4James Dong}
13548644c14618d30d9e57a69df40ed939986ebf02c4James Dong
135520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::Track::threadEntry() {
135630ab66297501757d745b9ae10da61adcd891f497Andreas Huber    int32_t count = 0;
135713aec890216948b0c364f8f92792129d0335f506James Dong    const int64_t interleaveDurationUs = mOwner->interleaveDuration();
135813aec890216948b0c364f8f92792129d0335f506James Dong    int64_t chunkTimestampUs = 0;
135913aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nChunks = 0;
136013aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nZeroLengthFrames = 0;
13618f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t lastTimestampUs = 0;  // Previous sample time stamp in ms
13628f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t lastDurationUs = 0;   // Between the previous two samples in ms
1363c059860c73678a202bfa33062723e8f82fb779d9James Dong    int64_t currDurationTicks = 0;  // Timescale based ticks
1364c059860c73678a202bfa33062723e8f82fb779d9James Dong    int64_t lastDurationTicks = 0;  // Timescale based ticks
13658f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int32_t sampleCount = 1;      // Sample count in the current stts table entry
1366be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    uint32_t previousSampleSize = 0;  // Size of the previous sample
1367a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    int64_t previousPausedDurationUs = 0;
13681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    int64_t timestampUs;
1369e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
1370e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    int64_t wallClockTimeUs = 0;
1371e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    int64_t lastWallClockTimeUs = 0;
1372e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
1373d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong    sp<MetaData> meta_data;
13748644c14618d30d9e57a69df40ed939986ebf02c4James Dong    bool collectStats = collectStatisticalData();
137520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1376ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    mNumSamples = 0;
13771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mMaxWriteTimeUs = 0;
137893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t err = OK;
137920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBuffer *buffer;
138093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    while (!mDone && (err = mSource->read(&buffer)) == OK) {
138120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (buffer->range_length() == 0) {
138220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer->release();
138320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer = NULL;
138413aec890216948b0c364f8f92792129d0335f506James Dong            ++nZeroLengthFrames;
138520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            continue;
138620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
138720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1388a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // If the codec specific data has not been received yet, delay pause.
1389a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // After the codec specific data is received, discard what we received
1390a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // when the track is to be paused.
1391a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused && !mResumed) {
1392a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer->release();
1393a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer = NULL;
1394a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            continue;
1395a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
1396a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
139730ab66297501757d745b9ae10da61adcd891f497Andreas Huber        ++count;
139830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
139903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        int32_t isCodecConfig;
140003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig)
140103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                && isCodecConfig) {
1402548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            CHECK(!mGotAllCodecSpecificData);
1403548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
14041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (mIsAvc) {
140503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                status_t err = makeAVCCodecSpecificData(
140603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        (const uint8_t *)buffer->data()
140703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                            + buffer->range_offset(),
140803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        buffer->range_length());
1409be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                CHECK_EQ(OK, err);
14101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            } else if (mIsMPEG4) {
141103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificDataSize = buffer->range_length();
141203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificData = malloc(mCodecSpecificDataSize);
141303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                memcpy(mCodecSpecificData,
141403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        (const uint8_t *)buffer->data()
141503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                            + buffer->range_offset(),
141603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                       buffer->range_length());
141730ab66297501757d745b9ae10da61adcd891f497Andreas Huber            }
141830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
141930ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer->release();
142030ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer = NULL;
142130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
1422548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            mGotAllCodecSpecificData = true;
142330ab66297501757d745b9ae10da61adcd891f497Andreas Huber            continue;
1424a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
1425a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
1426d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // Make a deep copy of the MediaBuffer and Metadata and release
1427d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // the original as soon as we can
1428d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        MediaBuffer *copy = new MediaBuffer(buffer->range_length());
1429d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(),
1430d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong                buffer->range_length());
1431d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        copy->set_range(0, buffer->range_length());
1432d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data = new MetaData(*buffer->meta_data().get());
1433d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer->release();
1434d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer = NULL;
1435d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
14361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (mIsAvc) StripStartcode(copy);
1437e136c3bb38e88315bf8797a464ebf2c788296b22James Dong
14388644c14618d30d9e57a69df40ed939986ebf02c4James Dong        size_t sampleSize;
14391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        sampleSize = mIsAvc
144003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR
1441d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong                ? copy->range_length() + 4
144203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else
1443d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong                ? copy->range_length() + 2
144403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif
1445d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong                : copy->range_length();
1446050b28a593350047845a45a14cc5026221ac1620James Dong
1447d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        // Max file size or duration handling
14488644c14618d30d9e57a69df40ed939986ebf02c4James Dong        mEstimatedTrackSizeBytes += sampleSize;
1449d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileSizeLimit()) {
1450d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
1451d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
1452d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
1453d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileDurationLimit()) {
1454d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
1455d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
1456d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
1457d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1458050b28a593350047845a45a14cc5026221ac1620James Dong
1459d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        int32_t isSync = false;
1460d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data->findInt32(kKeyIsSyncFrame, &isSync);
1461d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
1462d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        CHECK(meta_data->findInt64(kKeyTime, &timestampUs));
1463d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
1464d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong////////////////////////////////////////////////////////////////////////////////
14658644c14618d30d9e57a69df40ed939986ebf02c4James Dong        if (mSampleSizes.empty()) {
1466f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mStartTimestampUs = timestampUs;
1467f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mOwner->setStartTimestampUs(mStartTimestampUs);
14683c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        }
146948c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber
1470a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mResumed) {
1471c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong            previousPausedDurationUs += (timestampUs - mTrackDurationUs - lastDurationUs);
1472a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mResumed = false;
1473a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
1474a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
1475a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        timestampUs -= previousPausedDurationUs;
1476e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        if (mIsRealTimeRecording && !mIsAudio) {
1477e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            // The minor adjustment on the timestamp is heuristic/experimental
1478e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            // We are adjusting the timestamp to reduce the fluctuation of the duration
1479e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            // of neighboring samples. This in turn helps reduce the track header size,
1480e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            // especially, the number of entries in the "stts" box.
1481e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            if (mNumSamples > 1) {
1482e259531ce59ab1f31de5a23124b22536f6a5a767James Dong                int64_t durationUs = timestampUs + mOwner->getDriftTimeUs() - lastTimestampUs;
1483e259531ce59ab1f31de5a23124b22536f6a5a767James Dong                int64_t diffUs = (durationUs > lastDurationUs)
1484e259531ce59ab1f31de5a23124b22536f6a5a767James Dong                            ? durationUs - lastDurationUs
1485e259531ce59ab1f31de5a23124b22536f6a5a767James Dong                            : lastDurationUs - durationUs;
1486e259531ce59ab1f31de5a23124b22536f6a5a767James Dong                if (diffUs <= 5000) {  // XXX: Magic number 5ms
1487e259531ce59ab1f31de5a23124b22536f6a5a767James Dong                    timestampUs = lastTimestampUs + lastDurationUs;
1488e259531ce59ab1f31de5a23124b22536f6a5a767James Dong                } else {
1489e259531ce59ab1f31de5a23124b22536f6a5a767James Dong                    timestampUs += mOwner->getDriftTimeUs();
1490e259531ce59ab1f31de5a23124b22536f6a5a767James Dong                }
1491e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            }
1492e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        }
1493e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        CHECK(timestampUs >= 0);
1494e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        if (mNumSamples > 1) {
1495e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            if (timestampUs <= lastTimestampUs) {
1496e259531ce59ab1f31de5a23124b22536f6a5a767James Dong                LOGW("Drop a frame, since it arrives too late!");
1497e259531ce59ab1f31de5a23124b22536f6a5a767James Dong                copy->release();
1498e259531ce59ab1f31de5a23124b22536f6a5a767James Dong                copy = NULL;
1499e259531ce59ab1f31de5a23124b22536f6a5a767James Dong                continue;
1500e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            }
1501e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        }
1502e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
1503a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        LOGV("time stamp: %lld and previous paused duration %lld",
1504a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                timestampUs, previousPausedDurationUs);
1505c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong        if (timestampUs > mTrackDurationUs) {
1506c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong            mTrackDurationUs = timestampUs;
15073b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber        }
15083b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber
15098644c14618d30d9e57a69df40ed939986ebf02c4James Dong        mSampleSizes.push_back(sampleSize);
1510ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong        ++mNumSamples;
1511ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong        if (mNumSamples > 2) {
1512c059860c73678a202bfa33062723e8f82fb779d9James Dong            // We need to use the time scale based ticks, rather than the
1513c059860c73678a202bfa33062723e8f82fb779d9James Dong            // timestamp itself to determine whether we have to use a new
1514c059860c73678a202bfa33062723e8f82fb779d9James Dong            // stts entry, since we may have rounding errors.
1515c059860c73678a202bfa33062723e8f82fb779d9James Dong            // The calculation is intended to reduce the accumulated
1516c059860c73678a202bfa33062723e8f82fb779d9James Dong            // rounding errors.
1517c059860c73678a202bfa33062723e8f82fb779d9James Dong            currDurationTicks =
1518c059860c73678a202bfa33062723e8f82fb779d9James Dong                     ((timestampUs * mTimeScale + 500000LL) / 1000000LL -
1519c059860c73678a202bfa33062723e8f82fb779d9James Dong                     (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL);
1520c059860c73678a202bfa33062723e8f82fb779d9James Dong
1521c059860c73678a202bfa33062723e8f82fb779d9James Dong            if (currDurationTicks != lastDurationTicks) {
15228f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong                SttsTableEntry sttsEntry(sampleCount, lastDurationUs);
1523be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mSttsTableEntries.push_back(sttsEntry);
1524be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                sampleCount = 1;
1525be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            } else {
1526be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                ++sampleCount;
1527be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
1528be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
1529be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        if (mSamplesHaveSameSize) {
1530ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong            if (mNumSamples >= 2 && previousSampleSize != sampleSize) {
1531be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mSamplesHaveSameSize = false;
1532be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
15338644c14618d30d9e57a69df40ed939986ebf02c4James Dong            previousSampleSize = sampleSize;
1534be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
15358644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastDurationUs = timestampUs - lastTimestampUs;
1536c059860c73678a202bfa33062723e8f82fb779d9James Dong        lastDurationTicks = currDurationTicks;
15378644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastTimestampUs = timestampUs;
1538e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        if (mIsRealTimeRecording && mIsAudio) {
1539e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            wallClockTimeUs = systemTime() / 1000;
1540e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            int64_t wallClockDurationUs = wallClockTimeUs - lastWallClockTimeUs;
1541e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            if (mNumSamples > 2) {
1542e259531ce59ab1f31de5a23124b22536f6a5a767James Dong                mOwner->addDriftTimeUs(lastDurationUs - wallClockDurationUs);
1543e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            }
1544e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            lastWallClockTimeUs = wallClockTimeUs;
1545e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        }
154620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1547d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        if (isSync != 0) {
1548ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong            mStssTableEntries.push_back(mNumSamples);
1549d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        }
1550d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
155193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (mTrackingProgressStatus) {
155293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            if (mPreviousTrackTimeUs <= 0) {
155393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong                mPreviousTrackTimeUs = mStartTimestampUs;
155493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            }
1555faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong            trackProgressStatus(timestampUs);
155693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
155758ae9c530247668f8af36e30d228c716c226b3d4James Dong        if (mOwner->numTracks() == 1) {
15581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            off_t offset = mIsAvc? mOwner->addLengthPrefixedSample_l(copy)
155958ae9c530247668f8af36e30d228c716c226b3d4James Dong                                 : mOwner->addSample_l(copy);
156058ae9c530247668f8af36e30d228c716c226b3d4James Dong            if (mChunkOffsets.empty()) {
156158ae9c530247668f8af36e30d228c716c226b3d4James Dong                mChunkOffsets.push_back(offset);
156258ae9c530247668f8af36e30d228c716c226b3d4James Dong            }
156358ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy->release();
156458ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy = NULL;
156558ae9c530247668f8af36e30d228c716c226b3d4James Dong            continue;
156658ae9c530247668f8af36e30d228c716c226b3d4James Dong        }
156713aec890216948b0c364f8f92792129d0335f506James Dong
156813aec890216948b0c364f8f92792129d0335f506James Dong        mChunkSamples.push_back(copy);
156913aec890216948b0c364f8f92792129d0335f506James Dong        if (interleaveDurationUs == 0) {
157013aec890216948b0c364f8f92792129d0335f506James Dong            StscTableEntry stscEntry(++nChunks, 1, 1);
157113aec890216948b0c364f8f92792129d0335f506James Dong            mStscTableEntries.push_back(stscEntry);
15721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            bufferChunk(timestampUs);
157313aec890216948b0c364f8f92792129d0335f506James Dong        } else {
157413aec890216948b0c364f8f92792129d0335f506James Dong            if (chunkTimestampUs == 0) {
157513aec890216948b0c364f8f92792129d0335f506James Dong                chunkTimestampUs = timestampUs;
157613aec890216948b0c364f8f92792129d0335f506James Dong            } else {
157713aec890216948b0c364f8f92792129d0335f506James Dong                if (timestampUs - chunkTimestampUs > interleaveDurationUs) {
157813aec890216948b0c364f8f92792129d0335f506James Dong                    ++nChunks;
15798644c14618d30d9e57a69df40ed939986ebf02c4James Dong                    if (collectStats) {
15808644c14618d30d9e57a69df40ed939986ebf02c4James Dong                        mChunkDurations.push_back(timestampUs - chunkTimestampUs);
15818644c14618d30d9e57a69df40ed939986ebf02c4James Dong                    }
158213aec890216948b0c364f8f92792129d0335f506James Dong                    if (nChunks == 1 ||  // First chunk
158313aec890216948b0c364f8f92792129d0335f506James Dong                        (--(mStscTableEntries.end()))->samplesPerChunk !=
158413aec890216948b0c364f8f92792129d0335f506James Dong                         mChunkSamples.size()) {
158513aec890216948b0c364f8f92792129d0335f506James Dong                        StscTableEntry stscEntry(nChunks,
158613aec890216948b0c364f8f92792129d0335f506James Dong                                mChunkSamples.size(), 1);
158713aec890216948b0c364f8f92792129d0335f506James Dong                        mStscTableEntries.push_back(stscEntry);
158813aec890216948b0c364f8f92792129d0335f506James Dong                    }
15891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                    bufferChunk(timestampUs);
159013aec890216948b0c364f8f92792129d0335f506James Dong                    chunkTimestampUs = timestampUs;
159113aec890216948b0c364f8f92792129d0335f506James Dong                }
159213aec890216948b0c364f8f92792129d0335f506James Dong            }
159313aec890216948b0c364f8f92792129d0335f506James Dong        }
159413aec890216948b0c364f8f92792129d0335f506James Dong
159520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
159625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
15978644c14618d30d9e57a69df40ed939986ebf02c4James Dong    if (mSampleSizes.empty()) {
159893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        err = UNKNOWN_ERROR;
1599f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong    }
1600faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    mOwner->trackProgressStatus(this, -1, err);
1601be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
160213aec890216948b0c364f8f92792129d0335f506James Dong    // Last chunk
160358ae9c530247668f8af36e30d228c716c226b3d4James Dong    if (mOwner->numTracks() == 1) {
1604ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong        StscTableEntry stscEntry(1, mNumSamples, 1);
160558ae9c530247668f8af36e30d228c716c226b3d4James Dong        mStscTableEntries.push_back(stscEntry);
160658ae9c530247668f8af36e30d228c716c226b3d4James Dong    } else if (!mChunkSamples.empty()) {
160713aec890216948b0c364f8f92792129d0335f506James Dong        ++nChunks;
160813aec890216948b0c364f8f92792129d0335f506James Dong        StscTableEntry stscEntry(nChunks, mChunkSamples.size(), 1);
160913aec890216948b0c364f8f92792129d0335f506James Dong        mStscTableEntries.push_back(stscEntry);
16101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        bufferChunk(timestampUs);
161113aec890216948b0c364f8f92792129d0335f506James Dong    }
161213aec890216948b0c364f8f92792129d0335f506James Dong
1613be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // We don't really know how long the last frame lasts, since
1614be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // there is no frame time after it, just repeat the previous
1615be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // frame's duration.
1616ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    if (mNumSamples == 1) {
16178f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        lastDurationUs = 0;  // A single sample's duration
1618be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    } else {
1619be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        ++sampleCount;  // Count for the last sample
1620be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    }
16218f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    SttsTableEntry sttsEntry(sampleCount, lastDurationUs);
1622be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    mSttsTableEntries.push_back(sttsEntry);
1623c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs += lastDurationUs;
162425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = true;
16251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. Max write time: %lld us - %s",
16261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            count, nZeroLengthFrames, mNumSamples, mMaxWriteTimeUs, mIsAudio? "audio": "video");
1627365a963142093a1cd8efdcea76b5f65096a5b115James Dong
16281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    logStatisticalData(mIsAudio);
1629365a963142093a1cd8efdcea76b5f65096a5b115James Dong}
1630365a963142093a1cd8efdcea76b5f65096a5b115James Dong
1631faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) {
1632faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    LOGV("trackProgressStatus: %lld us", timeUs);
1633215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    if (mTrackEveryTimeDurationUs > 0 &&
1634215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) {
163593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        LOGV("Fire time tracking progress status at %lld us", timeUs);
1636faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        mOwner->trackProgressStatus(this, timeUs - mPreviousTrackTimeUs, err);
163793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        mPreviousTrackTimeUs = timeUs;
163893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
163993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
164093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
1641faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::trackProgressStatus(
1642faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        const MPEG4Writer::Track* track, int64_t timeUs, status_t err) {
1643faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    Mutex::Autolock lock(mLock);
1644faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    int32_t nTracks = mTracks.size();
1645faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    CHECK(nTracks >= 1);
1646faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    CHECK(nTracks < 64);  // Arbitrary number
1647faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
1648faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    int32_t trackNum = 0;
1649faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong#if 0
1650faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // In the worst case, we can put the trackNum
1651faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // along with MEDIA_RECORDER_INFO_COMPLETION_STATUS
1652faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // to report the progress.
1653faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    for (List<Track *>::iterator it = mTracks.begin();
1654faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong         it != mTracks.end(); ++it, ++trackNum) {
1655faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        if (track == (*it)) {
1656faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong            break;
1657faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        }
1658faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
1659faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong#endif
1660faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    CHECK(trackNum < nTracks);
1661faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    trackNum <<= 16;
1662faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
1663faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Error notification
1664faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Do not consider ERROR_END_OF_STREAM an error
1665faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (err != OK && err != ERROR_END_OF_STREAM) {
1666faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        notify(MEDIA_RECORDER_EVENT_ERROR,
1667faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               trackNum | MEDIA_RECORDER_ERROR_UNKNOWN,
1668faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
1669faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        return;
1670faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
1671faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
1672faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (timeUs == -1) {
1673faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send completion notification
1674faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        notify(MEDIA_RECORDER_EVENT_INFO,
1675faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               trackNum | MEDIA_RECORDER_INFO_COMPLETION_STATUS,
1676faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
1677faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        return;
1678faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    } else {
1679faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send progress status
1680faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        notify(MEDIA_RECORDER_EVENT_INFO,
1681faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               trackNum | MEDIA_RECORDER_INFO_PROGRESS_TIME_STATUS,
1682faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               timeUs / 1000);
1683faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
1684faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong}
1685faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
1686215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dongvoid MPEG4Writer::Track::findMinAvgMaxSampleDurationMs(
1687215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        int32_t *min, int32_t *avg, int32_t *max) {
16888644c14618d30d9e57a69df40ed939986ebf02c4James Dong    CHECK(!mSampleSizes.empty());
1689c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    int32_t avgSampleDurationMs = mTrackDurationUs / 1000 / mNumSamples;
1690215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    int32_t minSampleDurationMs = 0x7FFFFFFF;
1691215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    int32_t maxSampleDurationMs = 0;
1692365a963142093a1cd8efdcea76b5f65096a5b115James Dong    for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin();
1693365a963142093a1cd8efdcea76b5f65096a5b115James Dong        it != mSttsTableEntries.end(); ++it) {
16948f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int32_t sampleDurationMs =
16958f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            (static_cast<int32_t>(it->sampleDurationUs) + 500) / 1000;
1696215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        if (sampleDurationMs > maxSampleDurationMs) {
1697215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong            maxSampleDurationMs = sampleDurationMs;
1698215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        } else if (sampleDurationMs < minSampleDurationMs) {
1699215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong            minSampleDurationMs = sampleDurationMs;
1700365a963142093a1cd8efdcea76b5f65096a5b115James Dong        }
1701215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        LOGI("sample duration: %d ms", sampleDurationMs);
1702365a963142093a1cd8efdcea76b5f65096a5b115James Dong    }
1703215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    CHECK(minSampleDurationMs != 0);
1704215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    CHECK(avgSampleDurationMs != 0);
1705215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    CHECK(maxSampleDurationMs != 0);
1706215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    *min = minSampleDurationMs;
1707215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    *avg = avgSampleDurationMs;
1708215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    *max = maxSampleDurationMs;
1709365a963142093a1cd8efdcea76b5f65096a5b115James Dong}
1710365a963142093a1cd8efdcea76b5f65096a5b115James Dong
1711365a963142093a1cd8efdcea76b5f65096a5b115James Dong// Don't count the last duration
1712365a963142093a1cd8efdcea76b5f65096a5b115James Dongvoid MPEG4Writer::Track::findMinMaxChunkDurations(int64_t *min, int64_t *max) {
1713365a963142093a1cd8efdcea76b5f65096a5b115James Dong    int64_t duration = mOwner->interleaveDuration();
1714365a963142093a1cd8efdcea76b5f65096a5b115James Dong    int64_t minChunkDuration = duration;
1715365a963142093a1cd8efdcea76b5f65096a5b115James Dong    int64_t maxChunkDuration = duration;
1716365a963142093a1cd8efdcea76b5f65096a5b115James Dong    if (mChunkDurations.size() > 1) {
1717365a963142093a1cd8efdcea76b5f65096a5b115James Dong        for (List<int64_t>::iterator it = mChunkDurations.begin();
1718365a963142093a1cd8efdcea76b5f65096a5b115James Dong            it != --mChunkDurations.end(); ++it) {
1719365a963142093a1cd8efdcea76b5f65096a5b115James Dong            if (minChunkDuration > (*it)) {
1720365a963142093a1cd8efdcea76b5f65096a5b115James Dong                minChunkDuration = (*it);
1721365a963142093a1cd8efdcea76b5f65096a5b115James Dong            } else if (maxChunkDuration < (*it)) {
1722365a963142093a1cd8efdcea76b5f65096a5b115James Dong                maxChunkDuration = (*it);
1723365a963142093a1cd8efdcea76b5f65096a5b115James Dong            }
1724365a963142093a1cd8efdcea76b5f65096a5b115James Dong        }
1725365a963142093a1cd8efdcea76b5f65096a5b115James Dong    }
1726365a963142093a1cd8efdcea76b5f65096a5b115James Dong    *min = minChunkDuration;
1727365a963142093a1cd8efdcea76b5f65096a5b115James Dong    *max = maxChunkDuration;
1728365a963142093a1cd8efdcea76b5f65096a5b115James Dong}
1729365a963142093a1cd8efdcea76b5f65096a5b115James Dong
1730365a963142093a1cd8efdcea76b5f65096a5b115James Dongvoid MPEG4Writer::Track::logStatisticalData(bool isAudio) {
1731c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    if (mTrackDurationUs <= 0 || mSampleSizes.empty()) {
1732365a963142093a1cd8efdcea76b5f65096a5b115James Dong        LOGI("nothing is recorded");
1733365a963142093a1cd8efdcea76b5f65096a5b115James Dong        return;
1734365a963142093a1cd8efdcea76b5f65096a5b115James Dong    }
1735365a963142093a1cd8efdcea76b5f65096a5b115James Dong
17368644c14618d30d9e57a69df40ed939986ebf02c4James Dong    bool collectStats = collectStatisticalData();
1737365a963142093a1cd8efdcea76b5f65096a5b115James Dong
1738365a963142093a1cd8efdcea76b5f65096a5b115James Dong    if (collectStats) {
1739215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        LOGI("%s track - duration %lld us, total %d frames",
1740c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong                isAudio? "audio": "video", mTrackDurationUs,
1741ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong                mNumSamples);
1742215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        int32_t min, avg, max;
1743215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        findMinAvgMaxSampleDurationMs(&min, &avg, &max);
1744215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        LOGI("min/avg/max sample duration (ms): %d/%d/%d", min, avg, max);
1745215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        if (!isAudio) {
1746215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong            float avgFps = 1000.0 / avg;
1747215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong            float minFps = 1000.0 / max;
1748215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong            float maxFps = 1000.0 / min;
1749365a963142093a1cd8efdcea76b5f65096a5b115James Dong            LOGI("min/avg/max frame rate (fps): %.2f/%.2f/%.2f",
1750215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong                minFps, avgFps, maxFps);
1751365a963142093a1cd8efdcea76b5f65096a5b115James Dong        }
1752365a963142093a1cd8efdcea76b5f65096a5b115James Dong
1753365a963142093a1cd8efdcea76b5f65096a5b115James Dong        int64_t totalBytes = 0;
17548644c14618d30d9e57a69df40ed939986ebf02c4James Dong        for (List<size_t>::iterator it = mSampleSizes.begin();
17558644c14618d30d9e57a69df40ed939986ebf02c4James Dong            it != mSampleSizes.end(); ++it) {
17568644c14618d30d9e57a69df40ed939986ebf02c4James Dong            totalBytes += (*it);
1757365a963142093a1cd8efdcea76b5f65096a5b115James Dong        }
1758c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong        float bitRate = (totalBytes * 8000000.0) / mTrackDurationUs;
1759365a963142093a1cd8efdcea76b5f65096a5b115James Dong        LOGI("avg bit rate (bps): %.2f", bitRate);
1760365a963142093a1cd8efdcea76b5f65096a5b115James Dong
1761365a963142093a1cd8efdcea76b5f65096a5b115James Dong        int64_t duration = mOwner->interleaveDuration();
1762365a963142093a1cd8efdcea76b5f65096a5b115James Dong        if (duration != 0) {  // If interleaving is enabled
1763365a963142093a1cd8efdcea76b5f65096a5b115James Dong            int64_t minChunk, maxChunk;
1764365a963142093a1cd8efdcea76b5f65096a5b115James Dong            findMinMaxChunkDurations(&minChunk, &maxChunk);
1765365a963142093a1cd8efdcea76b5f65096a5b115James Dong            LOGI("min/avg/max chunk duration (ms): %lld/%lld/%lld",
1766365a963142093a1cd8efdcea76b5f65096a5b115James Dong                minChunk, duration, maxChunk);
1767365a963142093a1cd8efdcea76b5f65096a5b115James Dong        }
1768365a963142093a1cd8efdcea76b5f65096a5b115James Dong    }
176913aec890216948b0c364f8f92792129d0335f506James Dong}
177013aec890216948b0c364f8f92792129d0335f506James Dong
1771e259531ce59ab1f31de5a23124b22536f6a5a767James Dongvoid MPEG4Writer::addDriftTimeUs(int64_t driftTimeUs) {
1772e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    LOGV("addDriftTimeUs: %lld us", driftTimeUs);
1773e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
1774e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    mDriftTimeUs += driftTimeUs;
1775e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
1776e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
1777e259531ce59ab1f31de5a23124b22536f6a5a767James Dongint64_t MPEG4Writer::getDriftTimeUs() {
1778e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    LOGV("getDriftTimeUs: %lld us", mDriftTimeUs);
1779e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
1780e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    return mDriftTimeUs;
1781e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
1782e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
17831c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::Track::bufferChunk(int64_t timestampUs) {
17841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("bufferChunk");
17851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    int64_t startTimeUs = systemTime() / 1000;
17871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Chunk chunk(this, timestampUs, mChunkSamples);
17881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mOwner->bufferChunk(chunk);
178913aec890216948b0c364f8f92792129d0335f506James Dong    mChunkSamples.clear();
17901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    int64_t endTimeUs = systemTime() / 1000;
17911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (mMaxWriteTimeUs < endTimeUs - startTimeUs) {
17921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mMaxWriteTimeUs = endTimeUs - startTimeUs;
17931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
179420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
179520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
17963b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const {
1797c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    return mTrackDurationUs;
179820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
179920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1800d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const {
1801d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return mEstimatedTrackSizeBytes;
1802d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
1803d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
18041acfe8649f8169caf2ff098c2dc2de880d9a3760James Dongvoid MPEG4Writer::Track::writeTrackHeader(
18051acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        int32_t trackID, bool use32BitOffset) {
180620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const char *mime;
180720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool success = mMeta->findCString(kKeyMIMEType, &mime);
18080c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(success);
180920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
18108f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    LOGV("%s track time scale: %d",
18111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsAudio? "Audio": "Video", mTimeScale);
18128f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
181320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    time_t now = time(NULL);
18148f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int32_t mvhdTimeScale = mOwner->getTimeScale();
18158f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t trakDurationUs = getDurationUs();
181620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
181720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOwner->beginBox("trak");
181820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
181920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->beginBox("tkhd");
18201acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        // Flags = 7 to indicate that the track is enabled, and
18211acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        // part of the presentation
18221acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        mOwner->writeInt32(0x07);          // version=0, flags=7
182320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(now);           // creation time
182420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(now);           // modification time
182520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(trackID);
182620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);             // reserved
18278f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int32_t tkhdDuration =
18288f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
18298f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        mOwner->writeInt32(tkhdDuration);  // in mvhd timescale
183020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);             // reserved
183120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);             // reserved
183220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt16(0);             // layer
183320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt16(0);             // alternate group
18341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mOwner->writeInt16(mIsAudio ? 0x100 : 0);  // volume
183520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt16(0);             // reserved
183620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
183720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0x10000);       // matrix
183820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
183920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
184020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
184120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0x10000);
184220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
184320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
184420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
184520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0x40000000);
184620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
18471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (mIsAudio) {
184820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);
184920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);
185020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        } else {
185120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            int32_t width, height;
185220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            bool success = mMeta->findInt32(kKeyWidth, &width);
185320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            success = success && mMeta->findInt32(kKeyHeight, &height);
18540c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber            CHECK(success);
185520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1856050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->writeInt32(width << 16);   // 32-bit fixed-point value
1857050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->writeInt32(height << 16);  // 32-bit fixed-point value
185820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
185920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->endBox();  // tkhd
186020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1861f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong      int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
1862f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong      if (mStartTimestampUs != moovStartTimeUs) {
18633c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        mOwner->beginBox("edts");
18643c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong          mOwner->beginBox("elst");
18651acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong            mOwner->writeInt32(0);           // version=0, flags=0: 32-bit time
18661acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong            mOwner->writeInt32(2);           // never ends with an empty list
18678f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
18688f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            // First elst entry: specify the starting time offset
18698f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            int64_t offsetUs = mStartTimestampUs - moovStartTimeUs;
18708f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            int32_t seg = (offsetUs * mvhdTimeScale + 5E5) / 1E6;
18718f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            mOwner->writeInt32(seg);         // in mvhd timecale
18728f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            mOwner->writeInt32(-1);          // starting time offset
18738f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            mOwner->writeInt32(1 << 16);     // rate = 1.0
18748f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
18758f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            // Second elst entry: specify the track duration
18768f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            seg = (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
18778f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            mOwner->writeInt32(seg);         // in mvhd timescale
18781acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong            mOwner->writeInt32(0);
18791acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong            mOwner->writeInt32(1 << 16);
18803c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong          mOwner->endBox();
18813c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        mOwner->endBox();
18823c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong      }
18833c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
188420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->beginBox("mdia");
188520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
188620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("mdhd");
188720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // version=0, flags=0
188820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(now);           // creation time
188920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(now);           // modification time
18908f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong          mOwner->writeInt32(mTimeScale);    // media timescale
18918f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong          int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6;
18928f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong          mOwner->writeInt32(mdhdDuration);  // use media timescale
18931acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // Language follows the three letter standard ISO-639-2/T
18941acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // 'e', 'n', 'g' for "English", for instance.
18951acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // Each character is packed as the difference between its ASCII value and 0x60.
18961acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // For "English", these are 00101, 01110, 00111.
18971acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // XXX: Where is the padding bit located: 0x15C7?
18981acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          mOwner->writeInt16(0);             // language code
189920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt16(0);             // predefined
190020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->endBox();
190120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
190220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("hdlr");
190320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // version=0, flags=0
1904050b28a593350047845a45a14cc5026221ac1620James Dong          mOwner->writeInt32(0);             // component type: should be mhlr
19051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong          mOwner->writeFourcc(mIsAudio ? "soun" : "vide");  // component subtype
190620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // reserved
190720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // reserved
190820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // reserved
19091acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // Removing "r" for the name string just makes the string 4 byte aligned
19101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong          mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle");  // name
191120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->endBox();
191220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
191320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("minf");
19141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong          if (mIsAudio) {
191520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->beginBox("smhd");
191620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt32(0);           // version=0, flags=0
191720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // balance
191820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // reserved
191920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->endBox();
192020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          } else {
192120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->beginBox("vmhd");
19221acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong              mOwner->writeInt32(0x01);        // version=0, flags=1
192320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // graphics mode
192420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // opcolor
192520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);
192620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);
192720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->endBox();
192820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          }
1929050b28a593350047845a45a14cc5026221ac1620James Dong
1930050b28a593350047845a45a14cc5026221ac1620James Dong          mOwner->beginBox("dinf");
1931050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->beginBox("dref");
1932050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->writeInt32(0);  // version=0, flags=0
19331acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong              mOwner->writeInt32(1);  // entry count (either url or urn)
19341acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong              // The table index here refers to the sample description index
19351acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong              // in the sample table entries.
1936050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->beginBox("url ");
19371acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                mOwner->writeInt32(1);  // version=0, flags=1 (self-contained)
1938050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->endBox();  // url
1939050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->endBox();  // dref
1940050b28a593350047845a45a14cc5026221ac1620James Dong          mOwner->endBox();  // dinf
1941050b28a593350047845a45a14cc5026221ac1620James Dong
194220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("stbl");
194320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
194420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stsd");
194520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);               // version=0, flags=0
194620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(1);               // entry count
19471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (mIsAudio) {
194825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                const char *fourcc = NULL;
194918291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) {
195025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    fourcc = "samr";
195118291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
195225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    fourcc = "sawb";
1953050b28a593350047845a45a14cc5026221ac1620James Dong                } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
1954050b28a593350047845a45a14cc5026221ac1620James Dong                    fourcc = "mp4a";
195525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                } else {
195625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    LOGE("Unknown mime type '%s'.", mime);
195725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    CHECK(!"should not be here, unknown mime type.");
195825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                }
195925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
196025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                mOwner->beginBox(fourcc);          // audio format
196120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
196220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
1963050b28a593350047845a45a14cc5026221ac1620James Dong                  mOwner->writeInt16(0x1);         // data ref index
196420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
196520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
1966050b28a593350047845a45a14cc5026221ac1620James Dong                  int32_t nChannels;
1967050b28a593350047845a45a14cc5026221ac1620James Dong                  CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels));
1968050b28a593350047845a45a14cc5026221ac1620James Dong                  mOwner->writeInt16(nChannels);   // channel count
196920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(16);          // sample size
197020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // predefined
197120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
197220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
197320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  int32_t samplerate;
197420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  bool success = mMeta->findInt32(kKeySampleRate, &samplerate);
19750c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                  CHECK(success);
197620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
197720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(samplerate << 16);
1978050b28a593350047845a45a14cc5026221ac1620James Dong                  if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
1979050b28a593350047845a45a14cc5026221ac1620James Dong                    mOwner->beginBox("esds");
198051dfe6d646ddcc5fc252aa4c19c9936d32af8ad7James Dong                        CHECK(mCodecSpecificData);
198151dfe6d646ddcc5fc252aa4c19c9936d32af8ad7James Dong                        CHECK(mCodecSpecificDataSize > 0);
1982050b28a593350047845a45a14cc5026221ac1620James Dong
1983050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt32(0);     // version=0, flags=0
1984050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x03);   // ES_DescrTag
1985050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(23 + mCodecSpecificDataSize);
1986050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt16(0x0000);// ES_ID
1987050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x00);
1988050b28a593350047845a45a14cc5026221ac1620James Dong
1989050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x04);   // DecoderConfigDescrTag
1990050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(15 + mCodecSpecificDataSize);
1991050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x40);   // objectTypeIndication ISO/IEC 14492-2
1992050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x15);   // streamType AudioStream
1993050b28a593350047845a45a14cc5026221ac1620James Dong
1994050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt16(0x03);  // XXX
1995050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x00);   // buffer size 24-bit
1996050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt32(96000); // max bit rate
1997050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt32(96000); // avg bit rate
1998050b28a593350047845a45a14cc5026221ac1620James Dong
1999050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x05);   // DecoderSpecificInfoTag
2000050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(mCodecSpecificDataSize);
2001050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
2002050b28a593350047845a45a14cc5026221ac1620James Dong
2003050b28a593350047845a45a14cc5026221ac1620James Dong                        static const uint8_t kData2[] = {
2004050b28a593350047845a45a14cc5026221ac1620James Dong                            0x06,  // SLConfigDescriptorTag
2005050b28a593350047845a45a14cc5026221ac1620James Dong                            0x01,
2006050b28a593350047845a45a14cc5026221ac1620James Dong                            0x02
2007050b28a593350047845a45a14cc5026221ac1620James Dong                        };
2008050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->write(kData2, sizeof(kData2));
2009050b28a593350047845a45a14cc5026221ac1620James Dong
2010050b28a593350047845a45a14cc5026221ac1620James Dong                    mOwner->endBox();  // esds
20115aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                  } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) ||
20125aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                             !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
20135aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                    // 3gpp2 Spec AMRSampleEntry fields
20145aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                    mOwner->beginBox("damr");
20155aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                      mOwner->writeCString("   ");  // vendor: 4 bytes
20165aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                      mOwner->writeInt8(0);         // decoder version
20175aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                      mOwner->writeInt16(0x83FF);   // mode set: all enabled
20185aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                      mOwner->writeInt8(0);         // mode change period
20195aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                      mOwner->writeInt8(1);         // frames per sample
20205aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                    mOwner->endBox();
2021050b28a593350047845a45a14cc5026221ac1620James Dong                  }
202220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mOwner->endBox();
202320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
202418291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
202520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    mOwner->beginBox("mp4v");
202618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
202720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    mOwner->beginBox("s263");
202830ab66297501757d745b9ae10da61adcd891f497Andreas Huber                } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
202930ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    mOwner->beginBox("avc1");
203020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                } else {
203125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    LOGE("Unknown mime type '%s'.", mime);
20320c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                    CHECK(!"should not be here, unknown mime type.");
203320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
203420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
203520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
203620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
20371acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                  mOwner->writeInt16(1);           // data ref index
203820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // predefined
203920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
204020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // predefined
204120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // predefined
204220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // predefined
204320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
204420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  int32_t width, height;
204520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  bool success = mMeta->findInt32(kKeyWidth, &width);
204620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  success = success && mMeta->findInt32(kKeyHeight, &height);
20470c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                  CHECK(success);
204820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
204920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(width);
205020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(height);
205120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0x480000);    // horiz resolution
205220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0x480000);    // vert resolution
205320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
205420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(1);           // frame count
205520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->write("                                ", 32);
205620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0x18);        // depth
205720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(-1);          // predefined
205820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
20590c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                  CHECK(23 + mCodecSpecificDataSize < 128);
206020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
206118291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                  if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
2062a37923e9a57d489e7bed2129369219039fa5f12cJames Dong                      CHECK(mCodecSpecificData);
2063a37923e9a57d489e7bed2129369219039fa5f12cJames Dong                      CHECK(mCodecSpecificDataSize > 0);
206420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->beginBox("esds");
206520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
206620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt32(0);           // version=0, flags=0
206720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
206820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x03);  // ES_DescrTag
206920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(23 + mCodecSpecificDataSize);
207020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt16(0x0000);  // ES_ID
207120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x1f);
207220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
207320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x04);  // DecoderConfigDescrTag
207420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(15 + mCodecSpecificDataSize);
207520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x20);  // objectTypeIndication ISO/IEC 14492-2
207620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x11);  // streamType VisualStream
207720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
207820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        static const uint8_t kData[] = {
207920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x01, 0x77, 0x00,
208020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x00, 0x03, 0xe8, 0x00,
208120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x00, 0x03, 0xe8, 0x00
208220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        };
208320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->write(kData, sizeof(kData));
2084050b28a593350047845a45a14cc5026221ac1620James Dong
208520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x05);  // DecoderSpecificInfoTag
208620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
208720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(mCodecSpecificDataSize);
208820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
208920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
209020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        static const uint8_t kData2[] = {
209120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x06,  // SLConfigDescriptorTag
209220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x01,
209320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x02
209420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        };
209520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->write(kData2, sizeof(kData2));
209620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
209720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->endBox();  // esds
209818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                  } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
209920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->beginBox("d263");
210020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
210120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt32(0);  // vendor
210220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt8(0);   // decoder version
210320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt8(10);  // level: 10
210420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt8(0);   // profile: 0
210520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
210620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->endBox();  // d263
210730ab66297501757d745b9ae10da61adcd891f497Andreas Huber                  } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
210851dfe6d646ddcc5fc252aa4c19c9936d32af8ad7James Dong                      CHECK(mCodecSpecificData);
210951dfe6d646ddcc5fc252aa4c19c9936d32af8ad7James Dong                      CHECK(mCodecSpecificDataSize > 0);
211030ab66297501757d745b9ae10da61adcd891f497Andreas Huber                      mOwner->beginBox("avcC");
211130ab66297501757d745b9ae10da61adcd891f497Andreas Huber                        mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
211230ab66297501757d745b9ae10da61adcd891f497Andreas Huber                      mOwner->endBox();  // avcC
211320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  }
211430ab66297501757d745b9ae10da61adcd891f497Andreas Huber
21151acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                  mOwner->beginBox("pasp");
21161acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                    // This is useful if the pixel is not square
21171acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                    mOwner->writeInt32(1 << 16);  // hspacing
21181acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                    mOwner->writeInt32(1 << 16);  // vspacing
21191acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                  mOwner->endBox();  // pasp
212030ab66297501757d745b9ae10da61adcd891f497Andreas Huber                mOwner->endBox();  // mp4v, s263 or avc1
212120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
212220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stsd
212320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
212420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stts");
212520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
2126be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            mOwner->writeInt32(mSttsTableEntries.size());
2127c059860c73678a202bfa33062723e8f82fb779d9James Dong            int64_t prevTimestampUs = 0;
2128be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin();
2129be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                 it != mSttsTableEntries.end(); ++it) {
2130be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mOwner->writeInt32(it->sampleCount);
2131c059860c73678a202bfa33062723e8f82fb779d9James Dong
2132c059860c73678a202bfa33062723e8f82fb779d9James Dong                // Make sure that we are calculating the sample duration the exactly
2133c059860c73678a202bfa33062723e8f82fb779d9James Dong                // same way as we made decision on how to create stts entries.
2134c059860c73678a202bfa33062723e8f82fb779d9James Dong                int64_t currTimestampUs = prevTimestampUs + it->sampleDurationUs;
2135c059860c73678a202bfa33062723e8f82fb779d9James Dong                int32_t dur = ((currTimestampUs * mTimeScale + 500000LL) / 1000000LL -
2136c059860c73678a202bfa33062723e8f82fb779d9James Dong                               (prevTimestampUs * mTimeScale + 500000LL) / 1000000LL);
2137c059860c73678a202bfa33062723e8f82fb779d9James Dong                prevTimestampUs += (it->sampleCount * it->sampleDurationUs);
2138c059860c73678a202bfa33062723e8f82fb779d9James Dong
21398f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong                mOwner->writeInt32(dur);
214020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
214120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stts
214220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
21431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong          if (!mIsAudio) {
2144050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->beginBox("stss");
2145050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->writeInt32(0);  // version=0, flags=0
2146050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->writeInt32(mStssTableEntries.size());  // number of sync frames
2147050b28a593350047845a45a14cc5026221ac1620James Dong              for (List<int32_t>::iterator it = mStssTableEntries.begin();
2148050b28a593350047845a45a14cc5026221ac1620James Dong                   it != mStssTableEntries.end(); ++it) {
2149050b28a593350047845a45a14cc5026221ac1620James Dong                  mOwner->writeInt32(*it);
2150050b28a593350047845a45a14cc5026221ac1620James Dong              }
2151050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->endBox();  // stss
2152050b28a593350047845a45a14cc5026221ac1620James Dong          }
2153050b28a593350047845a45a14cc5026221ac1620James Dong
215420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stsz");
215520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
2156be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            if (mSamplesHaveSameSize) {
21578644c14618d30d9e57a69df40ed939986ebf02c4James Dong                List<size_t>::iterator it = mSampleSizes.begin();
21588644c14618d30d9e57a69df40ed939986ebf02c4James Dong                mOwner->writeInt32(*it);  // default sample size
2159be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            } else {
2160be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mOwner->writeInt32(0);
2161be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
2162ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong            mOwner->writeInt32(mNumSamples);
2163be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            if (!mSamplesHaveSameSize) {
21648644c14618d30d9e57a69df40ed939986ebf02c4James Dong                for (List<size_t>::iterator it = mSampleSizes.begin();
21658644c14618d30d9e57a69df40ed939986ebf02c4James Dong                     it != mSampleSizes.end(); ++it) {
21668644c14618d30d9e57a69df40ed939986ebf02c4James Dong                    mOwner->writeInt32(*it);
2167be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                }
216820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
216920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stsz
217020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
217120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stsc");
217220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
217313aec890216948b0c364f8f92792129d0335f506James Dong            mOwner->writeInt32(mStscTableEntries.size());
217413aec890216948b0c364f8f92792129d0335f506James Dong            for (List<StscTableEntry>::iterator it = mStscTableEntries.begin();
217513aec890216948b0c364f8f92792129d0335f506James Dong                 it != mStscTableEntries.end(); ++it) {
217613aec890216948b0c364f8f92792129d0335f506James Dong                mOwner->writeInt32(it->firstChunk);
217713aec890216948b0c364f8f92792129d0335f506James Dong                mOwner->writeInt32(it->samplesPerChunk);
217813aec890216948b0c364f8f92792129d0335f506James Dong                mOwner->writeInt32(it->sampleDescriptionId);
217920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
218020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stsc
21811acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          mOwner->beginBox(use32BitOffset? "stco": "co64");
218220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
218313aec890216948b0c364f8f92792129d0335f506James Dong            mOwner->writeInt32(mChunkOffsets.size());
218413aec890216948b0c364f8f92792129d0335f506James Dong            for (List<off_t>::iterator it = mChunkOffsets.begin();
218513aec890216948b0c364f8f92792129d0335f506James Dong                 it != mChunkOffsets.end(); ++it) {
21861acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                if (use32BitOffset) {
21871acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                    mOwner->writeInt32(static_cast<int32_t>(*it));
21881acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                } else {
21891acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                    mOwner->writeInt64((*it));
21901acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                }
219120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
21928f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong          mOwner->endBox();  // stco or co64
219320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
219420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->endBox();  // stbl
21951acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong       mOwner->endBox();  // minf
219620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->endBox();  // mdia
219720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOwner->endBox();  // trak
219820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
219920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
220020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
2201