MPEG4Writer.cpp revision c5f0c714dc4225cd2ec305d5ddd297964a3dd3dc
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
4120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Writer::Track {
4220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic:
4325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    Track(MPEG4Writer *owner, const sp<MediaSource> &source);
448f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
4520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    ~Track();
4620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t start(MetaData *params);
4820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void stop();
49a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    void pause();
5025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool reachedEOS();
5120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
523b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber    int64_t getDurationUs() const;
53d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t getEstimatedTrackSizeBytes() const;
541acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    void writeTrackHeader(int32_t trackID, bool use32BitOffset = true);
551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void bufferChunk(int64_t timestampUs);
561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isAvc() const { return mIsAvc; }
571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isAudio() const { return mIsAudio; }
581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isMPEG4() const { return mIsMPEG4; }
591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void addChunkOffset(off_t offset) { mChunkOffsets.push_back(offset); }
6020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate:
6220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Writer *mOwner;
6320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MetaData> mMeta;
64693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    sp<MediaSource> mSource;
6520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    volatile bool mDone;
66a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mPaused;
67a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mResumed;
681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAvc;
691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAudio;
701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsMPEG4;
71c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    int64_t mTrackDurationUs;
72d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t mEstimatedTrackSizeBytes;
731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    int64_t mMaxWriteTimeUs;
748f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int32_t mTimeScale;
7520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_t mThread;
7720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
78ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    // mNumSamples is used to track how many samples in mSampleSizes List.
79ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    // This is to reduce the cost associated with mSampleSizes.size() call,
80ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    // since it is O(n). Ideally, the fix should be in List class.
81ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    size_t              mNumSamples;
828644c14618d30d9e57a69df40ed939986ebf02c4James Dong    List<size_t>        mSampleSizes;
83be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    bool                mSamplesHaveSameSize;
84be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
8513aec890216948b0c364f8f92792129d0335f506James Dong    List<MediaBuffer *> mChunkSamples;
8613aec890216948b0c364f8f92792129d0335f506James Dong    List<off_t>         mChunkOffsets;
8713aec890216948b0c364f8f92792129d0335f506James Dong
8813aec890216948b0c364f8f92792129d0335f506James Dong    struct StscTableEntry {
8913aec890216948b0c364f8f92792129d0335f506James Dong
9013aec890216948b0c364f8f92792129d0335f506James Dong        StscTableEntry(uint32_t chunk, uint32_t samples, uint32_t id)
9113aec890216948b0c364f8f92792129d0335f506James Dong            : firstChunk(chunk),
9213aec890216948b0c364f8f92792129d0335f506James Dong              samplesPerChunk(samples),
9313aec890216948b0c364f8f92792129d0335f506James Dong              sampleDescriptionId(id) {}
9413aec890216948b0c364f8f92792129d0335f506James Dong
9513aec890216948b0c364f8f92792129d0335f506James Dong        uint32_t firstChunk;
9613aec890216948b0c364f8f92792129d0335f506James Dong        uint32_t samplesPerChunk;
9713aec890216948b0c364f8f92792129d0335f506James Dong        uint32_t sampleDescriptionId;
9813aec890216948b0c364f8f92792129d0335f506James Dong    };
9913aec890216948b0c364f8f92792129d0335f506James Dong    List<StscTableEntry> mStscTableEntries;
10020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
101050b28a593350047845a45a14cc5026221ac1620James Dong    List<int32_t> mStssTableEntries;
102365a963142093a1cd8efdcea76b5f65096a5b115James Dong    List<int64_t> mChunkDurations;
103050b28a593350047845a45a14cc5026221ac1620James Dong
104be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    struct SttsTableEntry {
105be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
1068f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        SttsTableEntry(uint32_t count, uint32_t durationUs)
1078f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            : sampleCount(count), sampleDurationUs(durationUs) {}
108be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
109be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        uint32_t sampleCount;
1108f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        uint32_t sampleDurationUs;
111be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    };
112be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    List<SttsTableEntry> mSttsTableEntries;
113be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
11420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *mCodecSpecificData;
11520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t mCodecSpecificDataSize;
116548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    bool mGotAllCodecSpecificData;
11793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    bool mTrackingProgressStatus;
11820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
11925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool mReachedEOS;
1203c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    int64_t mStartTimestampUs;
12193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mPreviousTrackTimeUs;
12293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mTrackEveryTimeDurationUs;
12325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
12420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    static void *ThreadWrapper(void *me);
12520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void threadEntry();
12620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    status_t makeAVCCodecSpecificData(
12803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            const uint8_t *data, size_t size);
129215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong
130215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    // Track authoring progress status
131faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    void trackProgressStatus(int64_t timeUs, status_t err = OK);
13293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    void initTrackingProgressStatus(MetaData *params);
13303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
134215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    // Utilities for collecting statistical data
135215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    void logStatisticalData(bool isAudio);
136215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    void findMinAvgMaxSampleDurationMs(
137215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong            int32_t *min, int32_t *avg, int32_t *max);
138215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    void findMinMaxChunkDurations(int64_t *min, int64_t *max);
139215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong
14019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    void getCodecSpecificDataFromInputFormatIfPossible();
14119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
14220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track(const Track &);
14320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track &operator=(const Track &);
14420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
14520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#define USE_NALLEN_FOUR         1
14703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
14820111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::MPEG4Writer(const char *filename)
14920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mFile(fopen(filename, "wb")),
1501acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong      mUse32BitOffset(true),
151a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
152a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mStarted(false),
15320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOffset(0),
15413aec890216948b0c364f8f92792129d0335f506James Dong      mMdatOffset(0),
1557837c17063a4c50bc856ba59418516fdab731de7James Dong      mEstimatedMoovBoxSize(0),
156f01528f435e6b1f02d118fcd8305a148c27a89f1James Dong      mInterleaveDurationUs(1000000) {
1570c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(mFile != NULL);
15820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
15920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
16030ab66297501757d745b9ae10da61adcd891f497Andreas HuberMPEG4Writer::MPEG4Writer(int fd)
16130ab66297501757d745b9ae10da61adcd891f497Andreas Huber    : mFile(fdopen(fd, "wb")),
1621acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong      mUse32BitOffset(true),
163a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
164a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mStarted(false),
16530ab66297501757d745b9ae10da61adcd891f497Andreas Huber      mOffset(0),
16613aec890216948b0c364f8f92792129d0335f506James Dong      mMdatOffset(0),
1677837c17063a4c50bc856ba59418516fdab731de7James Dong      mEstimatedMoovBoxSize(0),
168f01528f435e6b1f02d118fcd8305a148c27a89f1James Dong      mInterleaveDurationUs(1000000) {
16930ab66297501757d745b9ae10da61adcd891f497Andreas Huber    CHECK(mFile != NULL);
17030ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
17130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
17220111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() {
17320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    stop();
17420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
17520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
17620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber         it != mTracks.end(); ++it) {
17720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        delete *it;
17820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
17920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.clear();
18020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
18120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1822dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huberstatus_t MPEG4Writer::addSource(const sp<MediaSource> &source) {
18325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    Track *track = new Track(this, source);
18420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.push_back(track);
1852dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
1862dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    return OK;
18720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
18820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
18993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::startTracks(MetaData *params) {
190a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
191a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
19293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        status_t err = (*it)->start(params);
193a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
194a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (err != OK) {
195a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            for (List<Track *>::iterator it2 = mTracks.begin();
196a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                 it2 != it; ++it2) {
197a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                (*it2)->stop();
198a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            }
199a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
200a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            return err;
201a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
202a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
203a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    return OK;
204a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
205a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
2062dec2b5be2056c6d9428897dc672185872d30d17James Dongint64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) {
2072dec2b5be2056c6d9428897dc672185872d30d17James Dong    // This implementation is highly experimental/heurisitic.
2082dec2b5be2056c6d9428897dc672185872d30d17James Dong    //
2092dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Statistical analysis shows that metadata usually accounts
2102dec2b5be2056c6d9428897dc672185872d30d17James Dong    // for a small portion of the total file size, usually < 0.6%.
2112dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Currently, lets set to 0.4% for now.
2122dec2b5be2056c6d9428897dc672185872d30d17James Dong
2132dec2b5be2056c6d9428897dc672185872d30d17James Dong    // The default MIN_MOOV_BOX_SIZE is set to 0.4% x 1MB,
2142dec2b5be2056c6d9428897dc672185872d30d17James Dong    // where 1MB is the common file size limit for MMS application.
2152dec2b5be2056c6d9428897dc672185872d30d17James Dong    // The default MAX _MOOV_BOX_SIZE value is based on about 4
2162dec2b5be2056c6d9428897dc672185872d30d17James Dong    // minute video recording with a bit rate about 3 Mbps, because
2172dec2b5be2056c6d9428897dc672185872d30d17James Dong    // statistics also show that most of the video captured are going
2182dec2b5be2056c6d9428897dc672185872d30d17James Dong    // to be less than 3 minutes.
2192dec2b5be2056c6d9428897dc672185872d30d17James Dong
2202dec2b5be2056c6d9428897dc672185872d30d17James Dong    // If the estimation is wrong, we will pay the price of wasting
2212dec2b5be2056c6d9428897dc672185872d30d17James Dong    // some reserved space. This should not happen so often statistically.
2222dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int32_t factor = mUse32BitOffset? 1: 2;
2232dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int64_t MIN_MOOV_BOX_SIZE = 4 * 1024;  // 4 KB
2242dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000);
2252dec2b5be2056c6d9428897dc672185872d30d17James Dong    int64_t size = MIN_MOOV_BOX_SIZE;
2262dec2b5be2056c6d9428897dc672185872d30d17James Dong
2272dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (mMaxFileSizeLimitBytes != 0) {
2282dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = mMaxFileSizeLimitBytes * 4 / 1000;
2292dec2b5be2056c6d9428897dc672185872d30d17James Dong    } else if (mMaxFileDurationLimitUs != 0) {
2302dec2b5be2056c6d9428897dc672185872d30d17James Dong        if (bitRate <= 0) {
2312dec2b5be2056c6d9428897dc672185872d30d17James Dong            // We could not estimate the file size since bitRate is not set.
2322dec2b5be2056c6d9428897dc672185872d30d17James Dong            size = MIN_MOOV_BOX_SIZE;
2332dec2b5be2056c6d9428897dc672185872d30d17James Dong        } else {
2342dec2b5be2056c6d9428897dc672185872d30d17James Dong            size = ((mMaxFileDurationLimitUs * bitRate * 4) / 1000 / 8000000);
2352dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
2362dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
2372dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size < MIN_MOOV_BOX_SIZE) {
2382dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MIN_MOOV_BOX_SIZE;
2392dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
2402dec2b5be2056c6d9428897dc672185872d30d17James Dong
2412dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Any long duration recording will be probably end up with
2422dec2b5be2056c6d9428897dc672185872d30d17James Dong    // non-streamable mp4 file.
2432dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size > MAX_MOOV_BOX_SIZE) {
2442dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MAX_MOOV_BOX_SIZE;
2452dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
2462dec2b5be2056c6d9428897dc672185872d30d17James Dong
2472dec2b5be2056c6d9428897dc672185872d30d17James Dong    LOGI("limits: %lld/%lld bytes/us, bit rate: %d bps and the estimated"
2482dec2b5be2056c6d9428897dc672185872d30d17James Dong         " moov size %lld bytes",
2492dec2b5be2056c6d9428897dc672185872d30d17James Dong         mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size);
2502dec2b5be2056c6d9428897dc672185872d30d17James Dong    return factor * size;
2512dec2b5be2056c6d9428897dc672185872d30d17James Dong}
2522dec2b5be2056c6d9428897dc672185872d30d17James Dong
2532dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t MPEG4Writer::start(MetaData *param) {
25420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mFile == NULL) {
25525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return UNKNOWN_ERROR;
25620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
25720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2582dec2b5be2056c6d9428897dc672185872d30d17James Dong    int32_t use64BitOffset;
2592dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (param &&
2602dec2b5be2056c6d9428897dc672185872d30d17James Dong        param->findInt32(kKey64BitFileOffset, &use64BitOffset) &&
2612dec2b5be2056c6d9428897dc672185872d30d17James Dong        use64BitOffset) {
2622dec2b5be2056c6d9428897dc672185872d30d17James Dong        mUse32BitOffset = false;
2632dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
2642dec2b5be2056c6d9428897dc672185872d30d17James Dong
2652dec2b5be2056c6d9428897dc672185872d30d17James Dong    // System property can overwrite the file offset bits parameter
2662dec2b5be2056c6d9428897dc672185872d30d17James Dong    char value[PROPERTY_VALUE_MAX];
2672dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (property_get("media.stagefright.record-64bits", value, NULL)
2682dec2b5be2056c6d9428897dc672185872d30d17James Dong        && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
2692dec2b5be2056c6d9428897dc672185872d30d17James Dong        mUse32BitOffset = false;
2702dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
2712dec2b5be2056c6d9428897dc672185872d30d17James Dong
272065d1aff96818df54456053f1574aec8a234d0deJames Dong    mStartTimestampUs = -1;
27393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
274a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (mStarted) {
275a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused) {
276a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mPaused = false;
27793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            return startTracks(param);
278a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
279a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
280a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
281a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
2828f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    if (!param ||
2838f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        !param->findInt32(kKeyTimeScale, &mTimeScale)) {
2848f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        mTimeScale = 1000;
2858f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    }
2868f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    CHECK(mTimeScale > 0);
2878f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    LOGV("movie time scale: %d", mTimeScale);
2888f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
2897837c17063a4c50bc856ba59418516fdab731de7James Dong    mStreamableFile = true;
2907837c17063a4c50bc856ba59418516fdab731de7James Dong    mWriteMoovBoxToMemory = false;
2917837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBuffer = NULL;
2927837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
2937837c17063a4c50bc856ba59418516fdab731de7James Dong
29420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    beginBox("ftyp");
29593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong      {
29693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        int32_t fileType;
29793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (param && param->findInt32(kKeyFileType, &fileType) &&
29893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            fileType != OUTPUT_FORMAT_MPEG_4) {
29993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            writeFourcc("3gp4");
30093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        } else {
30193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            writeFourcc("isom");
30293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
30393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong      }
30420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      writeInt32(0);
30520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      writeFourcc("isom");
30693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong      writeFourcc("3gp4");
30720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    endBox();
30820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3097837c17063a4c50bc856ba59418516fdab731de7James Dong    mFreeBoxOffset = mOffset;
31020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3117837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mEstimatedMoovBoxSize == 0) {
3122dec2b5be2056c6d9428897dc672185872d30d17James Dong        int32_t bitRate = -1;
3132dec2b5be2056c6d9428897dc672185872d30d17James Dong        if (param) {
3142dec2b5be2056c6d9428897dc672185872d30d17James Dong            param->findInt32(kKeyBitRate, &bitRate);
3152dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
3162dec2b5be2056c6d9428897dc672185872d30d17James Dong        mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate);
3177837c17063a4c50bc856ba59418516fdab731de7James Dong    }
3187837c17063a4c50bc856ba59418516fdab731de7James Dong    CHECK(mEstimatedMoovBoxSize >= 8);
3197837c17063a4c50bc856ba59418516fdab731de7James Dong    fseeko(mFile, mFreeBoxOffset, SEEK_SET);
3207837c17063a4c50bc856ba59418516fdab731de7James Dong    writeInt32(mEstimatedMoovBoxSize);
3217837c17063a4c50bc856ba59418516fdab731de7James Dong    write("free", 4);
3227837c17063a4c50bc856ba59418516fdab731de7James Dong
3237837c17063a4c50bc856ba59418516fdab731de7James Dong    mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize;
3247837c17063a4c50bc856ba59418516fdab731de7James Dong    mOffset = mMdatOffset;
3257837c17063a4c50bc856ba59418516fdab731de7James Dong    fseeko(mFile, mMdatOffset, SEEK_SET);
3261acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
3271acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("????mdat", 8);
3281acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
3291acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("\x00\x00\x00\x01mdat????????", 16);
3301acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
3311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
3321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    status_t err = startWriterThread();
3331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (err != OK) {
3341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        return err;
3351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
3361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
3371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    err = startTracks(param);
338a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (err != OK) {
339a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return err;
34020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
3411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
342a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mStarted = true;
34325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
34420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
34520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
346a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dongvoid MPEG4Writer::pause() {
347a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (mFile == NULL) {
348a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return;
349a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
350a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
351a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
352a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
353a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        (*it)->pause();
354a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
355a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
356a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
3571c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::stopWriterThread() {
3581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("stopWriterThread");
3591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
3601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    {
3611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        Mutex::Autolock autolock(mLock);
3621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
3631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mDone = true;
3641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkReadyCondition.signal();
3651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
3661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
3671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void *dummy;
3681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_join(mThread, &dummy);
3691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
3701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
37120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::stop() {
37220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mFile == NULL) {
37320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return;
37420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
37520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3768f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t maxDurationUs = 0;
37720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
37820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber         it != mTracks.end(); ++it) {
37920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        (*it)->stop();
38020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3818f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int64_t durationUs = (*it)->getDurationUs();
3828f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        if (durationUs > maxDurationUs) {
3838f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            maxDurationUs = durationUs;
38420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
38520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
38620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    stopWriterThread();
3887837c17063a4c50bc856ba59418516fdab731de7James Dong
38920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // Fix up the size of the 'mdat' chunk.
3901acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
3911acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        fseeko(mFile, mMdatOffset, SEEK_SET);
3921acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        int32_t size = htonl(static_cast<int32_t>(mOffset - mMdatOffset));
3931acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        fwrite(&size, 1, 4, mFile);
3941acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
3951acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        fseeko(mFile, mMdatOffset + 8, SEEK_SET);
3961acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        int64_t size = mOffset - mMdatOffset;
3971acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        size = hton64(size);
3981acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        fwrite(&size, 1, 8, mFile);
3991acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
4007837c17063a4c50bc856ba59418516fdab731de7James Dong    fseeko(mFile, mOffset, SEEK_SET);
40120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
40220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    time_t now = time(NULL);
4037837c17063a4c50bc856ba59418516fdab731de7James Dong    const off_t moovOffset = mOffset;
4047837c17063a4c50bc856ba59418516fdab731de7James Dong    mWriteMoovBoxToMemory = true;
4057837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize);
4067837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
4077837c17063a4c50bc856ba59418516fdab731de7James Dong    CHECK(mMoovBoxBuffer != NULL);
4088f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int32_t duration = (maxDurationUs * mTimeScale) / 1E6;
40920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
41020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    beginBox("moov");
41120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
41220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      beginBox("mvhd");
41320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // version=0, flags=0
41420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(now);           // creation time
41520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(now);           // modification time
4168f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        writeInt32(mTimeScale);    // mvhd timescale
4171acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        writeInt32(duration);
4181acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        writeInt32(0x10000);       // rate: 1.0
41920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt16(0x100);         // volume
42020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt16(0);             // reserved
42120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // reserved
42220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // reserved
42320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0x10000);       // matrix
42420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
42520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
42620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
42720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0x10000);
42820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
42920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
43020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
43120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0x40000000);
43220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
43320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
43420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
43520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
43620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
43720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
43820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(mTracks.size() + 1);  // nextTrackID
43920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      endBox();  // mvhd
44020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
44120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      int32_t id = 1;
44220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      for (List<Track *>::iterator it = mTracks.begin();
44320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber           it != mTracks.end(); ++it, ++id) {
4441acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          (*it)->writeTrackHeader(id, mUse32BitOffset);
44520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      }
44620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    endBox();  // moov
44720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4487837c17063a4c50bc856ba59418516fdab731de7James Dong    mWriteMoovBoxToMemory = false;
4497837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mStreamableFile) {
4507837c17063a4c50bc856ba59418516fdab731de7James Dong        CHECK(mMoovBoxBufferOffset + 8 <= mEstimatedMoovBoxSize);
4517837c17063a4c50bc856ba59418516fdab731de7James Dong
4527837c17063a4c50bc856ba59418516fdab731de7James Dong        // Moov box
4537837c17063a4c50bc856ba59418516fdab731de7James Dong        fseeko(mFile, mFreeBoxOffset, SEEK_SET);
4547837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset = mFreeBoxOffset;
4557837c17063a4c50bc856ba59418516fdab731de7James Dong        write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, mFile);
4567837c17063a4c50bc856ba59418516fdab731de7James Dong
4577837c17063a4c50bc856ba59418516fdab731de7James Dong        // Free box
4582dec2b5be2056c6d9428897dc672185872d30d17James Dong        fseeko(mFile, mOffset, SEEK_SET);
4597837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset);
4607837c17063a4c50bc856ba59418516fdab731de7James Dong        write("free", 4);
4617837c17063a4c50bc856ba59418516fdab731de7James Dong
4627837c17063a4c50bc856ba59418516fdab731de7James Dong        // Free temp memory
4637837c17063a4c50bc856ba59418516fdab731de7James Dong        free(mMoovBoxBuffer);
4647837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBuffer = NULL;
4657837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBufferOffset = 0;
4662dec2b5be2056c6d9428897dc672185872d30d17James Dong    } else {
4672dec2b5be2056c6d9428897dc672185872d30d17James Dong        LOGI("The mp4 file will not be streamable.");
4687837c17063a4c50bc856ba59418516fdab731de7James Dong    }
4697837c17063a4c50bc856ba59418516fdab731de7James Dong
4700c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(mBoxes.empty());
47120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4727837c17063a4c50bc856ba59418516fdab731de7James Dong    fflush(mFile);
47320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fclose(mFile);
47420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mFile = NULL;
475a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mStarted = false;
47620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
47720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
47813aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) {
47913aec890216948b0c364f8f92792129d0335f506James Dong    mInterleaveDurationUs = durationUs;
48013aec890216948b0c364f8f92792129d0335f506James Dong    return OK;
48113aec890216948b0c364f8f92792129d0335f506James Dong}
48213aec890216948b0c364f8f92792129d0335f506James Dong
48313aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() {
48413aec890216948b0c364f8f92792129d0335f506James Dong    mLock.lock();
48513aec890216948b0c364f8f92792129d0335f506James Dong}
48613aec890216948b0c364f8f92792129d0335f506James Dong
48713aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() {
48813aec890216948b0c364f8f92792129d0335f506James Dong    mLock.unlock();
48913aec890216948b0c364f8f92792129d0335f506James Dong}
49020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
49113aec890216948b0c364f8f92792129d0335f506James Dongoff_t MPEG4Writer::addSample_l(MediaBuffer *buffer) {
49220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    off_t old_offset = mOffset;
49320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
49420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fwrite((const uint8_t *)buffer->data() + buffer->range_offset(),
49520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber           1, buffer->range_length(), mFile);
49620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
49720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += buffer->range_length();
49820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
49920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return old_offset;
50020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
50120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
50203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) {
50303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (buffer->range_length() < 4) {
50403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return;
50503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
50603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
50703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    const uint8_t *ptr =
50803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        (const uint8_t *)buffer->data() + buffer->range_offset();
50903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
51003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) {
51103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        buffer->set_range(
51203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                buffer->range_offset() + 4, buffer->range_length() - 4);
51303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
51403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
51503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
51613aec890216948b0c364f8f92792129d0335f506James Dongoff_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) {
51730ab66297501757d745b9ae10da61adcd891f497Andreas Huber    off_t old_offset = mOffset;
51830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
51930ab66297501757d745b9ae10da61adcd891f497Andreas Huber    size_t length = buffer->range_length();
52003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
52103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR
52203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    uint8_t x = length >> 24;
52303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    fwrite(&x, 1, 1, mFile);
52403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    x = (length >> 16) & 0xff;
52503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    fwrite(&x, 1, 1, mFile);
52603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    x = (length >> 8) & 0xff;
52703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    fwrite(&x, 1, 1, mFile);
52803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    x = length & 0xff;
52903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    fwrite(&x, 1, 1, mFile);
53003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else
53130ab66297501757d745b9ae10da61adcd891f497Andreas Huber    CHECK(length < 65536);
53230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
53330ab66297501757d745b9ae10da61adcd891f497Andreas Huber    uint8_t x = length >> 8;
53430ab66297501757d745b9ae10da61adcd891f497Andreas Huber    fwrite(&x, 1, 1, mFile);
53530ab66297501757d745b9ae10da61adcd891f497Andreas Huber    x = length & 0xff;
53630ab66297501757d745b9ae10da61adcd891f497Andreas Huber    fwrite(&x, 1, 1, mFile);
53703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif
53830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
53930ab66297501757d745b9ae10da61adcd891f497Andreas Huber    fwrite((const uint8_t *)buffer->data() + buffer->range_offset(),
54030ab66297501757d745b9ae10da61adcd891f497Andreas Huber           1, length, mFile);
54130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
54203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR
54303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    mOffset += length + 4;
54403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else
54530ab66297501757d745b9ae10da61adcd891f497Andreas Huber    mOffset += length + 2;
54603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif
54730ab66297501757d745b9ae10da61adcd891f497Andreas Huber
54830ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return old_offset;
54930ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
55030ab66297501757d745b9ae10da61adcd891f497Andreas Huber
5517837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write(
5527837c17063a4c50bc856ba59418516fdab731de7James Dong        const void *ptr, size_t size, size_t nmemb, FILE *stream) {
5537837c17063a4c50bc856ba59418516fdab731de7James Dong
5547837c17063a4c50bc856ba59418516fdab731de7James Dong    const size_t bytes = size * nmemb;
5557837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
5561acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        off_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes;
5571acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        if (moovBoxSize > mEstimatedMoovBoxSize) {
5587837c17063a4c50bc856ba59418516fdab731de7James Dong            for (List<off_t>::iterator it = mBoxes.begin();
5597837c17063a4c50bc856ba59418516fdab731de7James Dong                 it != mBoxes.end(); ++it) {
5607837c17063a4c50bc856ba59418516fdab731de7James Dong                (*it) += mOffset;
5617837c17063a4c50bc856ba59418516fdab731de7James Dong            }
5627837c17063a4c50bc856ba59418516fdab731de7James Dong            fseeko(mFile, mOffset, SEEK_SET);
5637837c17063a4c50bc856ba59418516fdab731de7James Dong            fwrite(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, stream);
5647837c17063a4c50bc856ba59418516fdab731de7James Dong            fwrite(ptr, size, nmemb, stream);
5657837c17063a4c50bc856ba59418516fdab731de7James Dong            mOffset += (bytes + mMoovBoxBufferOffset);
5667837c17063a4c50bc856ba59418516fdab731de7James Dong            free(mMoovBoxBuffer);
5677837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBuffer = NULL;
5687837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset = 0;
5697837c17063a4c50bc856ba59418516fdab731de7James Dong            mWriteMoovBoxToMemory = false;
5707837c17063a4c50bc856ba59418516fdab731de7James Dong            mStreamableFile = false;
5717837c17063a4c50bc856ba59418516fdab731de7James Dong        } else {
5727837c17063a4c50bc856ba59418516fdab731de7James Dong            memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes);
5737837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset += bytes;
5747837c17063a4c50bc856ba59418516fdab731de7James Dong        }
5757837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
5767837c17063a4c50bc856ba59418516fdab731de7James Dong        fwrite(ptr, size, nmemb, stream);
5777837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset += bytes;
5787837c17063a4c50bc856ba59418516fdab731de7James Dong    }
5797837c17063a4c50bc856ba59418516fdab731de7James Dong    return bytes;
5807837c17063a4c50bc856ba59418516fdab731de7James Dong}
5817837c17063a4c50bc856ba59418516fdab731de7James Dong
58220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) {
5830c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(fourcc), 4);
58420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5857837c17063a4c50bc856ba59418516fdab731de7James Dong    mBoxes.push_back(mWriteMoovBoxToMemory?
5867837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset: mOffset);
58720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
58820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeInt32(0);
58920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeFourcc(fourcc);
59020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
59120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
59220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() {
5930c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(!mBoxes.empty());
59420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
59520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    off_t offset = *--mBoxes.end();
59620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mBoxes.erase(--mBoxes.end());
59720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5987837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
5997837c17063a4c50bc856ba59418516fdab731de7James Dong       int32_t x = htonl(mMoovBoxBufferOffset - offset);
6007837c17063a4c50bc856ba59418516fdab731de7James Dong       memcpy(mMoovBoxBuffer + offset, &x, 4);
6017837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
6027837c17063a4c50bc856ba59418516fdab731de7James Dong        fseeko(mFile, offset, SEEK_SET);
6037837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mOffset - offset);
6047837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset -= 4;
6057837c17063a4c50bc856ba59418516fdab731de7James Dong        fseeko(mFile, mOffset, SEEK_SET);
6067837c17063a4c50bc856ba59418516fdab731de7James Dong    }
60720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
60820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
60920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) {
6107837c17063a4c50bc856ba59418516fdab731de7James Dong    write(&x, 1, 1, mFile);
61120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
61220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
61320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) {
61420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htons(x);
6157837c17063a4c50bc856ba59418516fdab731de7James Dong    write(&x, 1, 2, mFile);
61620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
61720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
61820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) {
61920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htonl(x);
6207837c17063a4c50bc856ba59418516fdab731de7James Dong    write(&x, 1, 4, mFile);
62120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
62220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
62320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) {
62420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = hton64(x);
6257837c17063a4c50bc856ba59418516fdab731de7James Dong    write(&x, 1, 8, mFile);
62620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
62720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
62820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) {
62920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t n = strlen(s);
6307837c17063a4c50bc856ba59418516fdab731de7James Dong    write(s, 1, n + 1, mFile);
63120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
63220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
63320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) {
6340c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(s), 4);
6357837c17063a4c50bc856ba59418516fdab731de7James Dong    write(s, 1, 4, mFile);
63620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
63720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
63820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) {
6397837c17063a4c50bc856ba59418516fdab731de7James Dong    write(data, 1, size, mFile);
64020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
64120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
642d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() {
643d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
644d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileSizeLimitBytes == 0) {
645d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
646d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
647d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
648956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize);
649d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
650d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
651d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes();
652d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
653d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return (nTotalBytesEstimate >= mMaxFileSizeLimitBytes);
654d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
655d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
656d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() {
657d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
658d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileDurationLimitUs == 0) {
659d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
660d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
661d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
662d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
663d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
664d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) {
665d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            return true;
666d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
667d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
668d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return false;
669d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
670d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
67125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() {
67225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool allDone = true;
67325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
67425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber         it != mTracks.end(); ++it) {
67525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        if (!(*it)->reachedEOS()) {
67625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            allDone = false;
67725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            break;
67825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        }
67925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
68025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
68125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return allDone;
68225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
68325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
684f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) {
685f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    LOGI("setStartTimestampUs: %lld", timeUs);
686f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    CHECK(timeUs >= 0);
6873c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
688065d1aff96818df54456053f1574aec8a234d0deJames Dong    if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) {
689f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mStartTimestampUs = timeUs;
690f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        LOGI("Earliest track starting time: %lld", mStartTimestampUs);
6913c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    }
6923c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
6933c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
694f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() {
6953c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
6963c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    return mStartTimestampUs;
6973c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
6983c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
69958ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() {
70058ae9c530247668f8af36e30d228c716c226b3d4James Dong    Mutex::Autolock autolock(mLock);
70158ae9c530247668f8af36e30d228c716c226b3d4James Dong    return mTracks.size();
70258ae9c530247668f8af36e30d228c716c226b3d4James Dong}
70358ae9c530247668f8af36e30d228c716c226b3d4James Dong
70420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
70520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
70620111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track(
70725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        MPEG4Writer *owner, const sp<MediaSource> &source)
70820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mOwner(owner),
70925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mMeta(source->getFormat()),
71020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSource(source),
71120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDone(false),
712a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
713a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mResumed(false),
714c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong      mTrackDurationUs(0),
715956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      mEstimatedTrackSizeBytes(0),
716be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong      mSamplesHaveSameSize(true),
71720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCodecSpecificData(NULL),
71825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mCodecSpecificDataSize(0),
719548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber      mGotAllCodecSpecificData(false),
72025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mReachedEOS(false) {
72119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    getCodecSpecificDataFromInputFormatIfPossible();
7228f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
7238f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    if (!mMeta->findInt32(kKeyTimeScale, &mTimeScale)) {
7248f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        mTimeScale = 1000;
7258f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    }
7261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
7271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    const char *mime;
7281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mMeta->findCString(kKeyMIMEType, &mime);
7291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
7301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAudio = !strncasecmp(mime, "audio/", 6);
7311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
7321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong               !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC);
7331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
7348f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    CHECK(mTimeScale > 0);
73519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber}
73619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
73719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Hubervoid MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() {
73819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    const char *mime;
73919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
74019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
74119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
74219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        uint32_t type;
74319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        const void *data;
74419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        size_t size;
74519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        if (mMeta->findData(kKeyAVCC, &type, &data, &size)) {
74619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mCodecSpecificData = malloc(size);
74719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mCodecSpecificDataSize = size;
74819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            memcpy(mCodecSpecificData, data, size);
74919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mGotAllCodecSpecificData = true;
75019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        }
75119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
75219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
75319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        uint32_t type;
75419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        const void *data;
75519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        size_t size;
75619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        if (mMeta->findData(kKeyESDS, &type, &data, &size)) {
75719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            ESDS esds(data, size);
75819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            if (esds.getCodecSpecificInfo(&data, &size) == OK) {
75919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mCodecSpecificData = malloc(size);
76019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mCodecSpecificDataSize = size;
76119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                memcpy(mCodecSpecificData, data, size);
76219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mGotAllCodecSpecificData = true;
76319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            }
76419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        }
76519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
76620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
76720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
76820111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() {
76920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    stop();
77020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
77120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mCodecSpecificData != NULL) {
77220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        free(mCodecSpecificData);
77320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mCodecSpecificData = NULL;
77420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
77520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
77620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
77793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) {
77893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    LOGV("initTrackingProgressStatus");
77993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mPreviousTrackTimeUs = -1;
78093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackingProgressStatus = false;
78193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackEveryTimeDurationUs = 0;
78293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    {
78393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        int64_t timeUs;
78493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) {
78593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            LOGV("Receive request to track progress status for every %lld us", timeUs);
78693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackEveryTimeDurationUs = timeUs;
78793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackingProgressStatus = true;
78893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
78993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
79093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
79193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
7921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong// static
7931c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid *MPEG4Writer::ThreadWrapper(void *me) {
7941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("ThreadWrapper: %p", me);
7951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    MPEG4Writer *writer = static_cast<MPEG4Writer *>(me);
7961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    writer->threadFunc();
7971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return NULL;
7981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
7991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8001c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::bufferChunk(const Chunk& chunk) {
8011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("bufferChunk: %p", chunk.mTrack);
8021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Mutex::Autolock autolock(mLock);
8031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    CHECK_EQ(mDone, false);
8041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
8061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
8071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (chunk.mTrack == it->mTrack) {  // Found owner
8091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            it->mChunks.push_back(chunk);
8101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.signal();
8111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            return;
8121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
8131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
8141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    CHECK("Received a chunk for a unknown track" == 0);
8161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
8171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8181c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::writeFirstChunk(ChunkInfo* info) {
8191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("writeFirstChunk: %p", info->mTrack);
8201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    List<Chunk>::iterator chunkIt = info->mChunks.begin();
8221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<MediaBuffer *>::iterator it = chunkIt->mSamples.begin();
8231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != chunkIt->mSamples.end(); ++it) {
8241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        off_t offset = info->mTrack->isAvc()
8261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                            ? addLengthPrefixedSample_l(*it)
8271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                            : addSample_l(*it);
8281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (it == chunkIt->mSamples.begin()) {
8291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            info->mTrack->addChunkOffset(offset);
8301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
8311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
8321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    // Done with the current chunk.
8341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    // Release all the samples in this chunk.
8351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    while (!chunkIt->mSamples.empty()) {
8361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        List<MediaBuffer *>::iterator it = chunkIt->mSamples.begin();
8371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it)->release();
8381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it) = NULL;
8391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        chunkIt->mSamples.erase(it);
8401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
8411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    chunkIt->mSamples.clear();
8421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    info->mChunks.erase(chunkIt);
8431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
8441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8451c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::writeChunks() {
8461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("writeChunks");
8471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    size_t outstandingChunks = 0;
8481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    while (!mChunkInfos.empty()) {
8491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        List<ChunkInfo>::iterator it = mChunkInfos.begin();
8501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        while (!it->mChunks.empty()) {
8511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            CHECK_EQ(OK, writeOneChunk());
8521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            ++outstandingChunks;
8531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
8541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        it->mTrack = NULL;
8551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkInfos.erase(it);
8561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
8571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mChunkInfos.clear();
8581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGD("%d chunks are written in the last batch", outstandingChunks);
8591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
8601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8611c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::writeOneChunk() {
8621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("writeOneChunk");
8631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    // Find the smallest timestamp, and write that chunk out
8651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    // XXX: What if some track is just too slow?
8661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL;
8671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Track *track = NULL;
8681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
8691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
8701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (!it->mChunks.empty()) {
8711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            List<Chunk>::iterator chunkIt = it->mChunks.begin();
8721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (chunkIt->mTimeStampUs < minTimestampUs) {
8731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                minTimestampUs = chunkIt->mTimeStampUs;
8741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                track = it->mTrack;
8751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            }
8761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
8771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
8781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (track == NULL) {
8801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        LOGV("Nothing to be written after all");
8811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        return OK;
8821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
8831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (mIsFirstChunk) {
8851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsFirstChunk = false;
8861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
8871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
8881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
8891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (it->mTrack == track) {
8901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            writeFirstChunk(&(*it));
8911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
8921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
8931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return OK;
8941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
8951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8961c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::threadFunc() {
8971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("threadFunc");
8981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    while (!mDone) {
9001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        {
9011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            Mutex::Autolock autolock(mLock);
9021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.wait(mLock);
9031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            CHECK_EQ(writeOneChunk(), OK);
9041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
9051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
9061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
9071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    {
9081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        // Write ALL samples
9091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        Mutex::Autolock autolock(mLock);
9101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        writeChunks();
9111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
9121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
9131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
9141c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::startWriterThread() {
9151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("startWriterThread");
9161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
9171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mDone = false;
9181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsFirstChunk = true;
9191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<Track *>::iterator it = mTracks.begin();
9201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mTracks.end(); ++it) {
9211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        ChunkInfo info;
9221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        info.mTrack = *it;
9231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkInfos.push_back(info);
9241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
9251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
9261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_t attr;
9271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_init(&attr);
9281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
9291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_create(&mThread, &attr, ThreadWrapper, this);
9301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_destroy(&attr);
9311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return OK;
9321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
9331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
93493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) {
935a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (!mDone && mPaused) {
936a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mPaused = false;
937a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mResumed = true;
938a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
939a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
94025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
94193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t startTimeUs;
94219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) {
94319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        startTimeUs = 0;
94419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
94519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
94693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    initTrackingProgressStatus(params);
94793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
948f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    sp<MetaData> meta = new MetaData;
949f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    meta->setInt64(kKeyTime, startTimeUs);
950f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    status_t err = mSource->start(meta.get());
95125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    if (err != OK) {
95225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        mDone = mReachedEOS = true;
95325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return err;
95425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
95520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
95620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_t attr;
95720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_init(&attr);
95820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
95920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
96020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = false;
961c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs = 0;
96225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = false;
963956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    mEstimatedTrackSizeBytes = 0;
96420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
96525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    pthread_create(&mThread, &attr, ThreadWrapper, this);
96620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_destroy(&attr);
96725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
96825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
96920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
97020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
971a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dongvoid MPEG4Writer::Track::pause() {
972a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
973a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
974a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
97520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::Track::stop() {
97620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mDone) {
97720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return;
97820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
97920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
98020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = true;
98120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
98220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *dummy;
98320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_join(mThread, &dummy);
98420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
98520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mSource->stop();
98620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
98720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
98825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() {
98925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return mReachedEOS;
99025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
99125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
99220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static
99320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) {
99420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = static_cast<Track *>(me);
99520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
99620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    track->threadEntry();
99720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
99820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return NULL;
99920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
100020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1001548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber#include <ctype.h>
1002548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huberstatic void hexdump(const void *_data, size_t size) {
1003548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    const uint8_t *data = (const uint8_t *)_data;
1004548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    size_t offset = 0;
1005548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    while (offset < size) {
1006548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        printf("0x%04x  ", offset);
1007548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
1008548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        size_t n = size - offset;
1009548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        if (n > 16) {
1010548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            n = 16;
1011548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        }
1012548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
1013548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        for (size_t i = 0; i < 16; ++i) {
1014548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            if (i == 8) {
1015548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber                printf(" ");
1016548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            }
1017548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
1018548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            if (offset + i < size) {
1019548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber                printf("%02x ", data[offset + i]);
1020548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            } else {
1021548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber                printf("   ");
1022548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            }
1023548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        }
1024548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
1025548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        printf(" ");
1026548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
1027548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        for (size_t i = 0; i < n; ++i) {
1028548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            if (isprint(data[offset + i])) {
1029548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber                printf("%c", data[offset + i]);
1030548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            } else {
1031548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber                printf(".");
1032548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            }
1033548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        }
1034548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
1035548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        printf("\n");
1036548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
1037548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        offset += 16;
1038548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    }
1039548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber}
1040548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
1041548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
104203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData(
104303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        const uint8_t *data, size_t size) {
1044548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    // hexdump(data, size);
1045548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
104603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (mCodecSpecificData != NULL) {
1047548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        LOGE("Already have codec specific data");
104803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
104903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
105003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
105103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (size < 4 || memcmp("\x00\x00\x00\x01", data, 4)) {
1052548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        LOGE("Must start with a start code");
105303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
105403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
105503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
105603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    size_t picParamOffset = 4;
105703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    while (picParamOffset + 3 < size
105803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            && memcmp("\x00\x00\x00\x01", &data[picParamOffset], 4)) {
105903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        ++picParamOffset;
106003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
106103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
106203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (picParamOffset + 3 >= size) {
1063548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        LOGE("Could not find start-code for pictureParameterSet");
106403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
106503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
106603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
106703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    size_t seqParamSetLength = picParamOffset - 4;
106803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    size_t picParamSetLength = size - picParamOffset - 4;
106903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
107003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    mCodecSpecificDataSize =
107103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        6 + 1 + seqParamSetLength + 2 + picParamSetLength + 2;
107203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
107303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    mCodecSpecificData = malloc(mCodecSpecificDataSize);
107403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    uint8_t *header = (uint8_t *)mCodecSpecificData;
107503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[0] = 1;
107603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[1] = 0x42;  // profile
107703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[2] = 0x80;
107803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[3] = 0x1e;  // level
107903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
108003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR
108103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[4] = 0xfc | 3;  // length size == 4 bytes
108203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else
108303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[4] = 0xfc | 1;  // length size == 2 bytes
108403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif
108503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
108603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[5] = 0xe0 | 1;
108703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[6] = seqParamSetLength >> 8;
108803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[7] = seqParamSetLength & 0xff;
108903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    memcpy(&header[8], &data[4], seqParamSetLength);
109003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header += 8 + seqParamSetLength;
109103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[0] = 1;
109203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[1] = picParamSetLength >> 8;
109303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[2] = picParamSetLength & 0xff;
109403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    memcpy(&header[3], &data[picParamOffset + 4], picParamSetLength);
109503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
109603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    return OK;
109703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
109803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
10998644c14618d30d9e57a69df40ed939986ebf02c4James Dongstatic bool collectStatisticalData() {
11008644c14618d30d9e57a69df40ed939986ebf02c4James Dong    char value[PROPERTY_VALUE_MAX];
11018644c14618d30d9e57a69df40ed939986ebf02c4James Dong    if (property_get("media.stagefright.record-stats", value, NULL)
11028644c14618d30d9e57a69df40ed939986ebf02c4James Dong        && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
11038644c14618d30d9e57a69df40ed939986ebf02c4James Dong        return true;
11048644c14618d30d9e57a69df40ed939986ebf02c4James Dong    }
11058644c14618d30d9e57a69df40ed939986ebf02c4James Dong    return false;
11068644c14618d30d9e57a69df40ed939986ebf02c4James Dong}
11078644c14618d30d9e57a69df40ed939986ebf02c4James Dong
110820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::Track::threadEntry() {
110930ab66297501757d745b9ae10da61adcd891f497Andreas Huber    int32_t count = 0;
111013aec890216948b0c364f8f92792129d0335f506James Dong    const int64_t interleaveDurationUs = mOwner->interleaveDuration();
111113aec890216948b0c364f8f92792129d0335f506James Dong    int64_t chunkTimestampUs = 0;
111213aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nChunks = 0;
111313aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nZeroLengthFrames = 0;
11148f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t lastTimestampUs = 0;  // Previous sample time stamp in ms
11158f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t lastDurationUs = 0;   // Between the previous two samples in ms
11168f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int32_t sampleCount = 1;      // Sample count in the current stts table entry
1117be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    uint32_t previousSampleSize = 0;  // Size of the previous sample
1118a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    int64_t previousPausedDurationUs = 0;
11191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    int64_t timestampUs;
1120d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong    sp<MetaData> meta_data;
11218644c14618d30d9e57a69df40ed939986ebf02c4James Dong    bool collectStats = collectStatisticalData();
112220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1123ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    mNumSamples = 0;
11241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mMaxWriteTimeUs = 0;
112593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t err = OK;
112620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBuffer *buffer;
112793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    while (!mDone && (err = mSource->read(&buffer)) == OK) {
112820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (buffer->range_length() == 0) {
112920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer->release();
113020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer = NULL;
113113aec890216948b0c364f8f92792129d0335f506James Dong            ++nZeroLengthFrames;
113220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            continue;
113320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
113420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1135a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // If the codec specific data has not been received yet, delay pause.
1136a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // After the codec specific data is received, discard what we received
1137a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // when the track is to be paused.
1138a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused && !mResumed) {
1139a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer->release();
1140a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer = NULL;
1141a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            continue;
1142a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
1143a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
114430ab66297501757d745b9ae10da61adcd891f497Andreas Huber        ++count;
114530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
114603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        int32_t isCodecConfig;
114703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig)
114803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                && isCodecConfig) {
1149548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            CHECK(!mGotAllCodecSpecificData);
1150548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
11511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (mIsAvc) {
115203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                status_t err = makeAVCCodecSpecificData(
115303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        (const uint8_t *)buffer->data()
115403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                            + buffer->range_offset(),
115503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        buffer->range_length());
1156be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                CHECK_EQ(OK, err);
11571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            } else if (mIsMPEG4) {
115803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificDataSize = buffer->range_length();
115903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificData = malloc(mCodecSpecificDataSize);
116003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                memcpy(mCodecSpecificData,
116103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        (const uint8_t *)buffer->data()
116203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                            + buffer->range_offset(),
116303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                       buffer->range_length());
116430ab66297501757d745b9ae10da61adcd891f497Andreas Huber            }
116530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
116630ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer->release();
116730ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer = NULL;
116830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
1169548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            mGotAllCodecSpecificData = true;
117030ab66297501757d745b9ae10da61adcd891f497Andreas Huber            continue;
1171548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        } else if (!mGotAllCodecSpecificData &&
11721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                count == 1 && mIsMPEG4 && mCodecSpecificData == NULL) {
117303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            // The TI mpeg4 encoder does not properly set the
117403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            // codec-specific-data flag.
117530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
117620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            const uint8_t *data =
117720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                (const uint8_t *)buffer->data() + buffer->range_offset();
117820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
117920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            const size_t size = buffer->range_length();
118020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
118120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            size_t offset = 0;
118220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (offset + 3 < size) {
118320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (data[offset] == 0x00 && data[offset + 1] == 0x00
118420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    && data[offset + 2] == 0x01 && data[offset + 3] == 0xb6) {
118520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    break;
118620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
118720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
118820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                ++offset;
118920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
119020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
11910c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber            // CHECK(offset + 3 < size);
1192bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber            if (offset + 3 >= size) {
1193bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber                // XXX assume the entire first chunk of data is the codec specific
1194bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber                // data.
1195bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber                offset = size;
1196bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber            }
119720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
119820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mCodecSpecificDataSize = offset;
119920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mCodecSpecificData = malloc(offset);
120020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            memcpy(mCodecSpecificData, data, offset);
120120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
120220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer->set_range(buffer->range_offset() + offset, size - offset);
120303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
120403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            if (size == offset) {
120503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                buffer->release();
120603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                buffer = NULL;
120703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
120803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                continue;
120903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            }
1210548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
1211548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            mGotAllCodecSpecificData = true;
12121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        } else if (!mGotAllCodecSpecificData && mIsAvc && count < 3) {
121303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            // The TI video encoder does not flag codec specific data
121403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            // as such and also splits up SPS and PPS across two buffers.
121503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
121603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            const uint8_t *data =
121703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                (const uint8_t *)buffer->data() + buffer->range_offset();
121803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
121903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            size_t size = buffer->range_length();
122003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
122103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            CHECK(count == 2 || mCodecSpecificData == NULL);
122203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
122303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            size_t offset = mCodecSpecificDataSize;
122403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            mCodecSpecificDataSize += size + 4;
122503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            mCodecSpecificData =
122603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                realloc(mCodecSpecificData, mCodecSpecificDataSize);
122703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
122803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            memcpy((uint8_t *)mCodecSpecificData + offset,
122903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                   "\x00\x00\x00\x01", 4);
123003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
123103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            memcpy((uint8_t *)mCodecSpecificData + offset + 4, data, size);
123203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
123303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            buffer->release();
123403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            buffer = NULL;
123503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
123603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            if (count == 2) {
123703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                void *tmp = mCodecSpecificData;
123803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                size = mCodecSpecificDataSize;
123903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificData = NULL;
124003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificDataSize = 0;
124103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
124203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                status_t err = makeAVCCodecSpecificData(
124303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        (const uint8_t *)tmp, size);
124403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                free(tmp);
124503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                tmp = NULL;
1246be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                CHECK_EQ(OK, err);
1247548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
1248548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber                mGotAllCodecSpecificData = true;
124903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            }
125003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
125103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            continue;
125220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
125320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1254a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (!mGotAllCodecSpecificData) {
1255a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mGotAllCodecSpecificData = true;
1256a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
1257a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
1258d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // Make a deep copy of the MediaBuffer and Metadata and release
1259d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // the original as soon as we can
1260d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        MediaBuffer *copy = new MediaBuffer(buffer->range_length());
1261d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(),
1262d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong                buffer->range_length());
1263d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        copy->set_range(0, buffer->range_length());
1264d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data = new MetaData(*buffer->meta_data().get());
1265d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer->release();
1266d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer = NULL;
1267d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
12681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (mIsAvc) StripStartcode(copy);
1269e136c3bb38e88315bf8797a464ebf2c788296b22James Dong
12708644c14618d30d9e57a69df40ed939986ebf02c4James Dong        size_t sampleSize;
12711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        sampleSize = mIsAvc
127203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR
1273d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong                ? copy->range_length() + 4
127403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else
1275d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong                ? copy->range_length() + 2
127603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif
1277d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong                : copy->range_length();
1278050b28a593350047845a45a14cc5026221ac1620James Dong
1279d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        // Max file size or duration handling
12808644c14618d30d9e57a69df40ed939986ebf02c4James Dong        mEstimatedTrackSizeBytes += sampleSize;
1281d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileSizeLimit()) {
1282d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
1283d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
1284d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
1285d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileDurationLimit()) {
1286d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
1287d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
1288d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
1289d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1290050b28a593350047845a45a14cc5026221ac1620James Dong
1291d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        int32_t isSync = false;
1292d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data->findInt32(kKeyIsSyncFrame, &isSync);
1293d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
1294d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        CHECK(meta_data->findInt64(kKeyTime, &timestampUs));
1295d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
1296d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong////////////////////////////////////////////////////////////////////////////////
12978644c14618d30d9e57a69df40ed939986ebf02c4James Dong        if (mSampleSizes.empty()) {
1298f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mStartTimestampUs = timestampUs;
1299f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mOwner->setStartTimestampUs(mStartTimestampUs);
13003c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        }
130148c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber
1302a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mResumed) {
1303c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong            previousPausedDurationUs += (timestampUs - mTrackDurationUs - lastDurationUs);
1304a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mResumed = false;
1305a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
1306a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
1307a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        timestampUs -= previousPausedDurationUs;
1308a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        LOGV("time stamp: %lld and previous paused duration %lld",
1309a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                timestampUs, previousPausedDurationUs);
1310c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong        if (timestampUs > mTrackDurationUs) {
1311c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong            mTrackDurationUs = timestampUs;
13123b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber        }
13133b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber
13148644c14618d30d9e57a69df40ed939986ebf02c4James Dong        mSampleSizes.push_back(sampleSize);
1315ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong        ++mNumSamples;
1316ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong        if (mNumSamples > 2) {
13178644c14618d30d9e57a69df40ed939986ebf02c4James Dong            if (lastDurationUs != timestampUs - lastTimestampUs) {
13188f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong                SttsTableEntry sttsEntry(sampleCount, lastDurationUs);
1319be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mSttsTableEntries.push_back(sttsEntry);
1320be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                sampleCount = 1;
1321be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            } else {
1322be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                ++sampleCount;
1323be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
1324be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
1325be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        if (mSamplesHaveSameSize) {
1326ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong            if (mNumSamples >= 2 && previousSampleSize != sampleSize) {
1327be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mSamplesHaveSameSize = false;
1328be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
13298644c14618d30d9e57a69df40ed939986ebf02c4James Dong            previousSampleSize = sampleSize;
1330be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
13318644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastDurationUs = timestampUs - lastTimestampUs;
13328644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastTimestampUs = timestampUs;
133320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1334d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        if (isSync != 0) {
1335ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong            mStssTableEntries.push_back(mNumSamples);
1336d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        }
1337d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
133893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (mTrackingProgressStatus) {
133993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            if (mPreviousTrackTimeUs <= 0) {
134093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong                mPreviousTrackTimeUs = mStartTimestampUs;
134193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            }
1342faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong            trackProgressStatus(timestampUs);
134393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
134458ae9c530247668f8af36e30d228c716c226b3d4James Dong        if (mOwner->numTracks() == 1) {
13451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            off_t offset = mIsAvc? mOwner->addLengthPrefixedSample_l(copy)
134658ae9c530247668f8af36e30d228c716c226b3d4James Dong                                 : mOwner->addSample_l(copy);
134758ae9c530247668f8af36e30d228c716c226b3d4James Dong            if (mChunkOffsets.empty()) {
134858ae9c530247668f8af36e30d228c716c226b3d4James Dong                mChunkOffsets.push_back(offset);
134958ae9c530247668f8af36e30d228c716c226b3d4James Dong            }
135058ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy->release();
135158ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy = NULL;
135258ae9c530247668f8af36e30d228c716c226b3d4James Dong            continue;
135358ae9c530247668f8af36e30d228c716c226b3d4James Dong        }
135413aec890216948b0c364f8f92792129d0335f506James Dong
135513aec890216948b0c364f8f92792129d0335f506James Dong        mChunkSamples.push_back(copy);
135613aec890216948b0c364f8f92792129d0335f506James Dong        if (interleaveDurationUs == 0) {
135713aec890216948b0c364f8f92792129d0335f506James Dong            StscTableEntry stscEntry(++nChunks, 1, 1);
135813aec890216948b0c364f8f92792129d0335f506James Dong            mStscTableEntries.push_back(stscEntry);
13591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            bufferChunk(timestampUs);
136013aec890216948b0c364f8f92792129d0335f506James Dong        } else {
136113aec890216948b0c364f8f92792129d0335f506James Dong            if (chunkTimestampUs == 0) {
136213aec890216948b0c364f8f92792129d0335f506James Dong                chunkTimestampUs = timestampUs;
136313aec890216948b0c364f8f92792129d0335f506James Dong            } else {
136413aec890216948b0c364f8f92792129d0335f506James Dong                if (timestampUs - chunkTimestampUs > interleaveDurationUs) {
136513aec890216948b0c364f8f92792129d0335f506James Dong                    ++nChunks;
13668644c14618d30d9e57a69df40ed939986ebf02c4James Dong                    if (collectStats) {
13678644c14618d30d9e57a69df40ed939986ebf02c4James Dong                        mChunkDurations.push_back(timestampUs - chunkTimestampUs);
13688644c14618d30d9e57a69df40ed939986ebf02c4James Dong                    }
136913aec890216948b0c364f8f92792129d0335f506James Dong                    if (nChunks == 1 ||  // First chunk
137013aec890216948b0c364f8f92792129d0335f506James Dong                        (--(mStscTableEntries.end()))->samplesPerChunk !=
137113aec890216948b0c364f8f92792129d0335f506James Dong                         mChunkSamples.size()) {
137213aec890216948b0c364f8f92792129d0335f506James Dong                        StscTableEntry stscEntry(nChunks,
137313aec890216948b0c364f8f92792129d0335f506James Dong                                mChunkSamples.size(), 1);
137413aec890216948b0c364f8f92792129d0335f506James Dong                        mStscTableEntries.push_back(stscEntry);
137513aec890216948b0c364f8f92792129d0335f506James Dong                    }
13761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                    bufferChunk(timestampUs);
137713aec890216948b0c364f8f92792129d0335f506James Dong                    chunkTimestampUs = timestampUs;
137813aec890216948b0c364f8f92792129d0335f506James Dong                }
137913aec890216948b0c364f8f92792129d0335f506James Dong            }
138013aec890216948b0c364f8f92792129d0335f506James Dong        }
138113aec890216948b0c364f8f92792129d0335f506James Dong
138220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
138325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
13848644c14618d30d9e57a69df40ed939986ebf02c4James Dong    if (mSampleSizes.empty()) {
138593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        err = UNKNOWN_ERROR;
1386f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong    }
1387faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    mOwner->trackProgressStatus(this, -1, err);
1388be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
138913aec890216948b0c364f8f92792129d0335f506James Dong    // Last chunk
139058ae9c530247668f8af36e30d228c716c226b3d4James Dong    if (mOwner->numTracks() == 1) {
1391ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong        StscTableEntry stscEntry(1, mNumSamples, 1);
139258ae9c530247668f8af36e30d228c716c226b3d4James Dong        mStscTableEntries.push_back(stscEntry);
139358ae9c530247668f8af36e30d228c716c226b3d4James Dong    } else if (!mChunkSamples.empty()) {
139413aec890216948b0c364f8f92792129d0335f506James Dong        ++nChunks;
139513aec890216948b0c364f8f92792129d0335f506James Dong        StscTableEntry stscEntry(nChunks, mChunkSamples.size(), 1);
139613aec890216948b0c364f8f92792129d0335f506James Dong        mStscTableEntries.push_back(stscEntry);
13971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        bufferChunk(timestampUs);
139813aec890216948b0c364f8f92792129d0335f506James Dong    }
139913aec890216948b0c364f8f92792129d0335f506James Dong
1400be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // We don't really know how long the last frame lasts, since
1401be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // there is no frame time after it, just repeat the previous
1402be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // frame's duration.
1403ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    if (mNumSamples == 1) {
14048f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        lastDurationUs = 0;  // A single sample's duration
1405be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    } else {
1406be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        ++sampleCount;  // Count for the last sample
1407be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    }
14088f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    SttsTableEntry sttsEntry(sampleCount, lastDurationUs);
1409be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    mSttsTableEntries.push_back(sttsEntry);
1410c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs += lastDurationUs;
141125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = true;
14121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. Max write time: %lld us - %s",
14131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            count, nZeroLengthFrames, mNumSamples, mMaxWriteTimeUs, mIsAudio? "audio": "video");
1414365a963142093a1cd8efdcea76b5f65096a5b115James Dong
14151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    logStatisticalData(mIsAudio);
1416365a963142093a1cd8efdcea76b5f65096a5b115James Dong}
1417365a963142093a1cd8efdcea76b5f65096a5b115James Dong
1418faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) {
1419faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    LOGV("trackProgressStatus: %lld us", timeUs);
1420215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    if (mTrackEveryTimeDurationUs > 0 &&
1421215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) {
142293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        LOGV("Fire time tracking progress status at %lld us", timeUs);
1423faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        mOwner->trackProgressStatus(this, timeUs - mPreviousTrackTimeUs, err);
142493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        mPreviousTrackTimeUs = timeUs;
142593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
142693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
142793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
1428faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::trackProgressStatus(
1429faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        const MPEG4Writer::Track* track, int64_t timeUs, status_t err) {
1430faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    Mutex::Autolock lock(mLock);
1431faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    int32_t nTracks = mTracks.size();
1432faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    CHECK(nTracks >= 1);
1433faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    CHECK(nTracks < 64);  // Arbitrary number
1434faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
1435faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    int32_t trackNum = 0;
1436faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong#if 0
1437faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // In the worst case, we can put the trackNum
1438faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // along with MEDIA_RECORDER_INFO_COMPLETION_STATUS
1439faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // to report the progress.
1440faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    for (List<Track *>::iterator it = mTracks.begin();
1441faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong         it != mTracks.end(); ++it, ++trackNum) {
1442faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        if (track == (*it)) {
1443faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong            break;
1444faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        }
1445faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
1446faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong#endif
1447faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    CHECK(trackNum < nTracks);
1448faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    trackNum <<= 16;
1449faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
1450faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Error notification
1451faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Do not consider ERROR_END_OF_STREAM an error
1452faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (err != OK && err != ERROR_END_OF_STREAM) {
1453faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        notify(MEDIA_RECORDER_EVENT_ERROR,
1454faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               trackNum | MEDIA_RECORDER_ERROR_UNKNOWN,
1455faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
1456faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        return;
1457faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
1458faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
1459faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (timeUs == -1) {
1460faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send completion notification
1461faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        notify(MEDIA_RECORDER_EVENT_INFO,
1462faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               trackNum | MEDIA_RECORDER_INFO_COMPLETION_STATUS,
1463faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
1464faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        return;
1465faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    } else {
1466faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send progress status
1467faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        notify(MEDIA_RECORDER_EVENT_INFO,
1468faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               trackNum | MEDIA_RECORDER_INFO_PROGRESS_TIME_STATUS,
1469faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               timeUs / 1000);
1470faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
1471faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong}
1472faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
1473215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dongvoid MPEG4Writer::Track::findMinAvgMaxSampleDurationMs(
1474215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        int32_t *min, int32_t *avg, int32_t *max) {
14758644c14618d30d9e57a69df40ed939986ebf02c4James Dong    CHECK(!mSampleSizes.empty());
1476c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    int32_t avgSampleDurationMs = mTrackDurationUs / 1000 / mNumSamples;
1477215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    int32_t minSampleDurationMs = 0x7FFFFFFF;
1478215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    int32_t maxSampleDurationMs = 0;
1479365a963142093a1cd8efdcea76b5f65096a5b115James Dong    for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin();
1480365a963142093a1cd8efdcea76b5f65096a5b115James Dong        it != mSttsTableEntries.end(); ++it) {
14818f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int32_t sampleDurationMs =
14828f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            (static_cast<int32_t>(it->sampleDurationUs) + 500) / 1000;
1483215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        if (sampleDurationMs > maxSampleDurationMs) {
1484215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong            maxSampleDurationMs = sampleDurationMs;
1485215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        } else if (sampleDurationMs < minSampleDurationMs) {
1486215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong            minSampleDurationMs = sampleDurationMs;
1487365a963142093a1cd8efdcea76b5f65096a5b115James Dong        }
1488215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        LOGI("sample duration: %d ms", sampleDurationMs);
1489365a963142093a1cd8efdcea76b5f65096a5b115James Dong    }
1490215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    CHECK(minSampleDurationMs != 0);
1491215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    CHECK(avgSampleDurationMs != 0);
1492215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    CHECK(maxSampleDurationMs != 0);
1493215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    *min = minSampleDurationMs;
1494215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    *avg = avgSampleDurationMs;
1495215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    *max = maxSampleDurationMs;
1496365a963142093a1cd8efdcea76b5f65096a5b115James Dong}
1497365a963142093a1cd8efdcea76b5f65096a5b115James Dong
1498365a963142093a1cd8efdcea76b5f65096a5b115James Dong// Don't count the last duration
1499365a963142093a1cd8efdcea76b5f65096a5b115James Dongvoid MPEG4Writer::Track::findMinMaxChunkDurations(int64_t *min, int64_t *max) {
1500365a963142093a1cd8efdcea76b5f65096a5b115James Dong    int64_t duration = mOwner->interleaveDuration();
1501365a963142093a1cd8efdcea76b5f65096a5b115James Dong    int64_t minChunkDuration = duration;
1502365a963142093a1cd8efdcea76b5f65096a5b115James Dong    int64_t maxChunkDuration = duration;
1503365a963142093a1cd8efdcea76b5f65096a5b115James Dong    if (mChunkDurations.size() > 1) {
1504365a963142093a1cd8efdcea76b5f65096a5b115James Dong        for (List<int64_t>::iterator it = mChunkDurations.begin();
1505365a963142093a1cd8efdcea76b5f65096a5b115James Dong            it != --mChunkDurations.end(); ++it) {
1506365a963142093a1cd8efdcea76b5f65096a5b115James Dong            if (minChunkDuration > (*it)) {
1507365a963142093a1cd8efdcea76b5f65096a5b115James Dong                minChunkDuration = (*it);
1508365a963142093a1cd8efdcea76b5f65096a5b115James Dong            } else if (maxChunkDuration < (*it)) {
1509365a963142093a1cd8efdcea76b5f65096a5b115James Dong                maxChunkDuration = (*it);
1510365a963142093a1cd8efdcea76b5f65096a5b115James Dong            }
1511365a963142093a1cd8efdcea76b5f65096a5b115James Dong        }
1512365a963142093a1cd8efdcea76b5f65096a5b115James Dong    }
1513365a963142093a1cd8efdcea76b5f65096a5b115James Dong    *min = minChunkDuration;
1514365a963142093a1cd8efdcea76b5f65096a5b115James Dong    *max = maxChunkDuration;
1515365a963142093a1cd8efdcea76b5f65096a5b115James Dong}
1516365a963142093a1cd8efdcea76b5f65096a5b115James Dong
1517365a963142093a1cd8efdcea76b5f65096a5b115James Dongvoid MPEG4Writer::Track::logStatisticalData(bool isAudio) {
1518c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    if (mTrackDurationUs <= 0 || mSampleSizes.empty()) {
1519365a963142093a1cd8efdcea76b5f65096a5b115James Dong        LOGI("nothing is recorded");
1520365a963142093a1cd8efdcea76b5f65096a5b115James Dong        return;
1521365a963142093a1cd8efdcea76b5f65096a5b115James Dong    }
1522365a963142093a1cd8efdcea76b5f65096a5b115James Dong
15238644c14618d30d9e57a69df40ed939986ebf02c4James Dong    bool collectStats = collectStatisticalData();
1524365a963142093a1cd8efdcea76b5f65096a5b115James Dong
1525365a963142093a1cd8efdcea76b5f65096a5b115James Dong    if (collectStats) {
1526215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        LOGI("%s track - duration %lld us, total %d frames",
1527c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong                isAudio? "audio": "video", mTrackDurationUs,
1528ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong                mNumSamples);
1529215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        int32_t min, avg, max;
1530215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        findMinAvgMaxSampleDurationMs(&min, &avg, &max);
1531215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        LOGI("min/avg/max sample duration (ms): %d/%d/%d", min, avg, max);
1532215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        if (!isAudio) {
1533215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong            float avgFps = 1000.0 / avg;
1534215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong            float minFps = 1000.0 / max;
1535215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong            float maxFps = 1000.0 / min;
1536365a963142093a1cd8efdcea76b5f65096a5b115James Dong            LOGI("min/avg/max frame rate (fps): %.2f/%.2f/%.2f",
1537215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong                minFps, avgFps, maxFps);
1538365a963142093a1cd8efdcea76b5f65096a5b115James Dong        }
1539365a963142093a1cd8efdcea76b5f65096a5b115James Dong
1540365a963142093a1cd8efdcea76b5f65096a5b115James Dong        int64_t totalBytes = 0;
15418644c14618d30d9e57a69df40ed939986ebf02c4James Dong        for (List<size_t>::iterator it = mSampleSizes.begin();
15428644c14618d30d9e57a69df40ed939986ebf02c4James Dong            it != mSampleSizes.end(); ++it) {
15438644c14618d30d9e57a69df40ed939986ebf02c4James Dong            totalBytes += (*it);
1544365a963142093a1cd8efdcea76b5f65096a5b115James Dong        }
1545c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong        float bitRate = (totalBytes * 8000000.0) / mTrackDurationUs;
1546365a963142093a1cd8efdcea76b5f65096a5b115James Dong        LOGI("avg bit rate (bps): %.2f", bitRate);
1547365a963142093a1cd8efdcea76b5f65096a5b115James Dong
1548365a963142093a1cd8efdcea76b5f65096a5b115James Dong        int64_t duration = mOwner->interleaveDuration();
1549365a963142093a1cd8efdcea76b5f65096a5b115James Dong        if (duration != 0) {  // If interleaving is enabled
1550365a963142093a1cd8efdcea76b5f65096a5b115James Dong            int64_t minChunk, maxChunk;
1551365a963142093a1cd8efdcea76b5f65096a5b115James Dong            findMinMaxChunkDurations(&minChunk, &maxChunk);
1552365a963142093a1cd8efdcea76b5f65096a5b115James Dong            LOGI("min/avg/max chunk duration (ms): %lld/%lld/%lld",
1553365a963142093a1cd8efdcea76b5f65096a5b115James Dong                minChunk, duration, maxChunk);
1554365a963142093a1cd8efdcea76b5f65096a5b115James Dong        }
1555365a963142093a1cd8efdcea76b5f65096a5b115James Dong    }
155613aec890216948b0c364f8f92792129d0335f506James Dong}
155713aec890216948b0c364f8f92792129d0335f506James Dong
15581c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::Track::bufferChunk(int64_t timestampUs) {
15591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("bufferChunk");
15601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
15611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    int64_t startTimeUs = systemTime() / 1000;
15621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Chunk chunk(this, timestampUs, mChunkSamples);
15631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mOwner->bufferChunk(chunk);
156413aec890216948b0c364f8f92792129d0335f506James Dong    mChunkSamples.clear();
15651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    int64_t endTimeUs = systemTime() / 1000;
15661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (mMaxWriteTimeUs < endTimeUs - startTimeUs) {
15671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mMaxWriteTimeUs = endTimeUs - startTimeUs;
15681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
156920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
157020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
15713b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const {
1572c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    return mTrackDurationUs;
157320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
157420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1575d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const {
1576d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return mEstimatedTrackSizeBytes;
1577d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
1578d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
15791acfe8649f8169caf2ff098c2dc2de880d9a3760James Dongvoid MPEG4Writer::Track::writeTrackHeader(
15801acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        int32_t trackID, bool use32BitOffset) {
158120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const char *mime;
158220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool success = mMeta->findCString(kKeyMIMEType, &mime);
15830c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(success);
158420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
15858f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    LOGV("%s track time scale: %d",
15861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsAudio? "Audio": "Video", mTimeScale);
15878f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
158820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
158920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    time_t now = time(NULL);
15908f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int32_t mvhdTimeScale = mOwner->getTimeScale();
15918f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t trakDurationUs = getDurationUs();
159220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
159320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOwner->beginBox("trak");
159420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
159520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->beginBox("tkhd");
15961acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        // Flags = 7 to indicate that the track is enabled, and
15971acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        // part of the presentation
15981acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        mOwner->writeInt32(0x07);          // version=0, flags=7
159920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(now);           // creation time
160020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(now);           // modification time
160120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(trackID);
160220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);             // reserved
16038f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int32_t tkhdDuration =
16048f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
16058f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        mOwner->writeInt32(tkhdDuration);  // in mvhd timescale
160620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);             // reserved
160720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);             // reserved
160820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt16(0);             // layer
160920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt16(0);             // alternate group
16101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mOwner->writeInt16(mIsAudio ? 0x100 : 0);  // volume
161120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt16(0);             // reserved
161220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
161320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0x10000);       // matrix
161420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
161520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
161620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
161720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0x10000);
161820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
161920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
162020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
162120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0x40000000);
162220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
16231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (mIsAudio) {
162420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);
162520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);
162620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        } else {
162720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            int32_t width, height;
162820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            bool success = mMeta->findInt32(kKeyWidth, &width);
162920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            success = success && mMeta->findInt32(kKeyHeight, &height);
16300c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber            CHECK(success);
163120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1632050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->writeInt32(width << 16);   // 32-bit fixed-point value
1633050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->writeInt32(height << 16);  // 32-bit fixed-point value
163420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
163520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->endBox();  // tkhd
163620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1637f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong      int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
1638f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong      if (mStartTimestampUs != moovStartTimeUs) {
16393c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        mOwner->beginBox("edts");
16403c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong          mOwner->beginBox("elst");
16411acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong            mOwner->writeInt32(0);           // version=0, flags=0: 32-bit time
16421acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong            mOwner->writeInt32(2);           // never ends with an empty list
16438f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
16448f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            // First elst entry: specify the starting time offset
16458f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            int64_t offsetUs = mStartTimestampUs - moovStartTimeUs;
16468f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            int32_t seg = (offsetUs * mvhdTimeScale + 5E5) / 1E6;
16478f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            mOwner->writeInt32(seg);         // in mvhd timecale
16488f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            mOwner->writeInt32(-1);          // starting time offset
16498f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            mOwner->writeInt32(1 << 16);     // rate = 1.0
16508f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
16518f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            // Second elst entry: specify the track duration
16528f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            seg = (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
16538f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            mOwner->writeInt32(seg);         // in mvhd timescale
16541acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong            mOwner->writeInt32(0);
16551acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong            mOwner->writeInt32(1 << 16);
16563c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong          mOwner->endBox();
16573c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        mOwner->endBox();
16583c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong      }
16593c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
166020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->beginBox("mdia");
166120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
166220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("mdhd");
166320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // version=0, flags=0
166420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(now);           // creation time
166520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(now);           // modification time
16668f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong          mOwner->writeInt32(mTimeScale);    // media timescale
16678f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong          int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6;
16688f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong          mOwner->writeInt32(mdhdDuration);  // use media timescale
16691acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // Language follows the three letter standard ISO-639-2/T
16701acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // 'e', 'n', 'g' for "English", for instance.
16711acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // Each character is packed as the difference between its ASCII value and 0x60.
16721acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // For "English", these are 00101, 01110, 00111.
16731acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // XXX: Where is the padding bit located: 0x15C7?
16741acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          mOwner->writeInt16(0);             // language code
167520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt16(0);             // predefined
167620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->endBox();
167720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
167820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("hdlr");
167920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // version=0, flags=0
1680050b28a593350047845a45a14cc5026221ac1620James Dong          mOwner->writeInt32(0);             // component type: should be mhlr
16811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong          mOwner->writeFourcc(mIsAudio ? "soun" : "vide");  // component subtype
168220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // reserved
168320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // reserved
168420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // reserved
16851acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // Removing "r" for the name string just makes the string 4 byte aligned
16861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong          mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle");  // name
168720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->endBox();
168820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
168920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("minf");
16901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong          if (mIsAudio) {
169120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->beginBox("smhd");
169220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt32(0);           // version=0, flags=0
169320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // balance
169420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // reserved
169520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->endBox();
169620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          } else {
169720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->beginBox("vmhd");
16981acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong              mOwner->writeInt32(0x01);        // version=0, flags=1
169920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // graphics mode
170020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // opcolor
170120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);
170220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);
170320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->endBox();
170420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          }
1705050b28a593350047845a45a14cc5026221ac1620James Dong
1706050b28a593350047845a45a14cc5026221ac1620James Dong          mOwner->beginBox("dinf");
1707050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->beginBox("dref");
1708050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->writeInt32(0);  // version=0, flags=0
17091acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong              mOwner->writeInt32(1);  // entry count (either url or urn)
17101acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong              // The table index here refers to the sample description index
17111acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong              // in the sample table entries.
1712050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->beginBox("url ");
17131acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                mOwner->writeInt32(1);  // version=0, flags=1 (self-contained)
1714050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->endBox();  // url
1715050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->endBox();  // dref
1716050b28a593350047845a45a14cc5026221ac1620James Dong          mOwner->endBox();  // dinf
1717050b28a593350047845a45a14cc5026221ac1620James Dong
171820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("stbl");
171920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
172020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stsd");
172120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);               // version=0, flags=0
172220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(1);               // entry count
17231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (mIsAudio) {
172425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                const char *fourcc = NULL;
172518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) {
172625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    fourcc = "samr";
172718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
172825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    fourcc = "sawb";
1729050b28a593350047845a45a14cc5026221ac1620James Dong                } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
1730050b28a593350047845a45a14cc5026221ac1620James Dong                    fourcc = "mp4a";
173125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                } else {
173225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    LOGE("Unknown mime type '%s'.", mime);
173325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    CHECK(!"should not be here, unknown mime type.");
173425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                }
173525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
173625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                mOwner->beginBox(fourcc);          // audio format
173720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
173820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
1739050b28a593350047845a45a14cc5026221ac1620James Dong                  mOwner->writeInt16(0x1);         // data ref index
174020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
174120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
1742050b28a593350047845a45a14cc5026221ac1620James Dong                  int32_t nChannels;
1743050b28a593350047845a45a14cc5026221ac1620James Dong                  CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels));
1744050b28a593350047845a45a14cc5026221ac1620James Dong                  mOwner->writeInt16(nChannels);   // channel count
174520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(16);          // sample size
174620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // predefined
174720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
174820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
174920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  int32_t samplerate;
175020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  bool success = mMeta->findInt32(kKeySampleRate, &samplerate);
17510c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                  CHECK(success);
175220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
175320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(samplerate << 16);
1754050b28a593350047845a45a14cc5026221ac1620James Dong                  if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
1755050b28a593350047845a45a14cc5026221ac1620James Dong                    mOwner->beginBox("esds");
1756050b28a593350047845a45a14cc5026221ac1620James Dong
1757050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt32(0);     // version=0, flags=0
1758050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x03);   // ES_DescrTag
1759050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(23 + mCodecSpecificDataSize);
1760050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt16(0x0000);// ES_ID
1761050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x00);
1762050b28a593350047845a45a14cc5026221ac1620James Dong
1763050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x04);   // DecoderConfigDescrTag
1764050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(15 + mCodecSpecificDataSize);
1765050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x40);   // objectTypeIndication ISO/IEC 14492-2
1766050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x15);   // streamType AudioStream
1767050b28a593350047845a45a14cc5026221ac1620James Dong
1768050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt16(0x03);  // XXX
1769050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x00);   // buffer size 24-bit
1770050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt32(96000); // max bit rate
1771050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt32(96000); // avg bit rate
1772050b28a593350047845a45a14cc5026221ac1620James Dong
1773050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x05);   // DecoderSpecificInfoTag
1774050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(mCodecSpecificDataSize);
1775050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
1776050b28a593350047845a45a14cc5026221ac1620James Dong
1777050b28a593350047845a45a14cc5026221ac1620James Dong                        static const uint8_t kData2[] = {
1778050b28a593350047845a45a14cc5026221ac1620James Dong                            0x06,  // SLConfigDescriptorTag
1779050b28a593350047845a45a14cc5026221ac1620James Dong                            0x01,
1780050b28a593350047845a45a14cc5026221ac1620James Dong                            0x02
1781050b28a593350047845a45a14cc5026221ac1620James Dong                        };
1782050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->write(kData2, sizeof(kData2));
1783050b28a593350047845a45a14cc5026221ac1620James Dong
1784050b28a593350047845a45a14cc5026221ac1620James Dong                    mOwner->endBox();  // esds
17855aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                  } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) ||
17865aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                             !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
17875aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                    // 3gpp2 Spec AMRSampleEntry fields
17885aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                    mOwner->beginBox("damr");
17895aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                      mOwner->writeCString("   ");  // vendor: 4 bytes
17905aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                      mOwner->writeInt8(0);         // decoder version
17915aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                      mOwner->writeInt16(0x83FF);   // mode set: all enabled
17925aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                      mOwner->writeInt8(0);         // mode change period
17935aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                      mOwner->writeInt8(1);         // frames per sample
17945aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                    mOwner->endBox();
1795050b28a593350047845a45a14cc5026221ac1620James Dong                  }
179620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mOwner->endBox();
179720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
179818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
179920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    mOwner->beginBox("mp4v");
180018291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
180120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    mOwner->beginBox("s263");
180230ab66297501757d745b9ae10da61adcd891f497Andreas Huber                } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
180330ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    mOwner->beginBox("avc1");
180420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                } else {
180525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    LOGE("Unknown mime type '%s'.", mime);
18060c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                    CHECK(!"should not be here, unknown mime type.");
180720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
180820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
180920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
181020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
18111acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                  mOwner->writeInt16(1);           // data ref index
181220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // predefined
181320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
181420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // predefined
181520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // predefined
181620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // predefined
181720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
181820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  int32_t width, height;
181920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  bool success = mMeta->findInt32(kKeyWidth, &width);
182020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  success = success && mMeta->findInt32(kKeyHeight, &height);
18210c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                  CHECK(success);
182220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
182320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(width);
182420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(height);
182520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0x480000);    // horiz resolution
182620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0x480000);    // vert resolution
182720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
182820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(1);           // frame count
182920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->write("                                ", 32);
183020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0x18);        // depth
183120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(-1);          // predefined
183220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
18330c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                  CHECK(23 + mCodecSpecificDataSize < 128);
183420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
183518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                  if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
183620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->beginBox("esds");
183720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
183820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt32(0);           // version=0, flags=0
183920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
184020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x03);  // ES_DescrTag
184120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(23 + mCodecSpecificDataSize);
184220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt16(0x0000);  // ES_ID
184320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x1f);
184420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
184520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x04);  // DecoderConfigDescrTag
184620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(15 + mCodecSpecificDataSize);
184720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x20);  // objectTypeIndication ISO/IEC 14492-2
184820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x11);  // streamType VisualStream
184920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
185020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        static const uint8_t kData[] = {
185120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x01, 0x77, 0x00,
185220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x00, 0x03, 0xe8, 0x00,
185320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x00, 0x03, 0xe8, 0x00
185420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        };
185520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->write(kData, sizeof(kData));
1856050b28a593350047845a45a14cc5026221ac1620James Dong
185720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x05);  // DecoderSpecificInfoTag
185820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
185920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(mCodecSpecificDataSize);
186020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
186120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
186220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        static const uint8_t kData2[] = {
186320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x06,  // SLConfigDescriptorTag
186420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x01,
186520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x02
186620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        };
186720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->write(kData2, sizeof(kData2));
186820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
186920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->endBox();  // esds
187018291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                  } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
187120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->beginBox("d263");
187220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
187320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt32(0);  // vendor
187420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt8(0);   // decoder version
187520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt8(10);  // level: 10
187620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt8(0);   // profile: 0
187720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
187820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->endBox();  // d263
187930ab66297501757d745b9ae10da61adcd891f497Andreas Huber                  } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
188030ab66297501757d745b9ae10da61adcd891f497Andreas Huber                      mOwner->beginBox("avcC");
188130ab66297501757d745b9ae10da61adcd891f497Andreas Huber                        mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
188230ab66297501757d745b9ae10da61adcd891f497Andreas Huber                      mOwner->endBox();  // avcC
188320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  }
188430ab66297501757d745b9ae10da61adcd891f497Andreas Huber
18851acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                  mOwner->beginBox("pasp");
18861acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                    // This is useful if the pixel is not square
18871acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                    mOwner->writeInt32(1 << 16);  // hspacing
18881acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                    mOwner->writeInt32(1 << 16);  // vspacing
18891acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                  mOwner->endBox();  // pasp
189030ab66297501757d745b9ae10da61adcd891f497Andreas Huber                mOwner->endBox();  // mp4v, s263 or avc1
189120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
189220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stsd
189320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
189420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stts");
189520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
1896be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            mOwner->writeInt32(mSttsTableEntries.size());
1897be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin();
1898be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                 it != mSttsTableEntries.end(); ++it) {
1899be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mOwner->writeInt32(it->sampleCount);
19008f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong                int32_t dur = (it->sampleDurationUs * mTimeScale + 5E5) / 1E6;
19018f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong                mOwner->writeInt32(dur);
190220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
190320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stts
190420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
19051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong          if (!mIsAudio) {
1906050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->beginBox("stss");
1907050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->writeInt32(0);  // version=0, flags=0
1908050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->writeInt32(mStssTableEntries.size());  // number of sync frames
1909050b28a593350047845a45a14cc5026221ac1620James Dong              for (List<int32_t>::iterator it = mStssTableEntries.begin();
1910050b28a593350047845a45a14cc5026221ac1620James Dong                   it != mStssTableEntries.end(); ++it) {
1911050b28a593350047845a45a14cc5026221ac1620James Dong                  mOwner->writeInt32(*it);
1912050b28a593350047845a45a14cc5026221ac1620James Dong              }
1913050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->endBox();  // stss
1914050b28a593350047845a45a14cc5026221ac1620James Dong          }
1915050b28a593350047845a45a14cc5026221ac1620James Dong
191620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stsz");
191720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
1918be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            if (mSamplesHaveSameSize) {
19198644c14618d30d9e57a69df40ed939986ebf02c4James Dong                List<size_t>::iterator it = mSampleSizes.begin();
19208644c14618d30d9e57a69df40ed939986ebf02c4James Dong                mOwner->writeInt32(*it);  // default sample size
1921be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            } else {
1922be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mOwner->writeInt32(0);
1923be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
1924ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong            mOwner->writeInt32(mNumSamples);
1925be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            if (!mSamplesHaveSameSize) {
19268644c14618d30d9e57a69df40ed939986ebf02c4James Dong                for (List<size_t>::iterator it = mSampleSizes.begin();
19278644c14618d30d9e57a69df40ed939986ebf02c4James Dong                     it != mSampleSizes.end(); ++it) {
19288644c14618d30d9e57a69df40ed939986ebf02c4James Dong                    mOwner->writeInt32(*it);
1929be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                }
193020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
193120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stsz
193220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
193320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stsc");
193420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
193513aec890216948b0c364f8f92792129d0335f506James Dong            mOwner->writeInt32(mStscTableEntries.size());
193613aec890216948b0c364f8f92792129d0335f506James Dong            for (List<StscTableEntry>::iterator it = mStscTableEntries.begin();
193713aec890216948b0c364f8f92792129d0335f506James Dong                 it != mStscTableEntries.end(); ++it) {
193813aec890216948b0c364f8f92792129d0335f506James Dong                mOwner->writeInt32(it->firstChunk);
193913aec890216948b0c364f8f92792129d0335f506James Dong                mOwner->writeInt32(it->samplesPerChunk);
194013aec890216948b0c364f8f92792129d0335f506James Dong                mOwner->writeInt32(it->sampleDescriptionId);
194120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
194220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stsc
19431acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          mOwner->beginBox(use32BitOffset? "stco": "co64");
194420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
194513aec890216948b0c364f8f92792129d0335f506James Dong            mOwner->writeInt32(mChunkOffsets.size());
194613aec890216948b0c364f8f92792129d0335f506James Dong            for (List<off_t>::iterator it = mChunkOffsets.begin();
194713aec890216948b0c364f8f92792129d0335f506James Dong                 it != mChunkOffsets.end(); ++it) {
19481acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                if (use32BitOffset) {
19491acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                    mOwner->writeInt32(static_cast<int32_t>(*it));
19501acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                } else {
19511acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                    mOwner->writeInt64((*it));
19521acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                }
195320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
19548f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong          mOwner->endBox();  // stco or co64
195520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
195620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->endBox();  // stbl
19571acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong       mOwner->endBox();  // minf
195820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->endBox();  // mdia
195920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOwner->endBox();  // trak
196020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
196120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
196220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
1963