MPEG4Writer.cpp revision e259531ce59ab1f31de5a23124b22536f6a5a767
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
17120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track(const Track &);
17220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track &operator=(const Track &);
17320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
17420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
17503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#define USE_NALLEN_FOUR         1
17603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
17720111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::MPEG4Writer(const char *filename)
17820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mFile(fopen(filename, "wb")),
1791acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong      mUse32BitOffset(true),
180a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
181a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mStarted(false),
18220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOffset(0),
18313aec890216948b0c364f8f92792129d0335f506James Dong      mMdatOffset(0),
1847837c17063a4c50bc856ba59418516fdab731de7James Dong      mEstimatedMoovBoxSize(0),
185f01528f435e6b1f02d118fcd8305a148c27a89f1James Dong      mInterleaveDurationUs(1000000) {
1860c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(mFile != NULL);
18720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
18820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
18930ab66297501757d745b9ae10da61adcd891f497Andreas HuberMPEG4Writer::MPEG4Writer(int fd)
19030ab66297501757d745b9ae10da61adcd891f497Andreas Huber    : mFile(fdopen(fd, "wb")),
1911acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong      mUse32BitOffset(true),
192a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
193a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mStarted(false),
19430ab66297501757d745b9ae10da61adcd891f497Andreas Huber      mOffset(0),
19513aec890216948b0c364f8f92792129d0335f506James Dong      mMdatOffset(0),
1967837c17063a4c50bc856ba59418516fdab731de7James Dong      mEstimatedMoovBoxSize(0),
197f01528f435e6b1f02d118fcd8305a148c27a89f1James Dong      mInterleaveDurationUs(1000000) {
19830ab66297501757d745b9ae10da61adcd891f497Andreas Huber    CHECK(mFile != NULL);
19930ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
20030ab66297501757d745b9ae10da61adcd891f497Andreas Huber
20120111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() {
20220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    stop();
20320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
20420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
20520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber         it != mTracks.end(); ++it) {
20620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        delete *it;
20720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
20820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.clear();
20920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
21020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2112dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huberstatus_t MPEG4Writer::addSource(const sp<MediaSource> &source) {
21225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    Track *track = new Track(this, source);
21320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.push_back(track);
2142dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
2152dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    return OK;
21620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
21720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
21893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::startTracks(MetaData *params) {
219a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
220a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
22193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        status_t err = (*it)->start(params);
222a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
223a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (err != OK) {
224a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            for (List<Track *>::iterator it2 = mTracks.begin();
225a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                 it2 != it; ++it2) {
226a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                (*it2)->stop();
227a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            }
228a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
229a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            return err;
230a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
231a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
232a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    return OK;
233a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
234a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
2352dec2b5be2056c6d9428897dc672185872d30d17James Dongint64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) {
2362dec2b5be2056c6d9428897dc672185872d30d17James Dong    // This implementation is highly experimental/heurisitic.
2372dec2b5be2056c6d9428897dc672185872d30d17James Dong    //
2382dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Statistical analysis shows that metadata usually accounts
2392dec2b5be2056c6d9428897dc672185872d30d17James Dong    // for a small portion of the total file size, usually < 0.6%.
2402dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Currently, lets set to 0.4% for now.
2412dec2b5be2056c6d9428897dc672185872d30d17James Dong
2422dec2b5be2056c6d9428897dc672185872d30d17James Dong    // The default MIN_MOOV_BOX_SIZE is set to 0.4% x 1MB,
2432dec2b5be2056c6d9428897dc672185872d30d17James Dong    // where 1MB is the common file size limit for MMS application.
2442dec2b5be2056c6d9428897dc672185872d30d17James Dong    // The default MAX _MOOV_BOX_SIZE value is based on about 4
2452dec2b5be2056c6d9428897dc672185872d30d17James Dong    // minute video recording with a bit rate about 3 Mbps, because
2462dec2b5be2056c6d9428897dc672185872d30d17James Dong    // statistics also show that most of the video captured are going
2472dec2b5be2056c6d9428897dc672185872d30d17James Dong    // to be less than 3 minutes.
2482dec2b5be2056c6d9428897dc672185872d30d17James Dong
2492dec2b5be2056c6d9428897dc672185872d30d17James Dong    // If the estimation is wrong, we will pay the price of wasting
2502dec2b5be2056c6d9428897dc672185872d30d17James Dong    // some reserved space. This should not happen so often statistically.
2512dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int32_t factor = mUse32BitOffset? 1: 2;
2522dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int64_t MIN_MOOV_BOX_SIZE = 4 * 1024;  // 4 KB
2532dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000);
2542dec2b5be2056c6d9428897dc672185872d30d17James Dong    int64_t size = MIN_MOOV_BOX_SIZE;
2552dec2b5be2056c6d9428897dc672185872d30d17James Dong
2562dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (mMaxFileSizeLimitBytes != 0) {
2572dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = mMaxFileSizeLimitBytes * 4 / 1000;
2582dec2b5be2056c6d9428897dc672185872d30d17James Dong    } else if (mMaxFileDurationLimitUs != 0) {
2592dec2b5be2056c6d9428897dc672185872d30d17James Dong        if (bitRate <= 0) {
2602dec2b5be2056c6d9428897dc672185872d30d17James Dong            // We could not estimate the file size since bitRate is not set.
2612dec2b5be2056c6d9428897dc672185872d30d17James Dong            size = MIN_MOOV_BOX_SIZE;
2622dec2b5be2056c6d9428897dc672185872d30d17James Dong        } else {
2632dec2b5be2056c6d9428897dc672185872d30d17James Dong            size = ((mMaxFileDurationLimitUs * bitRate * 4) / 1000 / 8000000);
2642dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
2652dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
2662dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size < MIN_MOOV_BOX_SIZE) {
2672dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MIN_MOOV_BOX_SIZE;
2682dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
2692dec2b5be2056c6d9428897dc672185872d30d17James Dong
2702dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Any long duration recording will be probably end up with
2712dec2b5be2056c6d9428897dc672185872d30d17James Dong    // non-streamable mp4 file.
2722dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size > MAX_MOOV_BOX_SIZE) {
2732dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MAX_MOOV_BOX_SIZE;
2742dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
2752dec2b5be2056c6d9428897dc672185872d30d17James Dong
2762dec2b5be2056c6d9428897dc672185872d30d17James Dong    LOGI("limits: %lld/%lld bytes/us, bit rate: %d bps and the estimated"
2772dec2b5be2056c6d9428897dc672185872d30d17James Dong         " moov size %lld bytes",
2782dec2b5be2056c6d9428897dc672185872d30d17James Dong         mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size);
2792dec2b5be2056c6d9428897dc672185872d30d17James Dong    return factor * size;
2802dec2b5be2056c6d9428897dc672185872d30d17James Dong}
2812dec2b5be2056c6d9428897dc672185872d30d17James Dong
2822dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t MPEG4Writer::start(MetaData *param) {
28320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mFile == NULL) {
28425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return UNKNOWN_ERROR;
28520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
28620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2872dec2b5be2056c6d9428897dc672185872d30d17James Dong    int32_t use64BitOffset;
2882dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (param &&
2892dec2b5be2056c6d9428897dc672185872d30d17James Dong        param->findInt32(kKey64BitFileOffset, &use64BitOffset) &&
2902dec2b5be2056c6d9428897dc672185872d30d17James Dong        use64BitOffset) {
2912dec2b5be2056c6d9428897dc672185872d30d17James Dong        mUse32BitOffset = false;
2922dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
2932dec2b5be2056c6d9428897dc672185872d30d17James Dong
2942dec2b5be2056c6d9428897dc672185872d30d17James Dong    // System property can overwrite the file offset bits parameter
2952dec2b5be2056c6d9428897dc672185872d30d17James Dong    char value[PROPERTY_VALUE_MAX];
2962dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (property_get("media.stagefright.record-64bits", value, NULL)
2972dec2b5be2056c6d9428897dc672185872d30d17James Dong        && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
2982dec2b5be2056c6d9428897dc672185872d30d17James Dong        mUse32BitOffset = false;
2992dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
3002dec2b5be2056c6d9428897dc672185872d30d17James Dong
301065d1aff96818df54456053f1574aec8a234d0deJames Dong    mStartTimestampUs = -1;
30293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
303a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (mStarted) {
304a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused) {
305a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mPaused = false;
30693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            return startTracks(param);
307a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
308a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
309a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
310a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
3118f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    if (!param ||
3128f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        !param->findInt32(kKeyTimeScale, &mTimeScale)) {
3138f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        mTimeScale = 1000;
3148f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    }
3158f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    CHECK(mTimeScale > 0);
3168f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    LOGV("movie time scale: %d", mTimeScale);
3178f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
3187837c17063a4c50bc856ba59418516fdab731de7James Dong    mStreamableFile = true;
3197837c17063a4c50bc856ba59418516fdab731de7James Dong    mWriteMoovBoxToMemory = false;
3207837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBuffer = NULL;
3217837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
3227837c17063a4c50bc856ba59418516fdab731de7James Dong
32320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    beginBox("ftyp");
32493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong      {
32593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        int32_t fileType;
32693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (param && param->findInt32(kKeyFileType, &fileType) &&
32793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            fileType != OUTPUT_FORMAT_MPEG_4) {
32893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            writeFourcc("3gp4");
32993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        } else {
33093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            writeFourcc("isom");
33193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
33293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong      }
33320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      writeInt32(0);
33420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      writeFourcc("isom");
33593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong      writeFourcc("3gp4");
33620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    endBox();
33720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3387837c17063a4c50bc856ba59418516fdab731de7James Dong    mFreeBoxOffset = mOffset;
33920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3407837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mEstimatedMoovBoxSize == 0) {
3412dec2b5be2056c6d9428897dc672185872d30d17James Dong        int32_t bitRate = -1;
3422dec2b5be2056c6d9428897dc672185872d30d17James Dong        if (param) {
3432dec2b5be2056c6d9428897dc672185872d30d17James Dong            param->findInt32(kKeyBitRate, &bitRate);
3442dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
3452dec2b5be2056c6d9428897dc672185872d30d17James Dong        mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate);
3467837c17063a4c50bc856ba59418516fdab731de7James Dong    }
3477837c17063a4c50bc856ba59418516fdab731de7James Dong    CHECK(mEstimatedMoovBoxSize >= 8);
3487837c17063a4c50bc856ba59418516fdab731de7James Dong    fseeko(mFile, mFreeBoxOffset, SEEK_SET);
3497837c17063a4c50bc856ba59418516fdab731de7James Dong    writeInt32(mEstimatedMoovBoxSize);
3507837c17063a4c50bc856ba59418516fdab731de7James Dong    write("free", 4);
3517837c17063a4c50bc856ba59418516fdab731de7James Dong
3527837c17063a4c50bc856ba59418516fdab731de7James Dong    mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize;
3537837c17063a4c50bc856ba59418516fdab731de7James Dong    mOffset = mMdatOffset;
3547837c17063a4c50bc856ba59418516fdab731de7James Dong    fseeko(mFile, mMdatOffset, SEEK_SET);
3551acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
3561acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("????mdat", 8);
3571acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
3581acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("\x00\x00\x00\x01mdat????????", 16);
3591acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
3601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
3611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    status_t err = startWriterThread();
3621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (err != OK) {
3631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        return err;
3641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
3651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
3661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    err = startTracks(param);
367a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (err != OK) {
368a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return err;
36920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
3701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
371a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mStarted = true;
37225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
37320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
37420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
375a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dongvoid MPEG4Writer::pause() {
376a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (mFile == NULL) {
377a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return;
378a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
379a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
380a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
381a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
382a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        (*it)->pause();
383a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
384a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
385a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
3861c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::stopWriterThread() {
3871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("stopWriterThread");
3881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
3891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    {
3901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        Mutex::Autolock autolock(mLock);
3911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
3921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mDone = true;
3931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkReadyCondition.signal();
3941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
3951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
3961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void *dummy;
3971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_join(mThread, &dummy);
3981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
3991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
40020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::stop() {
40120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mFile == NULL) {
40220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return;
40320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
40420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4058f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t maxDurationUs = 0;
40620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
40720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber         it != mTracks.end(); ++it) {
40820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        (*it)->stop();
40920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4108f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int64_t durationUs = (*it)->getDurationUs();
4118f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        if (durationUs > maxDurationUs) {
4128f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            maxDurationUs = durationUs;
41320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
41420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
41520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    stopWriterThread();
4177837c17063a4c50bc856ba59418516fdab731de7James Dong
41820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // Fix up the size of the 'mdat' chunk.
4191acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
4201acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        fseeko(mFile, mMdatOffset, SEEK_SET);
4211acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        int32_t size = htonl(static_cast<int32_t>(mOffset - mMdatOffset));
4221acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        fwrite(&size, 1, 4, mFile);
4231acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
4241acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        fseeko(mFile, mMdatOffset + 8, SEEK_SET);
4251acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        int64_t size = mOffset - mMdatOffset;
4261acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        size = hton64(size);
4271acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        fwrite(&size, 1, 8, mFile);
4281acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
4297837c17063a4c50bc856ba59418516fdab731de7James Dong    fseeko(mFile, mOffset, SEEK_SET);
43020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
43120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    time_t now = time(NULL);
4327837c17063a4c50bc856ba59418516fdab731de7James Dong    const off_t moovOffset = mOffset;
4337837c17063a4c50bc856ba59418516fdab731de7James Dong    mWriteMoovBoxToMemory = true;
4347837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize);
4357837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
4367837c17063a4c50bc856ba59418516fdab731de7James Dong    CHECK(mMoovBoxBuffer != NULL);
4378f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int32_t duration = (maxDurationUs * mTimeScale) / 1E6;
43820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
43920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    beginBox("moov");
44020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
44120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      beginBox("mvhd");
44220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // version=0, flags=0
44320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(now);           // creation time
44420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(now);           // modification time
4458f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        writeInt32(mTimeScale);    // mvhd timescale
4461acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        writeInt32(duration);
4471acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        writeInt32(0x10000);       // rate: 1.0
44820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt16(0x100);         // volume
44920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt16(0);             // reserved
45020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // reserved
45120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // reserved
45220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0x10000);       // matrix
45320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
45420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
45520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
45620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0x10000);
45720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
45820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
45920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
46020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0x40000000);
46120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
46220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
46320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
46420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
46520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
46620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
46720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(mTracks.size() + 1);  // nextTrackID
46820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      endBox();  // mvhd
46920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
47020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      int32_t id = 1;
47120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      for (List<Track *>::iterator it = mTracks.begin();
47220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber           it != mTracks.end(); ++it, ++id) {
4731acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          (*it)->writeTrackHeader(id, mUse32BitOffset);
47420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      }
47520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    endBox();  // moov
47620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4777837c17063a4c50bc856ba59418516fdab731de7James Dong    mWriteMoovBoxToMemory = false;
4787837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mStreamableFile) {
4797837c17063a4c50bc856ba59418516fdab731de7James Dong        CHECK(mMoovBoxBufferOffset + 8 <= mEstimatedMoovBoxSize);
4807837c17063a4c50bc856ba59418516fdab731de7James Dong
4817837c17063a4c50bc856ba59418516fdab731de7James Dong        // Moov box
4827837c17063a4c50bc856ba59418516fdab731de7James Dong        fseeko(mFile, mFreeBoxOffset, SEEK_SET);
4837837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset = mFreeBoxOffset;
4847837c17063a4c50bc856ba59418516fdab731de7James Dong        write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, mFile);
4857837c17063a4c50bc856ba59418516fdab731de7James Dong
4867837c17063a4c50bc856ba59418516fdab731de7James Dong        // Free box
4872dec2b5be2056c6d9428897dc672185872d30d17James Dong        fseeko(mFile, mOffset, SEEK_SET);
4887837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset);
4897837c17063a4c50bc856ba59418516fdab731de7James Dong        write("free", 4);
4907837c17063a4c50bc856ba59418516fdab731de7James Dong
4917837c17063a4c50bc856ba59418516fdab731de7James Dong        // Free temp memory
4927837c17063a4c50bc856ba59418516fdab731de7James Dong        free(mMoovBoxBuffer);
4937837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBuffer = NULL;
4947837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBufferOffset = 0;
4952dec2b5be2056c6d9428897dc672185872d30d17James Dong    } else {
4962dec2b5be2056c6d9428897dc672185872d30d17James Dong        LOGI("The mp4 file will not be streamable.");
4977837c17063a4c50bc856ba59418516fdab731de7James Dong    }
4987837c17063a4c50bc856ba59418516fdab731de7James Dong
4990c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(mBoxes.empty());
50020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5017837c17063a4c50bc856ba59418516fdab731de7James Dong    fflush(mFile);
50220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fclose(mFile);
50320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mFile = NULL;
504a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mStarted = false;
50520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
50620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
50713aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) {
50813aec890216948b0c364f8f92792129d0335f506James Dong    mInterleaveDurationUs = durationUs;
50913aec890216948b0c364f8f92792129d0335f506James Dong    return OK;
51013aec890216948b0c364f8f92792129d0335f506James Dong}
51113aec890216948b0c364f8f92792129d0335f506James Dong
51213aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() {
51313aec890216948b0c364f8f92792129d0335f506James Dong    mLock.lock();
51413aec890216948b0c364f8f92792129d0335f506James Dong}
51513aec890216948b0c364f8f92792129d0335f506James Dong
51613aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() {
51713aec890216948b0c364f8f92792129d0335f506James Dong    mLock.unlock();
51813aec890216948b0c364f8f92792129d0335f506James Dong}
51920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
52013aec890216948b0c364f8f92792129d0335f506James Dongoff_t MPEG4Writer::addSample_l(MediaBuffer *buffer) {
52120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    off_t old_offset = mOffset;
52220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
52320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fwrite((const uint8_t *)buffer->data() + buffer->range_offset(),
52420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber           1, buffer->range_length(), mFile);
52520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
52620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += buffer->range_length();
52720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
52820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return old_offset;
52920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
53020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
53103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) {
53203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (buffer->range_length() < 4) {
53303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return;
53403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
53503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
53603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    const uint8_t *ptr =
53703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        (const uint8_t *)buffer->data() + buffer->range_offset();
53803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
53903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) {
54003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        buffer->set_range(
54103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                buffer->range_offset() + 4, buffer->range_length() - 4);
54203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
54303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
54403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
54513aec890216948b0c364f8f92792129d0335f506James Dongoff_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) {
54630ab66297501757d745b9ae10da61adcd891f497Andreas Huber    off_t old_offset = mOffset;
54730ab66297501757d745b9ae10da61adcd891f497Andreas Huber
54830ab66297501757d745b9ae10da61adcd891f497Andreas Huber    size_t length = buffer->range_length();
54903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
55003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR
55103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    uint8_t x = length >> 24;
55203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    fwrite(&x, 1, 1, mFile);
55303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    x = (length >> 16) & 0xff;
55403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    fwrite(&x, 1, 1, mFile);
55503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    x = (length >> 8) & 0xff;
55603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    fwrite(&x, 1, 1, mFile);
55703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    x = length & 0xff;
55803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    fwrite(&x, 1, 1, mFile);
55903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else
56030ab66297501757d745b9ae10da61adcd891f497Andreas Huber    CHECK(length < 65536);
56130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
56230ab66297501757d745b9ae10da61adcd891f497Andreas Huber    uint8_t x = length >> 8;
56330ab66297501757d745b9ae10da61adcd891f497Andreas Huber    fwrite(&x, 1, 1, mFile);
56430ab66297501757d745b9ae10da61adcd891f497Andreas Huber    x = length & 0xff;
56530ab66297501757d745b9ae10da61adcd891f497Andreas Huber    fwrite(&x, 1, 1, mFile);
56603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif
56730ab66297501757d745b9ae10da61adcd891f497Andreas Huber
56830ab66297501757d745b9ae10da61adcd891f497Andreas Huber    fwrite((const uint8_t *)buffer->data() + buffer->range_offset(),
56930ab66297501757d745b9ae10da61adcd891f497Andreas Huber           1, length, mFile);
57030ab66297501757d745b9ae10da61adcd891f497Andreas Huber
57103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR
57203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    mOffset += length + 4;
57303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else
57430ab66297501757d745b9ae10da61adcd891f497Andreas Huber    mOffset += length + 2;
57503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif
57630ab66297501757d745b9ae10da61adcd891f497Andreas Huber
57730ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return old_offset;
57830ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
57930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
5807837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write(
5817837c17063a4c50bc856ba59418516fdab731de7James Dong        const void *ptr, size_t size, size_t nmemb, FILE *stream) {
5827837c17063a4c50bc856ba59418516fdab731de7James Dong
5837837c17063a4c50bc856ba59418516fdab731de7James Dong    const size_t bytes = size * nmemb;
5847837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
5851acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        off_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes;
5861acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        if (moovBoxSize > mEstimatedMoovBoxSize) {
5877837c17063a4c50bc856ba59418516fdab731de7James Dong            for (List<off_t>::iterator it = mBoxes.begin();
5887837c17063a4c50bc856ba59418516fdab731de7James Dong                 it != mBoxes.end(); ++it) {
5897837c17063a4c50bc856ba59418516fdab731de7James Dong                (*it) += mOffset;
5907837c17063a4c50bc856ba59418516fdab731de7James Dong            }
5917837c17063a4c50bc856ba59418516fdab731de7James Dong            fseeko(mFile, mOffset, SEEK_SET);
5927837c17063a4c50bc856ba59418516fdab731de7James Dong            fwrite(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, stream);
5937837c17063a4c50bc856ba59418516fdab731de7James Dong            fwrite(ptr, size, nmemb, stream);
5947837c17063a4c50bc856ba59418516fdab731de7James Dong            mOffset += (bytes + mMoovBoxBufferOffset);
5957837c17063a4c50bc856ba59418516fdab731de7James Dong            free(mMoovBoxBuffer);
5967837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBuffer = NULL;
5977837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset = 0;
5987837c17063a4c50bc856ba59418516fdab731de7James Dong            mWriteMoovBoxToMemory = false;
5997837c17063a4c50bc856ba59418516fdab731de7James Dong            mStreamableFile = false;
6007837c17063a4c50bc856ba59418516fdab731de7James Dong        } else {
6017837c17063a4c50bc856ba59418516fdab731de7James Dong            memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes);
6027837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset += bytes;
6037837c17063a4c50bc856ba59418516fdab731de7James Dong        }
6047837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
6057837c17063a4c50bc856ba59418516fdab731de7James Dong        fwrite(ptr, size, nmemb, stream);
6067837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset += bytes;
6077837c17063a4c50bc856ba59418516fdab731de7James Dong    }
6087837c17063a4c50bc856ba59418516fdab731de7James Dong    return bytes;
6097837c17063a4c50bc856ba59418516fdab731de7James Dong}
6107837c17063a4c50bc856ba59418516fdab731de7James Dong
61120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) {
6120c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(fourcc), 4);
61320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6147837c17063a4c50bc856ba59418516fdab731de7James Dong    mBoxes.push_back(mWriteMoovBoxToMemory?
6157837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset: mOffset);
61620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
61720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeInt32(0);
61820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeFourcc(fourcc);
61920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
62020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
62120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() {
6220c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(!mBoxes.empty());
62320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
62420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    off_t offset = *--mBoxes.end();
62520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mBoxes.erase(--mBoxes.end());
62620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6277837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
6287837c17063a4c50bc856ba59418516fdab731de7James Dong       int32_t x = htonl(mMoovBoxBufferOffset - offset);
6297837c17063a4c50bc856ba59418516fdab731de7James Dong       memcpy(mMoovBoxBuffer + offset, &x, 4);
6307837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
6317837c17063a4c50bc856ba59418516fdab731de7James Dong        fseeko(mFile, offset, SEEK_SET);
6327837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mOffset - offset);
6337837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset -= 4;
6347837c17063a4c50bc856ba59418516fdab731de7James Dong        fseeko(mFile, mOffset, SEEK_SET);
6357837c17063a4c50bc856ba59418516fdab731de7James Dong    }
63620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
63720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
63820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) {
6397837c17063a4c50bc856ba59418516fdab731de7James Dong    write(&x, 1, 1, mFile);
64020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
64120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
64220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) {
64320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htons(x);
6447837c17063a4c50bc856ba59418516fdab731de7James Dong    write(&x, 1, 2, mFile);
64520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
64620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
64720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) {
64820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htonl(x);
6497837c17063a4c50bc856ba59418516fdab731de7James Dong    write(&x, 1, 4, mFile);
65020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
65120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
65220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) {
65320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = hton64(x);
6547837c17063a4c50bc856ba59418516fdab731de7James Dong    write(&x, 1, 8, mFile);
65520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
65620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
65720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) {
65820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t n = strlen(s);
6597837c17063a4c50bc856ba59418516fdab731de7James Dong    write(s, 1, n + 1, mFile);
66020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
66120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
66220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) {
6630c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(s), 4);
6647837c17063a4c50bc856ba59418516fdab731de7James Dong    write(s, 1, 4, mFile);
66520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
66620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
66720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) {
6687837c17063a4c50bc856ba59418516fdab731de7James Dong    write(data, 1, size, mFile);
66920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
67020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
671d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() {
672d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
673d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileSizeLimitBytes == 0) {
674d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
675d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
676d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
677956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize);
678d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
679d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
680d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes();
681d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
682d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return (nTotalBytesEstimate >= mMaxFileSizeLimitBytes);
683d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
684d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
685d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() {
686d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
687d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileDurationLimitUs == 0) {
688d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
689d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
690d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
691d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
692d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
693d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) {
694d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            return true;
695d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
696d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
697d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return false;
698d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
699d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
70025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() {
70125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool allDone = true;
70225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
70325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber         it != mTracks.end(); ++it) {
70425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        if (!(*it)->reachedEOS()) {
70525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            allDone = false;
70625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            break;
70725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        }
70825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
70925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
71025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return allDone;
71125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
71225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
713f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) {
714f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    LOGI("setStartTimestampUs: %lld", timeUs);
715f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    CHECK(timeUs >= 0);
7163c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
717065d1aff96818df54456053f1574aec8a234d0deJames Dong    if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) {
718f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mStartTimestampUs = timeUs;
719f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        LOGI("Earliest track starting time: %lld", mStartTimestampUs);
7203c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    }
7213c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
7223c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
723f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() {
7243c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
7253c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    return mStartTimestampUs;
7263c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
7273c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
72858ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() {
72958ae9c530247668f8af36e30d228c716c226b3d4James Dong    Mutex::Autolock autolock(mLock);
73058ae9c530247668f8af36e30d228c716c226b3d4James Dong    return mTracks.size();
73158ae9c530247668f8af36e30d228c716c226b3d4James Dong}
73258ae9c530247668f8af36e30d228c716c226b3d4James Dong
73320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
73420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
73520111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track(
73625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        MPEG4Writer *owner, const sp<MediaSource> &source)
73720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mOwner(owner),
73825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mMeta(source->getFormat()),
73920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSource(source),
74020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDone(false),
741a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
742a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mResumed(false),
743c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong      mTrackDurationUs(0),
744956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      mEstimatedTrackSizeBytes(0),
745be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong      mSamplesHaveSameSize(true),
74620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCodecSpecificData(NULL),
74725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mCodecSpecificDataSize(0),
748548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber      mGotAllCodecSpecificData(false),
74925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mReachedEOS(false) {
75019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    getCodecSpecificDataFromInputFormatIfPossible();
7518f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
7528f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    if (!mMeta->findInt32(kKeyTimeScale, &mTimeScale)) {
7538f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        mTimeScale = 1000;
7548f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    }
7551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
7561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    const char *mime;
7571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mMeta->findCString(kKeyMIMEType, &mime);
7581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
7591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAudio = !strncasecmp(mime, "audio/", 6);
7601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
7611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong               !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC);
7621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
7638f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    CHECK(mTimeScale > 0);
76419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber}
76519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
76619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Hubervoid MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() {
76719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    const char *mime;
76819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
76919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
77019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
77119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        uint32_t type;
77219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        const void *data;
77319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        size_t size;
77419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        if (mMeta->findData(kKeyAVCC, &type, &data, &size)) {
77519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mCodecSpecificData = malloc(size);
77619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mCodecSpecificDataSize = size;
77719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            memcpy(mCodecSpecificData, data, size);
77819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mGotAllCodecSpecificData = true;
77919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        }
78019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
78119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
78219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        uint32_t type;
78319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        const void *data;
78419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        size_t size;
78519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        if (mMeta->findData(kKeyESDS, &type, &data, &size)) {
78619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            ESDS esds(data, size);
78719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            if (esds.getCodecSpecificInfo(&data, &size) == OK) {
78819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mCodecSpecificData = malloc(size);
78919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mCodecSpecificDataSize = size;
79019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                memcpy(mCodecSpecificData, data, size);
79119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mGotAllCodecSpecificData = true;
79219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            }
79319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        }
79419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
79520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
79620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
79720111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() {
79820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    stop();
79920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
80020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mCodecSpecificData != NULL) {
80120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        free(mCodecSpecificData);
80220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mCodecSpecificData = NULL;
80320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
80420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
80520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
80693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) {
80793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    LOGV("initTrackingProgressStatus");
80893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mPreviousTrackTimeUs = -1;
80993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackingProgressStatus = false;
81093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackEveryTimeDurationUs = 0;
81193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    {
81293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        int64_t timeUs;
81393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) {
81493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            LOGV("Receive request to track progress status for every %lld us", timeUs);
81593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackEveryTimeDurationUs = timeUs;
81693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackingProgressStatus = true;
81793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
81893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
81993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
82093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
8211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong// static
8221c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid *MPEG4Writer::ThreadWrapper(void *me) {
8231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("ThreadWrapper: %p", me);
8241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    MPEG4Writer *writer = static_cast<MPEG4Writer *>(me);
8251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    writer->threadFunc();
8261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return NULL;
8271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
8281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8291c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::bufferChunk(const Chunk& chunk) {
8301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("bufferChunk: %p", chunk.mTrack);
8311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Mutex::Autolock autolock(mLock);
8321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    CHECK_EQ(mDone, false);
8331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
8351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
8361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (chunk.mTrack == it->mTrack) {  // Found owner
8381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            it->mChunks.push_back(chunk);
8391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.signal();
8401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            return;
8411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
8421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
8431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    CHECK("Received a chunk for a unknown track" == 0);
8451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
8461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8471c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::writeFirstChunk(ChunkInfo* info) {
8481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("writeFirstChunk: %p", info->mTrack);
8491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    List<Chunk>::iterator chunkIt = info->mChunks.begin();
8511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<MediaBuffer *>::iterator it = chunkIt->mSamples.begin();
8521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != chunkIt->mSamples.end(); ++it) {
8531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        off_t offset = info->mTrack->isAvc()
8551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                            ? addLengthPrefixedSample_l(*it)
8561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                            : addSample_l(*it);
8571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (it == chunkIt->mSamples.begin()) {
8581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            info->mTrack->addChunkOffset(offset);
8591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
8601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
8611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    // Done with the current chunk.
8631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    // Release all the samples in this chunk.
8641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    while (!chunkIt->mSamples.empty()) {
8651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        List<MediaBuffer *>::iterator it = chunkIt->mSamples.begin();
8661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it)->release();
8671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it) = NULL;
8681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        chunkIt->mSamples.erase(it);
8691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
8701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    chunkIt->mSamples.clear();
8711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    info->mChunks.erase(chunkIt);
8721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
8731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8741c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::writeChunks() {
8751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("writeChunks");
8761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    size_t outstandingChunks = 0;
8771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    while (!mChunkInfos.empty()) {
8781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        List<ChunkInfo>::iterator it = mChunkInfos.begin();
8791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        while (!it->mChunks.empty()) {
8801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            CHECK_EQ(OK, writeOneChunk());
8811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            ++outstandingChunks;
8821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
8831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        it->mTrack = NULL;
8841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkInfos.erase(it);
8851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
8861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mChunkInfos.clear();
8871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGD("%d chunks are written in the last batch", outstandingChunks);
8881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
8891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8901c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::writeOneChunk() {
8911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("writeOneChunk");
8921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    // Find the smallest timestamp, and write that chunk out
8941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    // XXX: What if some track is just too slow?
8951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL;
8961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Track *track = NULL;
8971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
8981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
8991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (!it->mChunks.empty()) {
9001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            List<Chunk>::iterator chunkIt = it->mChunks.begin();
9011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (chunkIt->mTimeStampUs < minTimestampUs) {
9021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                minTimestampUs = chunkIt->mTimeStampUs;
9031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                track = it->mTrack;
9041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            }
9051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
9061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
9071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
9081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (track == NULL) {
9091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        LOGV("Nothing to be written after all");
9101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        return OK;
9111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
9121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
9131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (mIsFirstChunk) {
9141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsFirstChunk = false;
9151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
9161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
9171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
9181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (it->mTrack == track) {
9191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            writeFirstChunk(&(*it));
9201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
9211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
9221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return OK;
9231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
9241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
9251c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::threadFunc() {
9261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("threadFunc");
9271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
9281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    while (!mDone) {
9291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        {
9301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            Mutex::Autolock autolock(mLock);
9311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.wait(mLock);
9321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            CHECK_EQ(writeOneChunk(), OK);
9331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
9341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
9351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
9361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    {
9371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        // Write ALL samples
9381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        Mutex::Autolock autolock(mLock);
9391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        writeChunks();
9401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
9411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
9421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
9431c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::startWriterThread() {
9441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("startWriterThread");
9451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
9461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mDone = false;
9471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsFirstChunk = true;
948e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    mDriftTimeUs = 0;
9491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<Track *>::iterator it = mTracks.begin();
9501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mTracks.end(); ++it) {
9511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        ChunkInfo info;
9521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        info.mTrack = *it;
9531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkInfos.push_back(info);
9541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
9551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
9561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_t attr;
9571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_init(&attr);
9581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
9591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_create(&mThread, &attr, ThreadWrapper, this);
9601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_destroy(&attr);
9611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return OK;
9621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
9631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
96493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) {
965a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (!mDone && mPaused) {
966a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mPaused = false;
967a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mResumed = true;
968a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
969a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
97025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
97193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t startTimeUs;
97219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) {
97319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        startTimeUs = 0;
97419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
97519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
976e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    mIsRealTimeRecording = true;
977e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    {
978e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        int32_t isNotRealTime;
979e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        if (params && params->findInt32(kKeyNotRealTime, &isNotRealTime)) {
980e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            mIsRealTimeRecording = (isNotRealTime == 0);
981e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        }
982e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    }
983e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
98493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    initTrackingProgressStatus(params);
98593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
986f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    sp<MetaData> meta = new MetaData;
987f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    meta->setInt64(kKeyTime, startTimeUs);
988f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    status_t err = mSource->start(meta.get());
98925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    if (err != OK) {
99025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        mDone = mReachedEOS = true;
99125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return err;
99225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
99320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
99420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_t attr;
99520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_init(&attr);
99620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
99720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
99820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = false;
999c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs = 0;
100025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = false;
1001956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    mEstimatedTrackSizeBytes = 0;
100220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
100325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    pthread_create(&mThread, &attr, ThreadWrapper, this);
100420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_destroy(&attr);
100525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
100625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
100720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
100820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1009a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dongvoid MPEG4Writer::Track::pause() {
1010a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
1011a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
1012a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
101320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::Track::stop() {
101420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mDone) {
101520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return;
101620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
101720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
101820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = true;
101920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
102020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *dummy;
102120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_join(mThread, &dummy);
102220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
102320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mSource->stop();
102420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
102520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
102625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() {
102725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return mReachedEOS;
102825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
102925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
103020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static
103120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) {
103220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = static_cast<Track *>(me);
103320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
103420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    track->threadEntry();
103520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
103620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return NULL;
103720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
103820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1039548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber#include <ctype.h>
1040548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huberstatic void hexdump(const void *_data, size_t size) {
1041548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    const uint8_t *data = (const uint8_t *)_data;
1042548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    size_t offset = 0;
1043548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    while (offset < size) {
1044548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        printf("0x%04x  ", offset);
1045548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
1046548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        size_t n = size - offset;
1047548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        if (n > 16) {
1048548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            n = 16;
1049548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        }
1050548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
1051548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        for (size_t i = 0; i < 16; ++i) {
1052548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            if (i == 8) {
1053548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber                printf(" ");
1054548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            }
1055548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
1056548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            if (offset + i < size) {
1057548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber                printf("%02x ", data[offset + i]);
1058548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            } else {
1059548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber                printf("   ");
1060548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            }
1061548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        }
1062548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
1063548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        printf(" ");
1064548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
1065548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        for (size_t i = 0; i < n; ++i) {
1066548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            if (isprint(data[offset + i])) {
1067548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber                printf("%c", data[offset + i]);
1068548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            } else {
1069548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber                printf(".");
1070548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            }
1071548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        }
1072548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
1073548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        printf("\n");
1074548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
1075548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        offset += 16;
1076548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    }
1077548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber}
1078548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
10793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic void getNalUnitType(uint8_t byte, uint8_t* type) {
10803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    LOGV("getNalUnitType: %d", byte);
10813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
10823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // nal_unit_type: 5-bit unsigned integer
10833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *type = (byte & 0x1F);
10843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
10853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
10863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t *findNextStartCode(
10873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length) {
10883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
10893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    LOGV("findNextStartCode: %p %d", data, length);
10903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
10913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t bytesLeft = length;
10923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    while (bytesLeft > 4  &&
10933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            memcmp("\x00\x00\x00\x01", &data[length - bytesLeft], 4)) {
10943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        --bytesLeft;
10953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
10963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (bytesLeft <= 4) {
10973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        bytesLeft = 0; // Last parameter set
10983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
10993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return &data[length - bytesLeft];
11003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
11013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
11023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongconst uint8_t *MPEG4Writer::Track::parseParamSet(
11033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen) {
11043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
11053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    LOGV("parseParamSet");
11063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    CHECK(type == kNalUnitTypeSeqParamSet ||
11073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong          type == kNalUnitTypePicParamSet);
11083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
11093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *nextStartCode = findNextStartCode(data, length);
11103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *paramSetLen = nextStartCode - data;
11113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (*paramSetLen == 0) {
11123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        LOGE("Param set is malformed, since its length is 0");
11133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return NULL;
11143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
11153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
11163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    AVCParamSet paramSet(*paramSetLen, data);
11173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (type == kNalUnitTypeSeqParamSet) {
11183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (*paramSetLen < 4) {
11193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Seq parameter set malformed");
11203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return NULL;
11213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
11223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mSeqParamSets.empty()) {
11233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc = data[1];
11243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileCompatible = data[2];
11253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mLevelIdc = data[3];
11263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
11273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (mProfileIdc != data[1] ||
11283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mProfileCompatible != data[2] ||
11293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mLevelIdc != data[3]) {
11303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                LOGE("Inconsistent profile/level found in seq parameter sets");
11313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return NULL;
11323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
11333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
11343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mSeqParamSets.push_back(paramSet);
11353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    } else {
11363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mPicParamSets.push_back(paramSet);
11373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
11383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return nextStartCode;
11393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
11403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
11413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::copyAVCCodecSpecificData(
11423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
11433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    LOGV("copyAVCCodecSpecificData");
11443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
11453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 2 bytes for each of the parameter set length field
11463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // plus the 7 bytes for the header
11473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (size < 4 + 7) {
11483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        LOGE("Codec specific data length too short: %d", size);
11493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return ERROR_MALFORMED;
11503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
11513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
11523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize = size;
11533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificData = malloc(size);
11543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    memcpy(mCodecSpecificData, data, size);
11553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
11563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
11573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
11583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::parseAVCCodecSpecificData(
11593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
11603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
11613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    LOGV("parseAVCCodecSpecificData");
11623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data starts with a start code.
11633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // SPS and PPS are separated with start codes.
11643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Also, SPS must come before PPS
11653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t type = kNalUnitTypeSeqParamSet;
11663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotSps = false;
11673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotPps = false;
11683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *tmp = data;
11693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *nextStartCode = data;
11703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t bytesLeft = size;
11713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t paramSetLen = 0;
11723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize = 0;
11733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) {
11743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        getNalUnitType(*(tmp + 4), &type);
11753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (type == kNalUnitTypeSeqParamSet) {
11763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (gotPps) {
11773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                LOGE("SPS must come before PPS");
11783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
11793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
11803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
11813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotSps = true;
11823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
11833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
11843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else if (type == kNalUnitTypePicParamSet) {
11853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
11863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                LOGE("SPS must come before PPS");
11873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
11883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
11893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotPps) {
11903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotPps = true;
11913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
11923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
11933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
11943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Only SPS and PPS Nal units are expected");
11953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
11963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
11973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
11983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nextStartCode == NULL) {
11993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
12003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
12013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
12023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Move on to find the next parameter set
12033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        bytesLeft -= nextStartCode - tmp;
12043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        tmp = nextStartCode;
12053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mCodecSpecificDataSize += (2 + paramSetLen);
12063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
12073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
12083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
12093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of seq parameter sets
12103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nSeqParamSets = mSeqParamSets.size();
12113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets == 0) {
12123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Cound not find sequence parameter set");
12133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
12143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
12153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
12163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets > 0x1F) {
12173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Too many seq parameter sets (%d) found", nSeqParamSets);
12183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
12193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
12203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
12213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
12223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
12233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of pic parameter sets
12243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nPicParamSets = mPicParamSets.size();
12253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets == 0) {
12263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Cound not find picture parameter set");
12273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
12283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
12293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets > 0xFF) {
12303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Too many pic parameter sets (%d) found", nPicParamSets);
12313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
12323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
12333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
12343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
12353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
12363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the profiles
12373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // These profiles requires additional parameter set extensions
12383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mProfileIdc == 100 || mProfileIdc == 110 ||
12393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc == 122 || mProfileIdc == 144) {
12403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Sorry, no support for profile_idc: %d!", mProfileIdc);
12413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return BAD_VALUE;
12423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
12433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
12443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
12453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
12463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
1247548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
124803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData(
124903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        const uint8_t *data, size_t size) {
1250548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    // hexdump(data, size);
1251548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
125203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (mCodecSpecificData != NULL) {
1253548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        LOGE("Already have codec specific data");
125403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
125503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
125603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
12573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (size < 4) {
12583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        LOGE("Codec specific data length too short: %d", size);
125903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
126003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
126103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
12623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data is in the form of AVCCodecSpecificData
12633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (memcmp("\x00\x00\x00\x01", data, 4)) {
12643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return copyAVCCodecSpecificData(data, size);
126503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
126603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
12673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (parseAVCCodecSpecificData(data, size) != OK) {
126803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
126903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
127003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
12713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // ISO 14496-15: AVC file format
12723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize += 7;  // 7 more bytes in the header
127303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    mCodecSpecificData = malloc(mCodecSpecificDataSize);
127403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    uint8_t *header = (uint8_t *)mCodecSpecificData;
12753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = 1;                     // version
12763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[1] = mProfileIdc;           // profile indication
12773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[2] = mProfileCompatible;    // profile compatibility
12783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[3] = mLevelIdc;
127903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
12803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne
128103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR
128203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[4] = 0xfc | 3;  // length size == 4 bytes
128303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else
128403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[4] = 0xfc | 1;  // length size == 2 bytes
128503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif
128603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
12873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 3-bit '111' followed by 5-bit numSequenceParameterSets
12883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nSequenceParamSets = mSeqParamSets.size();
12893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[5] = 0xe0 | nSequenceParamSets;
12903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 6;
12913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mSeqParamSets.begin();
12923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mSeqParamSets.end(); ++it) {
12933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit sequence parameter set length
12943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t seqParamSetLength = it->mLength;
12953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = seqParamSetLength >> 8;
12963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = seqParamSetLength & 0xff;
12973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
12983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // SPS NAL unit (sequence parameter length bytes)
12993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, seqParamSetLength);
13003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + seqParamSetLength);
13013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
13023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 8-bit nPictureParameterSets
13043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nPictureParamSets = mPicParamSets.size();
13053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = nPictureParamSets;
13063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 1;
13073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mPicParamSets.begin();
13083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mPicParamSets.end(); ++it) {
13093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit picture parameter set length
13103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t picParamSetLength = it->mLength;
13113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = picParamSetLength >> 8;
13123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = picParamSetLength & 0xff;
13133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // PPS Nal unit (picture parameter set length bytes)
13153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, picParamSetLength);
13163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + picParamSetLength);
13173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
131803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
131903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    return OK;
132003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
132103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
13228644c14618d30d9e57a69df40ed939986ebf02c4James Dongstatic bool collectStatisticalData() {
13238644c14618d30d9e57a69df40ed939986ebf02c4James Dong    char value[PROPERTY_VALUE_MAX];
13248644c14618d30d9e57a69df40ed939986ebf02c4James Dong    if (property_get("media.stagefright.record-stats", value, NULL)
13258644c14618d30d9e57a69df40ed939986ebf02c4James Dong        && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
13268644c14618d30d9e57a69df40ed939986ebf02c4James Dong        return true;
13278644c14618d30d9e57a69df40ed939986ebf02c4James Dong    }
13288644c14618d30d9e57a69df40ed939986ebf02c4James Dong    return false;
13298644c14618d30d9e57a69df40ed939986ebf02c4James Dong}
13308644c14618d30d9e57a69df40ed939986ebf02c4James Dong
133120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::Track::threadEntry() {
133230ab66297501757d745b9ae10da61adcd891f497Andreas Huber    int32_t count = 0;
133313aec890216948b0c364f8f92792129d0335f506James Dong    const int64_t interleaveDurationUs = mOwner->interleaveDuration();
133413aec890216948b0c364f8f92792129d0335f506James Dong    int64_t chunkTimestampUs = 0;
133513aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nChunks = 0;
133613aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nZeroLengthFrames = 0;
13378f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t lastTimestampUs = 0;  // Previous sample time stamp in ms
13388f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t lastDurationUs = 0;   // Between the previous two samples in ms
13398f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int32_t sampleCount = 1;      // Sample count in the current stts table entry
1340be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    uint32_t previousSampleSize = 0;  // Size of the previous sample
1341a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    int64_t previousPausedDurationUs = 0;
13421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    int64_t timestampUs;
1343e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
1344e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    int64_t wallClockTimeUs = 0;
1345e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    int64_t lastWallClockTimeUs = 0;
1346e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
1347d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong    sp<MetaData> meta_data;
13488644c14618d30d9e57a69df40ed939986ebf02c4James Dong    bool collectStats = collectStatisticalData();
134920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1350ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    mNumSamples = 0;
13511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mMaxWriteTimeUs = 0;
135293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t err = OK;
135320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBuffer *buffer;
135493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    while (!mDone && (err = mSource->read(&buffer)) == OK) {
135520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (buffer->range_length() == 0) {
135620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer->release();
135720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer = NULL;
135813aec890216948b0c364f8f92792129d0335f506James Dong            ++nZeroLengthFrames;
135920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            continue;
136020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
136120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1362a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // If the codec specific data has not been received yet, delay pause.
1363a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // After the codec specific data is received, discard what we received
1364a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // when the track is to be paused.
1365a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused && !mResumed) {
1366a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer->release();
1367a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer = NULL;
1368a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            continue;
1369a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
1370a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
137130ab66297501757d745b9ae10da61adcd891f497Andreas Huber        ++count;
137230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
137303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        int32_t isCodecConfig;
137403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig)
137503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                && isCodecConfig) {
1376548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            CHECK(!mGotAllCodecSpecificData);
1377548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
13781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (mIsAvc) {
137903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                status_t err = makeAVCCodecSpecificData(
138003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        (const uint8_t *)buffer->data()
138103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                            + buffer->range_offset(),
138203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        buffer->range_length());
1383be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                CHECK_EQ(OK, err);
13841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            } else if (mIsMPEG4) {
138503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificDataSize = buffer->range_length();
138603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificData = malloc(mCodecSpecificDataSize);
138703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                memcpy(mCodecSpecificData,
138803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        (const uint8_t *)buffer->data()
138903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                            + buffer->range_offset(),
139003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                       buffer->range_length());
139130ab66297501757d745b9ae10da61adcd891f497Andreas Huber            }
139230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
139330ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer->release();
139430ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer = NULL;
139530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
1396548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            mGotAllCodecSpecificData = true;
139730ab66297501757d745b9ae10da61adcd891f497Andreas Huber            continue;
1398a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
1399a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
1400d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // Make a deep copy of the MediaBuffer and Metadata and release
1401d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // the original as soon as we can
1402d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        MediaBuffer *copy = new MediaBuffer(buffer->range_length());
1403d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(),
1404d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong                buffer->range_length());
1405d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        copy->set_range(0, buffer->range_length());
1406d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data = new MetaData(*buffer->meta_data().get());
1407d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer->release();
1408d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer = NULL;
1409d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
14101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (mIsAvc) StripStartcode(copy);
1411e136c3bb38e88315bf8797a464ebf2c788296b22James Dong
14128644c14618d30d9e57a69df40ed939986ebf02c4James Dong        size_t sampleSize;
14131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        sampleSize = mIsAvc
141403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR
1415d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong                ? copy->range_length() + 4
141603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else
1417d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong                ? copy->range_length() + 2
141803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif
1419d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong                : copy->range_length();
1420050b28a593350047845a45a14cc5026221ac1620James Dong
1421d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        // Max file size or duration handling
14228644c14618d30d9e57a69df40ed939986ebf02c4James Dong        mEstimatedTrackSizeBytes += sampleSize;
1423d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileSizeLimit()) {
1424d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
1425d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
1426d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
1427d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileDurationLimit()) {
1428d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
1429d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
1430d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
1431d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1432050b28a593350047845a45a14cc5026221ac1620James Dong
1433d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        int32_t isSync = false;
1434d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data->findInt32(kKeyIsSyncFrame, &isSync);
1435d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
1436d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        CHECK(meta_data->findInt64(kKeyTime, &timestampUs));
1437d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
1438d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong////////////////////////////////////////////////////////////////////////////////
14398644c14618d30d9e57a69df40ed939986ebf02c4James Dong        if (mSampleSizes.empty()) {
1440f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mStartTimestampUs = timestampUs;
1441f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mOwner->setStartTimestampUs(mStartTimestampUs);
14423c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        }
144348c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber
1444a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mResumed) {
1445c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong            previousPausedDurationUs += (timestampUs - mTrackDurationUs - lastDurationUs);
1446a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mResumed = false;
1447a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
1448a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
1449a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        timestampUs -= previousPausedDurationUs;
1450e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        if (mIsRealTimeRecording && !mIsAudio) {
1451e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            // The minor adjustment on the timestamp is heuristic/experimental
1452e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            // We are adjusting the timestamp to reduce the fluctuation of the duration
1453e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            // of neighboring samples. This in turn helps reduce the track header size,
1454e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            // especially, the number of entries in the "stts" box.
1455e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            if (mNumSamples > 1) {
1456e259531ce59ab1f31de5a23124b22536f6a5a767James Dong                int64_t durationUs = timestampUs + mOwner->getDriftTimeUs() - lastTimestampUs;
1457e259531ce59ab1f31de5a23124b22536f6a5a767James Dong                int64_t diffUs = (durationUs > lastDurationUs)
1458e259531ce59ab1f31de5a23124b22536f6a5a767James Dong                            ? durationUs - lastDurationUs
1459e259531ce59ab1f31de5a23124b22536f6a5a767James Dong                            : lastDurationUs - durationUs;
1460e259531ce59ab1f31de5a23124b22536f6a5a767James Dong                if (diffUs <= 5000) {  // XXX: Magic number 5ms
1461e259531ce59ab1f31de5a23124b22536f6a5a767James Dong                    timestampUs = lastTimestampUs + lastDurationUs;
1462e259531ce59ab1f31de5a23124b22536f6a5a767James Dong                } else {
1463e259531ce59ab1f31de5a23124b22536f6a5a767James Dong                    timestampUs += mOwner->getDriftTimeUs();
1464e259531ce59ab1f31de5a23124b22536f6a5a767James Dong                }
1465e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            }
1466e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        }
1467e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        CHECK(timestampUs >= 0);
1468e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        if (mNumSamples > 1) {
1469e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            if (timestampUs <= lastTimestampUs) {
1470e259531ce59ab1f31de5a23124b22536f6a5a767James Dong                LOGW("Drop a frame, since it arrives too late!");
1471e259531ce59ab1f31de5a23124b22536f6a5a767James Dong                copy->release();
1472e259531ce59ab1f31de5a23124b22536f6a5a767James Dong                copy = NULL;
1473e259531ce59ab1f31de5a23124b22536f6a5a767James Dong                continue;
1474e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            }
1475e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        }
1476e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
1477a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        LOGV("time stamp: %lld and previous paused duration %lld",
1478a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                timestampUs, previousPausedDurationUs);
1479c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong        if (timestampUs > mTrackDurationUs) {
1480c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong            mTrackDurationUs = timestampUs;
14813b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber        }
14823b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber
14838644c14618d30d9e57a69df40ed939986ebf02c4James Dong        mSampleSizes.push_back(sampleSize);
1484ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong        ++mNumSamples;
1485ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong        if (mNumSamples > 2) {
14868644c14618d30d9e57a69df40ed939986ebf02c4James Dong            if (lastDurationUs != timestampUs - lastTimestampUs) {
14878f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong                SttsTableEntry sttsEntry(sampleCount, lastDurationUs);
1488be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mSttsTableEntries.push_back(sttsEntry);
1489be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                sampleCount = 1;
1490be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            } else {
1491be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                ++sampleCount;
1492be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
1493be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
1494be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        if (mSamplesHaveSameSize) {
1495ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong            if (mNumSamples >= 2 && previousSampleSize != sampleSize) {
1496be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mSamplesHaveSameSize = false;
1497be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
14988644c14618d30d9e57a69df40ed939986ebf02c4James Dong            previousSampleSize = sampleSize;
1499be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
15008644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastDurationUs = timestampUs - lastTimestampUs;
15018644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastTimestampUs = timestampUs;
1502e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        if (mIsRealTimeRecording && mIsAudio) {
1503e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            wallClockTimeUs = systemTime() / 1000;
1504e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            int64_t wallClockDurationUs = wallClockTimeUs - lastWallClockTimeUs;
1505e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            if (mNumSamples > 2) {
1506e259531ce59ab1f31de5a23124b22536f6a5a767James Dong                mOwner->addDriftTimeUs(lastDurationUs - wallClockDurationUs);
1507e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            }
1508e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            lastWallClockTimeUs = wallClockTimeUs;
1509e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        }
151020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1511d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        if (isSync != 0) {
1512ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong            mStssTableEntries.push_back(mNumSamples);
1513d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        }
1514d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
151593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (mTrackingProgressStatus) {
151693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            if (mPreviousTrackTimeUs <= 0) {
151793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong                mPreviousTrackTimeUs = mStartTimestampUs;
151893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            }
1519faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong            trackProgressStatus(timestampUs);
152093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
152158ae9c530247668f8af36e30d228c716c226b3d4James Dong        if (mOwner->numTracks() == 1) {
15221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            off_t offset = mIsAvc? mOwner->addLengthPrefixedSample_l(copy)
152358ae9c530247668f8af36e30d228c716c226b3d4James Dong                                 : mOwner->addSample_l(copy);
152458ae9c530247668f8af36e30d228c716c226b3d4James Dong            if (mChunkOffsets.empty()) {
152558ae9c530247668f8af36e30d228c716c226b3d4James Dong                mChunkOffsets.push_back(offset);
152658ae9c530247668f8af36e30d228c716c226b3d4James Dong            }
152758ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy->release();
152858ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy = NULL;
152958ae9c530247668f8af36e30d228c716c226b3d4James Dong            continue;
153058ae9c530247668f8af36e30d228c716c226b3d4James Dong        }
153113aec890216948b0c364f8f92792129d0335f506James Dong
153213aec890216948b0c364f8f92792129d0335f506James Dong        mChunkSamples.push_back(copy);
153313aec890216948b0c364f8f92792129d0335f506James Dong        if (interleaveDurationUs == 0) {
153413aec890216948b0c364f8f92792129d0335f506James Dong            StscTableEntry stscEntry(++nChunks, 1, 1);
153513aec890216948b0c364f8f92792129d0335f506James Dong            mStscTableEntries.push_back(stscEntry);
15361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            bufferChunk(timestampUs);
153713aec890216948b0c364f8f92792129d0335f506James Dong        } else {
153813aec890216948b0c364f8f92792129d0335f506James Dong            if (chunkTimestampUs == 0) {
153913aec890216948b0c364f8f92792129d0335f506James Dong                chunkTimestampUs = timestampUs;
154013aec890216948b0c364f8f92792129d0335f506James Dong            } else {
154113aec890216948b0c364f8f92792129d0335f506James Dong                if (timestampUs - chunkTimestampUs > interleaveDurationUs) {
154213aec890216948b0c364f8f92792129d0335f506James Dong                    ++nChunks;
15438644c14618d30d9e57a69df40ed939986ebf02c4James Dong                    if (collectStats) {
15448644c14618d30d9e57a69df40ed939986ebf02c4James Dong                        mChunkDurations.push_back(timestampUs - chunkTimestampUs);
15458644c14618d30d9e57a69df40ed939986ebf02c4James Dong                    }
154613aec890216948b0c364f8f92792129d0335f506James Dong                    if (nChunks == 1 ||  // First chunk
154713aec890216948b0c364f8f92792129d0335f506James Dong                        (--(mStscTableEntries.end()))->samplesPerChunk !=
154813aec890216948b0c364f8f92792129d0335f506James Dong                         mChunkSamples.size()) {
154913aec890216948b0c364f8f92792129d0335f506James Dong                        StscTableEntry stscEntry(nChunks,
155013aec890216948b0c364f8f92792129d0335f506James Dong                                mChunkSamples.size(), 1);
155113aec890216948b0c364f8f92792129d0335f506James Dong                        mStscTableEntries.push_back(stscEntry);
155213aec890216948b0c364f8f92792129d0335f506James Dong                    }
15531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                    bufferChunk(timestampUs);
155413aec890216948b0c364f8f92792129d0335f506James Dong                    chunkTimestampUs = timestampUs;
155513aec890216948b0c364f8f92792129d0335f506James Dong                }
155613aec890216948b0c364f8f92792129d0335f506James Dong            }
155713aec890216948b0c364f8f92792129d0335f506James Dong        }
155813aec890216948b0c364f8f92792129d0335f506James Dong
155920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
156025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
15618644c14618d30d9e57a69df40ed939986ebf02c4James Dong    if (mSampleSizes.empty()) {
156293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        err = UNKNOWN_ERROR;
1563f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong    }
1564faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    mOwner->trackProgressStatus(this, -1, err);
1565be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
156613aec890216948b0c364f8f92792129d0335f506James Dong    // Last chunk
156758ae9c530247668f8af36e30d228c716c226b3d4James Dong    if (mOwner->numTracks() == 1) {
1568ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong        StscTableEntry stscEntry(1, mNumSamples, 1);
156958ae9c530247668f8af36e30d228c716c226b3d4James Dong        mStscTableEntries.push_back(stscEntry);
157058ae9c530247668f8af36e30d228c716c226b3d4James Dong    } else if (!mChunkSamples.empty()) {
157113aec890216948b0c364f8f92792129d0335f506James Dong        ++nChunks;
157213aec890216948b0c364f8f92792129d0335f506James Dong        StscTableEntry stscEntry(nChunks, mChunkSamples.size(), 1);
157313aec890216948b0c364f8f92792129d0335f506James Dong        mStscTableEntries.push_back(stscEntry);
15741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        bufferChunk(timestampUs);
157513aec890216948b0c364f8f92792129d0335f506James Dong    }
157613aec890216948b0c364f8f92792129d0335f506James Dong
1577be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // We don't really know how long the last frame lasts, since
1578be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // there is no frame time after it, just repeat the previous
1579be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // frame's duration.
1580ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    if (mNumSamples == 1) {
15818f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        lastDurationUs = 0;  // A single sample's duration
1582be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    } else {
1583be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        ++sampleCount;  // Count for the last sample
1584be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    }
15858f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    SttsTableEntry sttsEntry(sampleCount, lastDurationUs);
1586be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    mSttsTableEntries.push_back(sttsEntry);
1587c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs += lastDurationUs;
158825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = true;
15891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. Max write time: %lld us - %s",
15901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            count, nZeroLengthFrames, mNumSamples, mMaxWriteTimeUs, mIsAudio? "audio": "video");
1591365a963142093a1cd8efdcea76b5f65096a5b115James Dong
15921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    logStatisticalData(mIsAudio);
1593365a963142093a1cd8efdcea76b5f65096a5b115James Dong}
1594365a963142093a1cd8efdcea76b5f65096a5b115James Dong
1595faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) {
1596faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    LOGV("trackProgressStatus: %lld us", timeUs);
1597215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    if (mTrackEveryTimeDurationUs > 0 &&
1598215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) {
159993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        LOGV("Fire time tracking progress status at %lld us", timeUs);
1600faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        mOwner->trackProgressStatus(this, timeUs - mPreviousTrackTimeUs, err);
160193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        mPreviousTrackTimeUs = timeUs;
160293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
160393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
160493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
1605faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::trackProgressStatus(
1606faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        const MPEG4Writer::Track* track, int64_t timeUs, status_t err) {
1607faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    Mutex::Autolock lock(mLock);
1608faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    int32_t nTracks = mTracks.size();
1609faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    CHECK(nTracks >= 1);
1610faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    CHECK(nTracks < 64);  // Arbitrary number
1611faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
1612faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    int32_t trackNum = 0;
1613faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong#if 0
1614faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // In the worst case, we can put the trackNum
1615faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // along with MEDIA_RECORDER_INFO_COMPLETION_STATUS
1616faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // to report the progress.
1617faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    for (List<Track *>::iterator it = mTracks.begin();
1618faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong         it != mTracks.end(); ++it, ++trackNum) {
1619faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        if (track == (*it)) {
1620faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong            break;
1621faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        }
1622faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
1623faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong#endif
1624faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    CHECK(trackNum < nTracks);
1625faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    trackNum <<= 16;
1626faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
1627faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Error notification
1628faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Do not consider ERROR_END_OF_STREAM an error
1629faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (err != OK && err != ERROR_END_OF_STREAM) {
1630faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        notify(MEDIA_RECORDER_EVENT_ERROR,
1631faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               trackNum | MEDIA_RECORDER_ERROR_UNKNOWN,
1632faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
1633faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        return;
1634faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
1635faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
1636faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (timeUs == -1) {
1637faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send completion notification
1638faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        notify(MEDIA_RECORDER_EVENT_INFO,
1639faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               trackNum | MEDIA_RECORDER_INFO_COMPLETION_STATUS,
1640faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
1641faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        return;
1642faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    } else {
1643faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send progress status
1644faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        notify(MEDIA_RECORDER_EVENT_INFO,
1645faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               trackNum | MEDIA_RECORDER_INFO_PROGRESS_TIME_STATUS,
1646faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               timeUs / 1000);
1647faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
1648faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong}
1649faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
1650215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dongvoid MPEG4Writer::Track::findMinAvgMaxSampleDurationMs(
1651215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        int32_t *min, int32_t *avg, int32_t *max) {
16528644c14618d30d9e57a69df40ed939986ebf02c4James Dong    CHECK(!mSampleSizes.empty());
1653c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    int32_t avgSampleDurationMs = mTrackDurationUs / 1000 / mNumSamples;
1654215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    int32_t minSampleDurationMs = 0x7FFFFFFF;
1655215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    int32_t maxSampleDurationMs = 0;
1656365a963142093a1cd8efdcea76b5f65096a5b115James Dong    for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin();
1657365a963142093a1cd8efdcea76b5f65096a5b115James Dong        it != mSttsTableEntries.end(); ++it) {
16588f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int32_t sampleDurationMs =
16598f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            (static_cast<int32_t>(it->sampleDurationUs) + 500) / 1000;
1660215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        if (sampleDurationMs > maxSampleDurationMs) {
1661215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong            maxSampleDurationMs = sampleDurationMs;
1662215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        } else if (sampleDurationMs < minSampleDurationMs) {
1663215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong            minSampleDurationMs = sampleDurationMs;
1664365a963142093a1cd8efdcea76b5f65096a5b115James Dong        }
1665215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        LOGI("sample duration: %d ms", sampleDurationMs);
1666365a963142093a1cd8efdcea76b5f65096a5b115James Dong    }
1667215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    CHECK(minSampleDurationMs != 0);
1668215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    CHECK(avgSampleDurationMs != 0);
1669215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    CHECK(maxSampleDurationMs != 0);
1670215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    *min = minSampleDurationMs;
1671215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    *avg = avgSampleDurationMs;
1672215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    *max = maxSampleDurationMs;
1673365a963142093a1cd8efdcea76b5f65096a5b115James Dong}
1674365a963142093a1cd8efdcea76b5f65096a5b115James Dong
1675365a963142093a1cd8efdcea76b5f65096a5b115James Dong// Don't count the last duration
1676365a963142093a1cd8efdcea76b5f65096a5b115James Dongvoid MPEG4Writer::Track::findMinMaxChunkDurations(int64_t *min, int64_t *max) {
1677365a963142093a1cd8efdcea76b5f65096a5b115James Dong    int64_t duration = mOwner->interleaveDuration();
1678365a963142093a1cd8efdcea76b5f65096a5b115James Dong    int64_t minChunkDuration = duration;
1679365a963142093a1cd8efdcea76b5f65096a5b115James Dong    int64_t maxChunkDuration = duration;
1680365a963142093a1cd8efdcea76b5f65096a5b115James Dong    if (mChunkDurations.size() > 1) {
1681365a963142093a1cd8efdcea76b5f65096a5b115James Dong        for (List<int64_t>::iterator it = mChunkDurations.begin();
1682365a963142093a1cd8efdcea76b5f65096a5b115James Dong            it != --mChunkDurations.end(); ++it) {
1683365a963142093a1cd8efdcea76b5f65096a5b115James Dong            if (minChunkDuration > (*it)) {
1684365a963142093a1cd8efdcea76b5f65096a5b115James Dong                minChunkDuration = (*it);
1685365a963142093a1cd8efdcea76b5f65096a5b115James Dong            } else if (maxChunkDuration < (*it)) {
1686365a963142093a1cd8efdcea76b5f65096a5b115James Dong                maxChunkDuration = (*it);
1687365a963142093a1cd8efdcea76b5f65096a5b115James Dong            }
1688365a963142093a1cd8efdcea76b5f65096a5b115James Dong        }
1689365a963142093a1cd8efdcea76b5f65096a5b115James Dong    }
1690365a963142093a1cd8efdcea76b5f65096a5b115James Dong    *min = minChunkDuration;
1691365a963142093a1cd8efdcea76b5f65096a5b115James Dong    *max = maxChunkDuration;
1692365a963142093a1cd8efdcea76b5f65096a5b115James Dong}
1693365a963142093a1cd8efdcea76b5f65096a5b115James Dong
1694365a963142093a1cd8efdcea76b5f65096a5b115James Dongvoid MPEG4Writer::Track::logStatisticalData(bool isAudio) {
1695c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    if (mTrackDurationUs <= 0 || mSampleSizes.empty()) {
1696365a963142093a1cd8efdcea76b5f65096a5b115James Dong        LOGI("nothing is recorded");
1697365a963142093a1cd8efdcea76b5f65096a5b115James Dong        return;
1698365a963142093a1cd8efdcea76b5f65096a5b115James Dong    }
1699365a963142093a1cd8efdcea76b5f65096a5b115James Dong
17008644c14618d30d9e57a69df40ed939986ebf02c4James Dong    bool collectStats = collectStatisticalData();
1701365a963142093a1cd8efdcea76b5f65096a5b115James Dong
1702365a963142093a1cd8efdcea76b5f65096a5b115James Dong    if (collectStats) {
1703215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        LOGI("%s track - duration %lld us, total %d frames",
1704c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong                isAudio? "audio": "video", mTrackDurationUs,
1705ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong                mNumSamples);
1706215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        int32_t min, avg, max;
1707215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        findMinAvgMaxSampleDurationMs(&min, &avg, &max);
1708215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        LOGI("min/avg/max sample duration (ms): %d/%d/%d", min, avg, max);
1709215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        if (!isAudio) {
1710215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong            float avgFps = 1000.0 / avg;
1711215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong            float minFps = 1000.0 / max;
1712215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong            float maxFps = 1000.0 / min;
1713365a963142093a1cd8efdcea76b5f65096a5b115James Dong            LOGI("min/avg/max frame rate (fps): %.2f/%.2f/%.2f",
1714215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong                minFps, avgFps, maxFps);
1715365a963142093a1cd8efdcea76b5f65096a5b115James Dong        }
1716365a963142093a1cd8efdcea76b5f65096a5b115James Dong
1717365a963142093a1cd8efdcea76b5f65096a5b115James Dong        int64_t totalBytes = 0;
17188644c14618d30d9e57a69df40ed939986ebf02c4James Dong        for (List<size_t>::iterator it = mSampleSizes.begin();
17198644c14618d30d9e57a69df40ed939986ebf02c4James Dong            it != mSampleSizes.end(); ++it) {
17208644c14618d30d9e57a69df40ed939986ebf02c4James Dong            totalBytes += (*it);
1721365a963142093a1cd8efdcea76b5f65096a5b115James Dong        }
1722c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong        float bitRate = (totalBytes * 8000000.0) / mTrackDurationUs;
1723365a963142093a1cd8efdcea76b5f65096a5b115James Dong        LOGI("avg bit rate (bps): %.2f", bitRate);
1724365a963142093a1cd8efdcea76b5f65096a5b115James Dong
1725365a963142093a1cd8efdcea76b5f65096a5b115James Dong        int64_t duration = mOwner->interleaveDuration();
1726365a963142093a1cd8efdcea76b5f65096a5b115James Dong        if (duration != 0) {  // If interleaving is enabled
1727365a963142093a1cd8efdcea76b5f65096a5b115James Dong            int64_t minChunk, maxChunk;
1728365a963142093a1cd8efdcea76b5f65096a5b115James Dong            findMinMaxChunkDurations(&minChunk, &maxChunk);
1729365a963142093a1cd8efdcea76b5f65096a5b115James Dong            LOGI("min/avg/max chunk duration (ms): %lld/%lld/%lld",
1730365a963142093a1cd8efdcea76b5f65096a5b115James Dong                minChunk, duration, maxChunk);
1731365a963142093a1cd8efdcea76b5f65096a5b115James Dong        }
1732365a963142093a1cd8efdcea76b5f65096a5b115James Dong    }
173313aec890216948b0c364f8f92792129d0335f506James Dong}
173413aec890216948b0c364f8f92792129d0335f506James Dong
1735e259531ce59ab1f31de5a23124b22536f6a5a767James Dongvoid MPEG4Writer::addDriftTimeUs(int64_t driftTimeUs) {
1736e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    LOGV("addDriftTimeUs: %lld us", driftTimeUs);
1737e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
1738e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    mDriftTimeUs += driftTimeUs;
1739e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
1740e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
1741e259531ce59ab1f31de5a23124b22536f6a5a767James Dongint64_t MPEG4Writer::getDriftTimeUs() {
1742e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    LOGV("getDriftTimeUs: %lld us", mDriftTimeUs);
1743e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
1744e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    return mDriftTimeUs;
1745e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
1746e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
17471c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::Track::bufferChunk(int64_t timestampUs) {
17481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("bufferChunk");
17491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    int64_t startTimeUs = systemTime() / 1000;
17511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Chunk chunk(this, timestampUs, mChunkSamples);
17521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mOwner->bufferChunk(chunk);
175313aec890216948b0c364f8f92792129d0335f506James Dong    mChunkSamples.clear();
17541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    int64_t endTimeUs = systemTime() / 1000;
17551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (mMaxWriteTimeUs < endTimeUs - startTimeUs) {
17561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mMaxWriteTimeUs = endTimeUs - startTimeUs;
17571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
175820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
175920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
17603b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const {
1761c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    return mTrackDurationUs;
176220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
176320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1764d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const {
1765d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return mEstimatedTrackSizeBytes;
1766d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
1767d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
17681acfe8649f8169caf2ff098c2dc2de880d9a3760James Dongvoid MPEG4Writer::Track::writeTrackHeader(
17691acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        int32_t trackID, bool use32BitOffset) {
177020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const char *mime;
177120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool success = mMeta->findCString(kKeyMIMEType, &mime);
17720c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(success);
177320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
17748f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    LOGV("%s track time scale: %d",
17751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsAudio? "Audio": "Video", mTimeScale);
17768f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
177720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
177820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    time_t now = time(NULL);
17798f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int32_t mvhdTimeScale = mOwner->getTimeScale();
17808f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t trakDurationUs = getDurationUs();
178120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
178220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOwner->beginBox("trak");
178320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
178420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->beginBox("tkhd");
17851acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        // Flags = 7 to indicate that the track is enabled, and
17861acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        // part of the presentation
17871acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        mOwner->writeInt32(0x07);          // version=0, flags=7
178820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(now);           // creation time
178920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(now);           // modification time
179020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(trackID);
179120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);             // reserved
17928f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int32_t tkhdDuration =
17938f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
17948f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        mOwner->writeInt32(tkhdDuration);  // in mvhd timescale
179520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);             // reserved
179620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);             // reserved
179720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt16(0);             // layer
179820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt16(0);             // alternate group
17991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mOwner->writeInt16(mIsAudio ? 0x100 : 0);  // volume
180020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt16(0);             // reserved
180120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
180220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0x10000);       // matrix
180320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
180420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
180520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
180620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0x10000);
180720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
180820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
180920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
181020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0x40000000);
181120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
18121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (mIsAudio) {
181320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);
181420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);
181520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        } else {
181620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            int32_t width, height;
181720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            bool success = mMeta->findInt32(kKeyWidth, &width);
181820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            success = success && mMeta->findInt32(kKeyHeight, &height);
18190c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber            CHECK(success);
182020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1821050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->writeInt32(width << 16);   // 32-bit fixed-point value
1822050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->writeInt32(height << 16);  // 32-bit fixed-point value
182320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
182420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->endBox();  // tkhd
182520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1826f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong      int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
1827f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong      if (mStartTimestampUs != moovStartTimeUs) {
18283c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        mOwner->beginBox("edts");
18293c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong          mOwner->beginBox("elst");
18301acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong            mOwner->writeInt32(0);           // version=0, flags=0: 32-bit time
18311acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong            mOwner->writeInt32(2);           // never ends with an empty list
18328f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
18338f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            // First elst entry: specify the starting time offset
18348f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            int64_t offsetUs = mStartTimestampUs - moovStartTimeUs;
18358f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            int32_t seg = (offsetUs * mvhdTimeScale + 5E5) / 1E6;
18368f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            mOwner->writeInt32(seg);         // in mvhd timecale
18378f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            mOwner->writeInt32(-1);          // starting time offset
18388f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            mOwner->writeInt32(1 << 16);     // rate = 1.0
18398f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
18408f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            // Second elst entry: specify the track duration
18418f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            seg = (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
18428f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            mOwner->writeInt32(seg);         // in mvhd timescale
18431acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong            mOwner->writeInt32(0);
18441acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong            mOwner->writeInt32(1 << 16);
18453c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong          mOwner->endBox();
18463c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        mOwner->endBox();
18473c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong      }
18483c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
184920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->beginBox("mdia");
185020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
185120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("mdhd");
185220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // version=0, flags=0
185320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(now);           // creation time
185420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(now);           // modification time
18558f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong          mOwner->writeInt32(mTimeScale);    // media timescale
18568f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong          int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6;
18578f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong          mOwner->writeInt32(mdhdDuration);  // use media timescale
18581acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // Language follows the three letter standard ISO-639-2/T
18591acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // 'e', 'n', 'g' for "English", for instance.
18601acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // Each character is packed as the difference between its ASCII value and 0x60.
18611acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // For "English", these are 00101, 01110, 00111.
18621acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // XXX: Where is the padding bit located: 0x15C7?
18631acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          mOwner->writeInt16(0);             // language code
186420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt16(0);             // predefined
186520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->endBox();
186620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
186720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("hdlr");
186820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // version=0, flags=0
1869050b28a593350047845a45a14cc5026221ac1620James Dong          mOwner->writeInt32(0);             // component type: should be mhlr
18701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong          mOwner->writeFourcc(mIsAudio ? "soun" : "vide");  // component subtype
187120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // reserved
187220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // reserved
187320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // reserved
18741acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // Removing "r" for the name string just makes the string 4 byte aligned
18751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong          mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle");  // name
187620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->endBox();
187720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
187820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("minf");
18791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong          if (mIsAudio) {
188020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->beginBox("smhd");
188120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt32(0);           // version=0, flags=0
188220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // balance
188320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // reserved
188420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->endBox();
188520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          } else {
188620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->beginBox("vmhd");
18871acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong              mOwner->writeInt32(0x01);        // version=0, flags=1
188820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // graphics mode
188920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // opcolor
189020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);
189120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);
189220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->endBox();
189320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          }
1894050b28a593350047845a45a14cc5026221ac1620James Dong
1895050b28a593350047845a45a14cc5026221ac1620James Dong          mOwner->beginBox("dinf");
1896050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->beginBox("dref");
1897050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->writeInt32(0);  // version=0, flags=0
18981acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong              mOwner->writeInt32(1);  // entry count (either url or urn)
18991acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong              // The table index here refers to the sample description index
19001acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong              // in the sample table entries.
1901050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->beginBox("url ");
19021acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                mOwner->writeInt32(1);  // version=0, flags=1 (self-contained)
1903050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->endBox();  // url
1904050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->endBox();  // dref
1905050b28a593350047845a45a14cc5026221ac1620James Dong          mOwner->endBox();  // dinf
1906050b28a593350047845a45a14cc5026221ac1620James Dong
190720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("stbl");
190820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
190920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stsd");
191020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);               // version=0, flags=0
191120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(1);               // entry count
19121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (mIsAudio) {
191325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                const char *fourcc = NULL;
191418291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) {
191525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    fourcc = "samr";
191618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
191725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    fourcc = "sawb";
1918050b28a593350047845a45a14cc5026221ac1620James Dong                } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
1919050b28a593350047845a45a14cc5026221ac1620James Dong                    fourcc = "mp4a";
192025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                } else {
192125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    LOGE("Unknown mime type '%s'.", mime);
192225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    CHECK(!"should not be here, unknown mime type.");
192325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                }
192425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
192525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                mOwner->beginBox(fourcc);          // audio format
192620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
192720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
1928050b28a593350047845a45a14cc5026221ac1620James Dong                  mOwner->writeInt16(0x1);         // data ref index
192920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
193020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
1931050b28a593350047845a45a14cc5026221ac1620James Dong                  int32_t nChannels;
1932050b28a593350047845a45a14cc5026221ac1620James Dong                  CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels));
1933050b28a593350047845a45a14cc5026221ac1620James Dong                  mOwner->writeInt16(nChannels);   // channel count
193420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(16);          // sample size
193520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // predefined
193620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
193720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
193820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  int32_t samplerate;
193920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  bool success = mMeta->findInt32(kKeySampleRate, &samplerate);
19400c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                  CHECK(success);
194120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
194220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(samplerate << 16);
1943050b28a593350047845a45a14cc5026221ac1620James Dong                  if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
1944050b28a593350047845a45a14cc5026221ac1620James Dong                    mOwner->beginBox("esds");
194551dfe6d646ddcc5fc252aa4c19c9936d32af8ad7James Dong                        CHECK(mCodecSpecificData);
194651dfe6d646ddcc5fc252aa4c19c9936d32af8ad7James Dong                        CHECK(mCodecSpecificDataSize > 0);
1947050b28a593350047845a45a14cc5026221ac1620James Dong
1948050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt32(0);     // version=0, flags=0
1949050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x03);   // ES_DescrTag
1950050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(23 + mCodecSpecificDataSize);
1951050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt16(0x0000);// ES_ID
1952050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x00);
1953050b28a593350047845a45a14cc5026221ac1620James Dong
1954050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x04);   // DecoderConfigDescrTag
1955050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(15 + mCodecSpecificDataSize);
1956050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x40);   // objectTypeIndication ISO/IEC 14492-2
1957050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x15);   // streamType AudioStream
1958050b28a593350047845a45a14cc5026221ac1620James Dong
1959050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt16(0x03);  // XXX
1960050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x00);   // buffer size 24-bit
1961050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt32(96000); // max bit rate
1962050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt32(96000); // avg bit rate
1963050b28a593350047845a45a14cc5026221ac1620James Dong
1964050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x05);   // DecoderSpecificInfoTag
1965050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(mCodecSpecificDataSize);
1966050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
1967050b28a593350047845a45a14cc5026221ac1620James Dong
1968050b28a593350047845a45a14cc5026221ac1620James Dong                        static const uint8_t kData2[] = {
1969050b28a593350047845a45a14cc5026221ac1620James Dong                            0x06,  // SLConfigDescriptorTag
1970050b28a593350047845a45a14cc5026221ac1620James Dong                            0x01,
1971050b28a593350047845a45a14cc5026221ac1620James Dong                            0x02
1972050b28a593350047845a45a14cc5026221ac1620James Dong                        };
1973050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->write(kData2, sizeof(kData2));
1974050b28a593350047845a45a14cc5026221ac1620James Dong
1975050b28a593350047845a45a14cc5026221ac1620James Dong                    mOwner->endBox();  // esds
19765aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                  } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) ||
19775aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                             !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
19785aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                    // 3gpp2 Spec AMRSampleEntry fields
19795aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                    mOwner->beginBox("damr");
19805aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                      mOwner->writeCString("   ");  // vendor: 4 bytes
19815aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                      mOwner->writeInt8(0);         // decoder version
19825aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                      mOwner->writeInt16(0x83FF);   // mode set: all enabled
19835aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                      mOwner->writeInt8(0);         // mode change period
19845aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                      mOwner->writeInt8(1);         // frames per sample
19855aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                    mOwner->endBox();
1986050b28a593350047845a45a14cc5026221ac1620James Dong                  }
198720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mOwner->endBox();
198820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
198918291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
199020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    mOwner->beginBox("mp4v");
199118291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
199220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    mOwner->beginBox("s263");
199330ab66297501757d745b9ae10da61adcd891f497Andreas Huber                } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
199430ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    mOwner->beginBox("avc1");
199520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                } else {
199625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    LOGE("Unknown mime type '%s'.", mime);
19970c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                    CHECK(!"should not be here, unknown mime type.");
199820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
199920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
200020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
200120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
20021acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                  mOwner->writeInt16(1);           // data ref index
200320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // predefined
200420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
200520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // predefined
200620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // predefined
200720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // predefined
200820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
200920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  int32_t width, height;
201020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  bool success = mMeta->findInt32(kKeyWidth, &width);
201120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  success = success && mMeta->findInt32(kKeyHeight, &height);
20120c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                  CHECK(success);
201320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
201420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(width);
201520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(height);
201620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0x480000);    // horiz resolution
201720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0x480000);    // vert resolution
201820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
201920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(1);           // frame count
202020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->write("                                ", 32);
202120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0x18);        // depth
202220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(-1);          // predefined
202320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
20240c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                  CHECK(23 + mCodecSpecificDataSize < 128);
202520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
202618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                  if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
2027a37923e9a57d489e7bed2129369219039fa5f12cJames Dong                      CHECK(mCodecSpecificData);
2028a37923e9a57d489e7bed2129369219039fa5f12cJames Dong                      CHECK(mCodecSpecificDataSize > 0);
202920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->beginBox("esds");
203020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
203120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt32(0);           // version=0, flags=0
203220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
203320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x03);  // ES_DescrTag
203420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(23 + mCodecSpecificDataSize);
203520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt16(0x0000);  // ES_ID
203620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x1f);
203720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
203820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x04);  // DecoderConfigDescrTag
203920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(15 + mCodecSpecificDataSize);
204020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x20);  // objectTypeIndication ISO/IEC 14492-2
204120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x11);  // streamType VisualStream
204220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
204320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        static const uint8_t kData[] = {
204420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x01, 0x77, 0x00,
204520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x00, 0x03, 0xe8, 0x00,
204620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x00, 0x03, 0xe8, 0x00
204720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        };
204820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->write(kData, sizeof(kData));
2049050b28a593350047845a45a14cc5026221ac1620James Dong
205020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x05);  // DecoderSpecificInfoTag
205120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
205220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(mCodecSpecificDataSize);
205320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
205420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
205520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        static const uint8_t kData2[] = {
205620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x06,  // SLConfigDescriptorTag
205720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x01,
205820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x02
205920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        };
206020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->write(kData2, sizeof(kData2));
206120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
206220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->endBox();  // esds
206318291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                  } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
206420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->beginBox("d263");
206520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
206620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt32(0);  // vendor
206720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt8(0);   // decoder version
206820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt8(10);  // level: 10
206920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt8(0);   // profile: 0
207020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
207120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->endBox();  // d263
207230ab66297501757d745b9ae10da61adcd891f497Andreas Huber                  } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
207351dfe6d646ddcc5fc252aa4c19c9936d32af8ad7James Dong                      CHECK(mCodecSpecificData);
207451dfe6d646ddcc5fc252aa4c19c9936d32af8ad7James Dong                      CHECK(mCodecSpecificDataSize > 0);
207530ab66297501757d745b9ae10da61adcd891f497Andreas Huber                      mOwner->beginBox("avcC");
207630ab66297501757d745b9ae10da61adcd891f497Andreas Huber                        mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
207730ab66297501757d745b9ae10da61adcd891f497Andreas Huber                      mOwner->endBox();  // avcC
207820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  }
207930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
20801acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                  mOwner->beginBox("pasp");
20811acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                    // This is useful if the pixel is not square
20821acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                    mOwner->writeInt32(1 << 16);  // hspacing
20831acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                    mOwner->writeInt32(1 << 16);  // vspacing
20841acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                  mOwner->endBox();  // pasp
208530ab66297501757d745b9ae10da61adcd891f497Andreas Huber                mOwner->endBox();  // mp4v, s263 or avc1
208620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
208720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stsd
208820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
208920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stts");
209020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
2091be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            mOwner->writeInt32(mSttsTableEntries.size());
2092be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin();
2093be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                 it != mSttsTableEntries.end(); ++it) {
2094be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mOwner->writeInt32(it->sampleCount);
20958f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong                int32_t dur = (it->sampleDurationUs * mTimeScale + 5E5) / 1E6;
20968f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong                mOwner->writeInt32(dur);
209720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
209820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stts
209920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
21001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong          if (!mIsAudio) {
2101050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->beginBox("stss");
2102050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->writeInt32(0);  // version=0, flags=0
2103050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->writeInt32(mStssTableEntries.size());  // number of sync frames
2104050b28a593350047845a45a14cc5026221ac1620James Dong              for (List<int32_t>::iterator it = mStssTableEntries.begin();
2105050b28a593350047845a45a14cc5026221ac1620James Dong                   it != mStssTableEntries.end(); ++it) {
2106050b28a593350047845a45a14cc5026221ac1620James Dong                  mOwner->writeInt32(*it);
2107050b28a593350047845a45a14cc5026221ac1620James Dong              }
2108050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->endBox();  // stss
2109050b28a593350047845a45a14cc5026221ac1620James Dong          }
2110050b28a593350047845a45a14cc5026221ac1620James Dong
211120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stsz");
211220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
2113be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            if (mSamplesHaveSameSize) {
21148644c14618d30d9e57a69df40ed939986ebf02c4James Dong                List<size_t>::iterator it = mSampleSizes.begin();
21158644c14618d30d9e57a69df40ed939986ebf02c4James Dong                mOwner->writeInt32(*it);  // default sample size
2116be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            } else {
2117be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mOwner->writeInt32(0);
2118be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
2119ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong            mOwner->writeInt32(mNumSamples);
2120be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            if (!mSamplesHaveSameSize) {
21218644c14618d30d9e57a69df40ed939986ebf02c4James Dong                for (List<size_t>::iterator it = mSampleSizes.begin();
21228644c14618d30d9e57a69df40ed939986ebf02c4James Dong                     it != mSampleSizes.end(); ++it) {
21238644c14618d30d9e57a69df40ed939986ebf02c4James Dong                    mOwner->writeInt32(*it);
2124be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                }
212520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
212620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stsz
212720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
212820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stsc");
212920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
213013aec890216948b0c364f8f92792129d0335f506James Dong            mOwner->writeInt32(mStscTableEntries.size());
213113aec890216948b0c364f8f92792129d0335f506James Dong            for (List<StscTableEntry>::iterator it = mStscTableEntries.begin();
213213aec890216948b0c364f8f92792129d0335f506James Dong                 it != mStscTableEntries.end(); ++it) {
213313aec890216948b0c364f8f92792129d0335f506James Dong                mOwner->writeInt32(it->firstChunk);
213413aec890216948b0c364f8f92792129d0335f506James Dong                mOwner->writeInt32(it->samplesPerChunk);
213513aec890216948b0c364f8f92792129d0335f506James Dong                mOwner->writeInt32(it->sampleDescriptionId);
213620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
213720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stsc
21381acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          mOwner->beginBox(use32BitOffset? "stco": "co64");
213920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
214013aec890216948b0c364f8f92792129d0335f506James Dong            mOwner->writeInt32(mChunkOffsets.size());
214113aec890216948b0c364f8f92792129d0335f506James Dong            for (List<off_t>::iterator it = mChunkOffsets.begin();
214213aec890216948b0c364f8f92792129d0335f506James Dong                 it != mChunkOffsets.end(); ++it) {
21431acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                if (use32BitOffset) {
21441acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                    mOwner->writeInt32(static_cast<int32_t>(*it));
21451acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                } else {
21461acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                    mOwner->writeInt64((*it));
21471acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                }
214820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
21498f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong          mOwner->endBox();  // stco or co64
215020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
215120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->endBox();  // stbl
21521acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong       mOwner->endBox();  // minf
215320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->endBox();  // mdia
215420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOwner->endBox();  // trak
215520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
215620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
215720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
2158