MPEG4Writer.cpp revision 2dec2b5be2056c6d9428897dc672185872d30d17
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
3720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android {
3820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Writer::Track {
4020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic:
4125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    Track(MPEG4Writer *owner, const sp<MediaSource> &source);
4220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    ~Track();
4320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
44f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    status_t start(int64_t startTimeUs);
4520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void stop();
46a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    void pause();
4725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool reachedEOS();
4820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
493b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber    int64_t getDurationUs() const;
50d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t getEstimatedTrackSizeBytes() const;
511acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    void writeTrackHeader(int32_t trackID, bool use32BitOffset = true);
5220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate:
5420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Writer *mOwner;
5520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MetaData> mMeta;
56693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    sp<MediaSource> mSource;
5720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    volatile bool mDone;
58a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mPaused;
59a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mResumed;
603b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber    int64_t mMaxTimeStampUs;
61d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t mEstimatedTrackSizeBytes;
6220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_t mThread;
6420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    struct SampleInfo {
6620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        size_t size;
6720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        int64_t timestamp;
6820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    };
6913aec890216948b0c364f8f92792129d0335f506James Dong    List<SampleInfo>    mSampleInfos;
70be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    bool                mSamplesHaveSameSize;
71be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
7213aec890216948b0c364f8f92792129d0335f506James Dong    List<MediaBuffer *> mChunkSamples;
7313aec890216948b0c364f8f92792129d0335f506James Dong    List<off_t>         mChunkOffsets;
7413aec890216948b0c364f8f92792129d0335f506James Dong
7513aec890216948b0c364f8f92792129d0335f506James Dong    struct StscTableEntry {
7613aec890216948b0c364f8f92792129d0335f506James Dong
7713aec890216948b0c364f8f92792129d0335f506James Dong        StscTableEntry(uint32_t chunk, uint32_t samples, uint32_t id)
7813aec890216948b0c364f8f92792129d0335f506James Dong            : firstChunk(chunk),
7913aec890216948b0c364f8f92792129d0335f506James Dong              samplesPerChunk(samples),
8013aec890216948b0c364f8f92792129d0335f506James Dong              sampleDescriptionId(id) {}
8113aec890216948b0c364f8f92792129d0335f506James Dong
8213aec890216948b0c364f8f92792129d0335f506James Dong        uint32_t firstChunk;
8313aec890216948b0c364f8f92792129d0335f506James Dong        uint32_t samplesPerChunk;
8413aec890216948b0c364f8f92792129d0335f506James Dong        uint32_t sampleDescriptionId;
8513aec890216948b0c364f8f92792129d0335f506James Dong    };
8613aec890216948b0c364f8f92792129d0335f506James Dong    List<StscTableEntry> mStscTableEntries;
8720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
88050b28a593350047845a45a14cc5026221ac1620James Dong    List<int32_t> mStssTableEntries;
89365a963142093a1cd8efdcea76b5f65096a5b115James Dong    List<int64_t> mChunkDurations;
90050b28a593350047845a45a14cc5026221ac1620James Dong
91be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    struct SttsTableEntry {
92be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
93be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        SttsTableEntry(uint32_t count, uint32_t duration)
94be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            : sampleCount(count), sampleDuration(duration) {}
95be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
96be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        uint32_t sampleCount;
97be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        uint32_t sampleDuration;
98be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    };
99be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    List<SttsTableEntry> mSttsTableEntries;
100be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
10120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *mCodecSpecificData;
10220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t mCodecSpecificDataSize;
103548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    bool mGotAllCodecSpecificData;
10420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool mReachedEOS;
1063c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    int64_t mStartTimestampUs;
10725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
10820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    static void *ThreadWrapper(void *me);
10920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void threadEntry();
11020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
11103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    status_t makeAVCCodecSpecificData(
11203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            const uint8_t *data, size_t size);
11313aec890216948b0c364f8f92792129d0335f506James Dong    void writeOneChunk(bool isAvc);
114365a963142093a1cd8efdcea76b5f65096a5b115James Dong    void logStatisticalData(bool isAudio);
115365a963142093a1cd8efdcea76b5f65096a5b115James Dong    void findMinMaxFrameRates(float *minFps, float *maxFps);
116365a963142093a1cd8efdcea76b5f65096a5b115James Dong    void findMinMaxChunkDurations(int64_t *min, int64_t *max);
11703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
11820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track(const Track &);
11920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track &operator=(const Track &);
12020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
12120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#define USE_NALLEN_FOUR         1
12303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
12420111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::MPEG4Writer(const char *filename)
12520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mFile(fopen(filename, "wb")),
1261acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong      mUse32BitOffset(true),
127a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
128a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mStarted(false),
12920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOffset(0),
13013aec890216948b0c364f8f92792129d0335f506James Dong      mMdatOffset(0),
1317837c17063a4c50bc856ba59418516fdab731de7James Dong      mEstimatedMoovBoxSize(0),
13213aec890216948b0c364f8f92792129d0335f506James Dong      mInterleaveDurationUs(500000) {
1330c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(mFile != NULL);
13420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
13520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
13630ab66297501757d745b9ae10da61adcd891f497Andreas HuberMPEG4Writer::MPEG4Writer(int fd)
13730ab66297501757d745b9ae10da61adcd891f497Andreas Huber    : mFile(fdopen(fd, "wb")),
1381acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong      mUse32BitOffset(true),
139a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
140a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mStarted(false),
14130ab66297501757d745b9ae10da61adcd891f497Andreas Huber      mOffset(0),
14213aec890216948b0c364f8f92792129d0335f506James Dong      mMdatOffset(0),
1437837c17063a4c50bc856ba59418516fdab731de7James Dong      mEstimatedMoovBoxSize(0),
14413aec890216948b0c364f8f92792129d0335f506James Dong      mInterleaveDurationUs(500000) {
14530ab66297501757d745b9ae10da61adcd891f497Andreas Huber    CHECK(mFile != NULL);
14630ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
14730ab66297501757d745b9ae10da61adcd891f497Andreas Huber
14820111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() {
14920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    stop();
15020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
15120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
15220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber         it != mTracks.end(); ++it) {
15320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        delete *it;
15420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
15520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.clear();
15620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
15720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1582dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huberstatus_t MPEG4Writer::addSource(const sp<MediaSource> &source) {
15925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    Track *track = new Track(this, source);
16020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.push_back(track);
1612dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
1622dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    return OK;
16320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
16420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
165a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dongstatus_t MPEG4Writer::startTracks() {
166f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    int64_t startTimeUs = systemTime() / 1000;
167a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
168a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
169f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        status_t err = (*it)->start(startTimeUs);
170a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
171a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (err != OK) {
172a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            for (List<Track *>::iterator it2 = mTracks.begin();
173a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                 it2 != it; ++it2) {
174a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                (*it2)->stop();
175a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            }
176a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
177a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            return err;
178a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
179a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
180a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    return OK;
181a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
182a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
1832dec2b5be2056c6d9428897dc672185872d30d17James Dongint64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) {
1842dec2b5be2056c6d9428897dc672185872d30d17James Dong    // This implementation is highly experimental/heurisitic.
1852dec2b5be2056c6d9428897dc672185872d30d17James Dong    //
1862dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Statistical analysis shows that metadata usually accounts
1872dec2b5be2056c6d9428897dc672185872d30d17James Dong    // for a small portion of the total file size, usually < 0.6%.
1882dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Currently, lets set to 0.4% for now.
1892dec2b5be2056c6d9428897dc672185872d30d17James Dong
1902dec2b5be2056c6d9428897dc672185872d30d17James Dong    // The default MIN_MOOV_BOX_SIZE is set to 0.4% x 1MB,
1912dec2b5be2056c6d9428897dc672185872d30d17James Dong    // where 1MB is the common file size limit for MMS application.
1922dec2b5be2056c6d9428897dc672185872d30d17James Dong    // The default MAX _MOOV_BOX_SIZE value is based on about 4
1932dec2b5be2056c6d9428897dc672185872d30d17James Dong    // minute video recording with a bit rate about 3 Mbps, because
1942dec2b5be2056c6d9428897dc672185872d30d17James Dong    // statistics also show that most of the video captured are going
1952dec2b5be2056c6d9428897dc672185872d30d17James Dong    // to be less than 3 minutes.
1962dec2b5be2056c6d9428897dc672185872d30d17James Dong
1972dec2b5be2056c6d9428897dc672185872d30d17James Dong    // If the estimation is wrong, we will pay the price of wasting
1982dec2b5be2056c6d9428897dc672185872d30d17James Dong    // some reserved space. This should not happen so often statistically.
1992dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int32_t factor = mUse32BitOffset? 1: 2;
2002dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int64_t MIN_MOOV_BOX_SIZE = 4 * 1024;  // 4 KB
2012dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000);
2022dec2b5be2056c6d9428897dc672185872d30d17James Dong    int64_t size = MIN_MOOV_BOX_SIZE;
2032dec2b5be2056c6d9428897dc672185872d30d17James Dong
2042dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (mMaxFileSizeLimitBytes != 0) {
2052dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = mMaxFileSizeLimitBytes * 4 / 1000;
2062dec2b5be2056c6d9428897dc672185872d30d17James Dong    } else if (mMaxFileDurationLimitUs != 0) {
2072dec2b5be2056c6d9428897dc672185872d30d17James Dong        if (bitRate <= 0) {
2082dec2b5be2056c6d9428897dc672185872d30d17James Dong            // We could not estimate the file size since bitRate is not set.
2092dec2b5be2056c6d9428897dc672185872d30d17James Dong            size = MIN_MOOV_BOX_SIZE;
2102dec2b5be2056c6d9428897dc672185872d30d17James Dong        } else {
2112dec2b5be2056c6d9428897dc672185872d30d17James Dong            size = ((mMaxFileDurationLimitUs * bitRate * 4) / 1000 / 8000000);
2122dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
2132dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
2142dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size < MIN_MOOV_BOX_SIZE) {
2152dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MIN_MOOV_BOX_SIZE;
2162dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
2172dec2b5be2056c6d9428897dc672185872d30d17James Dong
2182dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Any long duration recording will be probably end up with
2192dec2b5be2056c6d9428897dc672185872d30d17James Dong    // non-streamable mp4 file.
2202dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size > MAX_MOOV_BOX_SIZE) {
2212dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MAX_MOOV_BOX_SIZE;
2222dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
2232dec2b5be2056c6d9428897dc672185872d30d17James Dong
2242dec2b5be2056c6d9428897dc672185872d30d17James Dong    LOGI("limits: %lld/%lld bytes/us, bit rate: %d bps and the estimated"
2252dec2b5be2056c6d9428897dc672185872d30d17James Dong         " moov size %lld bytes",
2262dec2b5be2056c6d9428897dc672185872d30d17James Dong         mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size);
2272dec2b5be2056c6d9428897dc672185872d30d17James Dong    return factor * size;
2282dec2b5be2056c6d9428897dc672185872d30d17James Dong}
2292dec2b5be2056c6d9428897dc672185872d30d17James Dong
2302dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t MPEG4Writer::start(MetaData *param) {
23120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mFile == NULL) {
23225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return UNKNOWN_ERROR;
23320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
23420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2352dec2b5be2056c6d9428897dc672185872d30d17James Dong    int32_t use64BitOffset;
2362dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (param &&
2372dec2b5be2056c6d9428897dc672185872d30d17James Dong        param->findInt32(kKey64BitFileOffset, &use64BitOffset) &&
2382dec2b5be2056c6d9428897dc672185872d30d17James Dong        use64BitOffset) {
2392dec2b5be2056c6d9428897dc672185872d30d17James Dong        mUse32BitOffset = false;
2402dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
2412dec2b5be2056c6d9428897dc672185872d30d17James Dong
2422dec2b5be2056c6d9428897dc672185872d30d17James Dong    // System property can overwrite the file offset bits parameter
2432dec2b5be2056c6d9428897dc672185872d30d17James Dong    char value[PROPERTY_VALUE_MAX];
2442dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (property_get("media.stagefright.record-64bits", value, NULL)
2452dec2b5be2056c6d9428897dc672185872d30d17James Dong        && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
2462dec2b5be2056c6d9428897dc672185872d30d17James Dong        mUse32BitOffset = false;
2472dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
2482dec2b5be2056c6d9428897dc672185872d30d17James Dong
249065d1aff96818df54456053f1574aec8a234d0deJames Dong    mStartTimestampUs = -1;
250a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (mStarted) {
251a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused) {
252a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mPaused = false;
253a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            return startTracks();
254a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
255a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
256a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
257a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
2587837c17063a4c50bc856ba59418516fdab731de7James Dong    mStreamableFile = true;
2597837c17063a4c50bc856ba59418516fdab731de7James Dong    mWriteMoovBoxToMemory = false;
2607837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBuffer = NULL;
2617837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
2627837c17063a4c50bc856ba59418516fdab731de7James Dong
26320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    beginBox("ftyp");
26420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      writeFourcc("isom");
26520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      writeInt32(0);
26620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      writeFourcc("isom");
26720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    endBox();
26820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2697837c17063a4c50bc856ba59418516fdab731de7James Dong    mFreeBoxOffset = mOffset;
27020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2717837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mEstimatedMoovBoxSize == 0) {
2722dec2b5be2056c6d9428897dc672185872d30d17James Dong        int32_t bitRate = -1;
2732dec2b5be2056c6d9428897dc672185872d30d17James Dong        if (param) {
2742dec2b5be2056c6d9428897dc672185872d30d17James Dong            param->findInt32(kKeyBitRate, &bitRate);
2752dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
2762dec2b5be2056c6d9428897dc672185872d30d17James Dong        mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate);
2777837c17063a4c50bc856ba59418516fdab731de7James Dong    }
2787837c17063a4c50bc856ba59418516fdab731de7James Dong    CHECK(mEstimatedMoovBoxSize >= 8);
2797837c17063a4c50bc856ba59418516fdab731de7James Dong    fseeko(mFile, mFreeBoxOffset, SEEK_SET);
2807837c17063a4c50bc856ba59418516fdab731de7James Dong    writeInt32(mEstimatedMoovBoxSize);
2817837c17063a4c50bc856ba59418516fdab731de7James Dong    write("free", 4);
2827837c17063a4c50bc856ba59418516fdab731de7James Dong
2837837c17063a4c50bc856ba59418516fdab731de7James Dong    mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize;
2847837c17063a4c50bc856ba59418516fdab731de7James Dong    mOffset = mMdatOffset;
2857837c17063a4c50bc856ba59418516fdab731de7James Dong    fseeko(mFile, mMdatOffset, SEEK_SET);
2861acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
2871acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("????mdat", 8);
2881acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
2891acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("\x00\x00\x00\x01mdat????????", 16);
2901acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
29125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
292a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    status_t err = startTracks();
293a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (err != OK) {
294a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return err;
29520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
296a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mStarted = true;
29725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
29820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
29920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
300a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dongvoid MPEG4Writer::pause() {
301a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (mFile == NULL) {
302a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return;
303a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
304a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
305a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
306a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
307a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        (*it)->pause();
308a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
309a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
310a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
31120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::stop() {
31220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mFile == NULL) {
31320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return;
31420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
31520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
31620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int64_t max_duration = 0;
31720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
31820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber         it != mTracks.end(); ++it) {
31920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        (*it)->stop();
32020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3213b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber        int64_t duration = (*it)->getDurationUs();
32220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (duration > max_duration) {
32320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            max_duration = duration;
32420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
32520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
32620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3277837c17063a4c50bc856ba59418516fdab731de7James Dong
32820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // Fix up the size of the 'mdat' chunk.
3291acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
3301acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        fseeko(mFile, mMdatOffset, SEEK_SET);
3311acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        int32_t size = htonl(static_cast<int32_t>(mOffset - mMdatOffset));
3321acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        fwrite(&size, 1, 4, mFile);
3331acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
3341acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        fseeko(mFile, mMdatOffset + 8, SEEK_SET);
3351acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        int64_t size = mOffset - mMdatOffset;
3361acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        size = hton64(size);
3371acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        fwrite(&size, 1, 8, mFile);
3381acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
3397837c17063a4c50bc856ba59418516fdab731de7James Dong    fseeko(mFile, mOffset, SEEK_SET);
34020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
34120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    time_t now = time(NULL);
3427837c17063a4c50bc856ba59418516fdab731de7James Dong    const off_t moovOffset = mOffset;
3437837c17063a4c50bc856ba59418516fdab731de7James Dong    mWriteMoovBoxToMemory = true;
3447837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize);
3457837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
3467837c17063a4c50bc856ba59418516fdab731de7James Dong    CHECK(mMoovBoxBuffer != NULL);
3471acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    int32_t timeScale = 1000;
3481acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    int32_t duration = max_duration / timeScale;
34920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
35020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    beginBox("moov");
35120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
35220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      beginBox("mvhd");
35320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // version=0, flags=0
35420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(now);           // creation time
35520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(now);           // modification time
3561acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        writeInt32(timeScale);          // timescale
3571acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        writeInt32(duration);
3581acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        writeInt32(0x10000);       // rate: 1.0
35920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt16(0x100);         // volume
36020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt16(0);             // reserved
36120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // reserved
36220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // reserved
36320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0x10000);       // matrix
36420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
36520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
36620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
36720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0x10000);
36820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
36920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
37020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
37120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0x40000000);
37220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
37320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
37420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
37520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
37620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
37720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
37820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(mTracks.size() + 1);  // nextTrackID
37920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      endBox();  // mvhd
38020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
38120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      int32_t id = 1;
38220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      for (List<Track *>::iterator it = mTracks.begin();
38320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber           it != mTracks.end(); ++it, ++id) {
3841acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          (*it)->writeTrackHeader(id, mUse32BitOffset);
38520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      }
38620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    endBox();  // moov
38720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3887837c17063a4c50bc856ba59418516fdab731de7James Dong    mWriteMoovBoxToMemory = false;
3897837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mStreamableFile) {
3907837c17063a4c50bc856ba59418516fdab731de7James Dong        CHECK(mMoovBoxBufferOffset + 8 <= mEstimatedMoovBoxSize);
3917837c17063a4c50bc856ba59418516fdab731de7James Dong
3927837c17063a4c50bc856ba59418516fdab731de7James Dong        // Moov box
3937837c17063a4c50bc856ba59418516fdab731de7James Dong        fseeko(mFile, mFreeBoxOffset, SEEK_SET);
3947837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset = mFreeBoxOffset;
3957837c17063a4c50bc856ba59418516fdab731de7James Dong        write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, mFile);
3967837c17063a4c50bc856ba59418516fdab731de7James Dong
3977837c17063a4c50bc856ba59418516fdab731de7James Dong        // Free box
3982dec2b5be2056c6d9428897dc672185872d30d17James Dong        fseeko(mFile, mOffset, SEEK_SET);
3997837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset);
4007837c17063a4c50bc856ba59418516fdab731de7James Dong        write("free", 4);
4017837c17063a4c50bc856ba59418516fdab731de7James Dong
4027837c17063a4c50bc856ba59418516fdab731de7James Dong        // Free temp memory
4037837c17063a4c50bc856ba59418516fdab731de7James Dong        free(mMoovBoxBuffer);
4047837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBuffer = NULL;
4057837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBufferOffset = 0;
4062dec2b5be2056c6d9428897dc672185872d30d17James Dong    } else {
4072dec2b5be2056c6d9428897dc672185872d30d17James Dong        LOGI("The mp4 file will not be streamable.");
4087837c17063a4c50bc856ba59418516fdab731de7James Dong    }
4097837c17063a4c50bc856ba59418516fdab731de7James Dong
4100c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(mBoxes.empty());
41120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4127837c17063a4c50bc856ba59418516fdab731de7James Dong    fflush(mFile);
41320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fclose(mFile);
41420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mFile = NULL;
415a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mStarted = false;
41620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
41720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
41813aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) {
41913aec890216948b0c364f8f92792129d0335f506James Dong    mInterleaveDurationUs = durationUs;
42013aec890216948b0c364f8f92792129d0335f506James Dong    return OK;
42113aec890216948b0c364f8f92792129d0335f506James Dong}
42213aec890216948b0c364f8f92792129d0335f506James Dong
42313aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() {
42413aec890216948b0c364f8f92792129d0335f506James Dong    mLock.lock();
42513aec890216948b0c364f8f92792129d0335f506James Dong}
42613aec890216948b0c364f8f92792129d0335f506James Dong
42713aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() {
42813aec890216948b0c364f8f92792129d0335f506James Dong    mLock.unlock();
42913aec890216948b0c364f8f92792129d0335f506James Dong}
43020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
43113aec890216948b0c364f8f92792129d0335f506James Dongoff_t MPEG4Writer::addSample_l(MediaBuffer *buffer) {
43220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    off_t old_offset = mOffset;
43320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
43420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fwrite((const uint8_t *)buffer->data() + buffer->range_offset(),
43520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber           1, buffer->range_length(), mFile);
43620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
43720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += buffer->range_length();
43820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
43920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return old_offset;
44020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
44120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
44203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) {
44303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (buffer->range_length() < 4) {
44403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return;
44503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
44603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
44703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    const uint8_t *ptr =
44803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        (const uint8_t *)buffer->data() + buffer->range_offset();
44903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
45003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) {
45103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        buffer->set_range(
45203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                buffer->range_offset() + 4, buffer->range_length() - 4);
45303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
45403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
45503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
45613aec890216948b0c364f8f92792129d0335f506James Dongoff_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) {
45730ab66297501757d745b9ae10da61adcd891f497Andreas Huber    off_t old_offset = mOffset;
45830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
45930ab66297501757d745b9ae10da61adcd891f497Andreas Huber    size_t length = buffer->range_length();
46003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
46103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR
46203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    uint8_t x = length >> 24;
46303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    fwrite(&x, 1, 1, mFile);
46403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    x = (length >> 16) & 0xff;
46503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    fwrite(&x, 1, 1, mFile);
46603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    x = (length >> 8) & 0xff;
46703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    fwrite(&x, 1, 1, mFile);
46803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    x = length & 0xff;
46903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    fwrite(&x, 1, 1, mFile);
47003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else
47130ab66297501757d745b9ae10da61adcd891f497Andreas Huber    CHECK(length < 65536);
47230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
47330ab66297501757d745b9ae10da61adcd891f497Andreas Huber    uint8_t x = length >> 8;
47430ab66297501757d745b9ae10da61adcd891f497Andreas Huber    fwrite(&x, 1, 1, mFile);
47530ab66297501757d745b9ae10da61adcd891f497Andreas Huber    x = length & 0xff;
47630ab66297501757d745b9ae10da61adcd891f497Andreas Huber    fwrite(&x, 1, 1, mFile);
47703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif
47830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
47930ab66297501757d745b9ae10da61adcd891f497Andreas Huber    fwrite((const uint8_t *)buffer->data() + buffer->range_offset(),
48030ab66297501757d745b9ae10da61adcd891f497Andreas Huber           1, length, mFile);
48130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
48203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR
48303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    mOffset += length + 4;
48403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else
48530ab66297501757d745b9ae10da61adcd891f497Andreas Huber    mOffset += length + 2;
48603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif
48730ab66297501757d745b9ae10da61adcd891f497Andreas Huber
48830ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return old_offset;
48930ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
49030ab66297501757d745b9ae10da61adcd891f497Andreas Huber
4917837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write(
4927837c17063a4c50bc856ba59418516fdab731de7James Dong        const void *ptr, size_t size, size_t nmemb, FILE *stream) {
4937837c17063a4c50bc856ba59418516fdab731de7James Dong
4947837c17063a4c50bc856ba59418516fdab731de7James Dong    const size_t bytes = size * nmemb;
4957837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
4961acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        off_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes;
4971acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        if (moovBoxSize > mEstimatedMoovBoxSize) {
4987837c17063a4c50bc856ba59418516fdab731de7James Dong            for (List<off_t>::iterator it = mBoxes.begin();
4997837c17063a4c50bc856ba59418516fdab731de7James Dong                 it != mBoxes.end(); ++it) {
5007837c17063a4c50bc856ba59418516fdab731de7James Dong                (*it) += mOffset;
5017837c17063a4c50bc856ba59418516fdab731de7James Dong            }
5027837c17063a4c50bc856ba59418516fdab731de7James Dong            fseeko(mFile, mOffset, SEEK_SET);
5037837c17063a4c50bc856ba59418516fdab731de7James Dong            fwrite(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, stream);
5047837c17063a4c50bc856ba59418516fdab731de7James Dong            fwrite(ptr, size, nmemb, stream);
5057837c17063a4c50bc856ba59418516fdab731de7James Dong            mOffset += (bytes + mMoovBoxBufferOffset);
5067837c17063a4c50bc856ba59418516fdab731de7James Dong            free(mMoovBoxBuffer);
5077837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBuffer = NULL;
5087837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset = 0;
5097837c17063a4c50bc856ba59418516fdab731de7James Dong            mWriteMoovBoxToMemory = false;
5107837c17063a4c50bc856ba59418516fdab731de7James Dong            mStreamableFile = false;
5117837c17063a4c50bc856ba59418516fdab731de7James Dong        } else {
5127837c17063a4c50bc856ba59418516fdab731de7James Dong            memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes);
5137837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset += bytes;
5147837c17063a4c50bc856ba59418516fdab731de7James Dong        }
5157837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
5167837c17063a4c50bc856ba59418516fdab731de7James Dong        fwrite(ptr, size, nmemb, stream);
5177837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset += bytes;
5187837c17063a4c50bc856ba59418516fdab731de7James Dong    }
5197837c17063a4c50bc856ba59418516fdab731de7James Dong    return bytes;
5207837c17063a4c50bc856ba59418516fdab731de7James Dong}
5217837c17063a4c50bc856ba59418516fdab731de7James Dong
52220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) {
5230c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(fourcc), 4);
52420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5257837c17063a4c50bc856ba59418516fdab731de7James Dong    mBoxes.push_back(mWriteMoovBoxToMemory?
5267837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset: mOffset);
52720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
52820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeInt32(0);
52920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeFourcc(fourcc);
53020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
53120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
53220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() {
5330c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(!mBoxes.empty());
53420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
53520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    off_t offset = *--mBoxes.end();
53620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mBoxes.erase(--mBoxes.end());
53720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5387837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
5397837c17063a4c50bc856ba59418516fdab731de7James Dong       int32_t x = htonl(mMoovBoxBufferOffset - offset);
5407837c17063a4c50bc856ba59418516fdab731de7James Dong       memcpy(mMoovBoxBuffer + offset, &x, 4);
5417837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
5427837c17063a4c50bc856ba59418516fdab731de7James Dong        fseeko(mFile, offset, SEEK_SET);
5437837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mOffset - offset);
5447837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset -= 4;
5457837c17063a4c50bc856ba59418516fdab731de7James Dong        fseeko(mFile, mOffset, SEEK_SET);
5467837c17063a4c50bc856ba59418516fdab731de7James Dong    }
54720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
54820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
54920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) {
5507837c17063a4c50bc856ba59418516fdab731de7James Dong    write(&x, 1, 1, mFile);
55120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
55220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
55320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) {
55420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htons(x);
5557837c17063a4c50bc856ba59418516fdab731de7James Dong    write(&x, 1, 2, mFile);
55620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
55720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
55820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) {
55920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htonl(x);
5607837c17063a4c50bc856ba59418516fdab731de7James Dong    write(&x, 1, 4, mFile);
56120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
56220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
56320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) {
56420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = hton64(x);
5657837c17063a4c50bc856ba59418516fdab731de7James Dong    write(&x, 1, 8, mFile);
56620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
56720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
56820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) {
56920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t n = strlen(s);
5707837c17063a4c50bc856ba59418516fdab731de7James Dong    write(s, 1, n + 1, mFile);
57120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
57220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
57320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) {
5740c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(s), 4);
5757837c17063a4c50bc856ba59418516fdab731de7James Dong    write(s, 1, 4, mFile);
57620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
57720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
57820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) {
5797837c17063a4c50bc856ba59418516fdab731de7James Dong    write(data, 1, size, mFile);
58020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
58120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
582d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() {
583d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
584d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileSizeLimitBytes == 0) {
585d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
586d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
587d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
588956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize);
589d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
590d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
591d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes();
592d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
593d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return (nTotalBytesEstimate >= mMaxFileSizeLimitBytes);
594d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
595d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
596d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() {
597d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
598d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileDurationLimitUs == 0) {
599d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
600d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
601d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
602d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
603d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
604d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) {
605d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            return true;
606d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
607d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
608d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return false;
609d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
610d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
61125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() {
61225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool allDone = true;
61325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
61425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber         it != mTracks.end(); ++it) {
61525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        if (!(*it)->reachedEOS()) {
61625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            allDone = false;
61725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            break;
61825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        }
61925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
62025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
62125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return allDone;
62225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
62325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
624f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) {
625f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    LOGI("setStartTimestampUs: %lld", timeUs);
626f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    CHECK(timeUs >= 0);
6273c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
628065d1aff96818df54456053f1574aec8a234d0deJames Dong    if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) {
629f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mStartTimestampUs = timeUs;
630f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        LOGI("Earliest track starting time: %lld", mStartTimestampUs);
6313c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    }
6323c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
6333c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
634f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() {
635f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    LOGI("getStartTimestampUs: %lld", mStartTimestampUs);
6363c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
6373c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    return mStartTimestampUs;
6383c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
6393c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
64058ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() {
64158ae9c530247668f8af36e30d228c716c226b3d4James Dong    Mutex::Autolock autolock(mLock);
64258ae9c530247668f8af36e30d228c716c226b3d4James Dong    return mTracks.size();
64358ae9c530247668f8af36e30d228c716c226b3d4James Dong}
64458ae9c530247668f8af36e30d228c716c226b3d4James Dong
64520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
64620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
64720111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track(
64825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        MPEG4Writer *owner, const sp<MediaSource> &source)
64920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mOwner(owner),
65025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mMeta(source->getFormat()),
65120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSource(source),
65220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDone(false),
653a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
654a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mResumed(false),
6553b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber      mMaxTimeStampUs(0),
656956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      mEstimatedTrackSizeBytes(0),
657be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong      mSamplesHaveSameSize(true),
65820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCodecSpecificData(NULL),
65925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mCodecSpecificDataSize(0),
660548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber      mGotAllCodecSpecificData(false),
66125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mReachedEOS(false) {
66220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
66320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
66420111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() {
66520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    stop();
66620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
66720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mCodecSpecificData != NULL) {
66820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        free(mCodecSpecificData);
66920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mCodecSpecificData = NULL;
67020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
67120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
67220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
673f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongstatus_t MPEG4Writer::Track::start(int64_t startTimeUs) {
674a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (!mDone && mPaused) {
675a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mPaused = false;
676a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mResumed = true;
677a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
678a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
67925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
680f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    sp<MetaData> meta = new MetaData;
681f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    meta->setInt64(kKeyTime, startTimeUs);
682f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    status_t err = mSource->start(meta.get());
68325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    if (err != OK) {
68425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        mDone = mReachedEOS = true;
68525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return err;
68625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
68720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
68820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_t attr;
68920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_init(&attr);
69020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
69120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
69220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = false;
6933b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber    mMaxTimeStampUs = 0;
69425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = false;
695956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    mEstimatedTrackSizeBytes = 0;
69620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
69725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    pthread_create(&mThread, &attr, ThreadWrapper, this);
69820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_destroy(&attr);
69925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
70025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
70120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
70220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
703a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dongvoid MPEG4Writer::Track::pause() {
704a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
705a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
706a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
70720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::Track::stop() {
70820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mDone) {
70920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return;
71020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
71120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
71220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = true;
71320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
71420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *dummy;
71520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_join(mThread, &dummy);
71620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
71720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mSource->stop();
71820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
71920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
72025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() {
72125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return mReachedEOS;
72225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
72325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
72420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static
72520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) {
72620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = static_cast<Track *>(me);
72720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
72820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    track->threadEntry();
72920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
73020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return NULL;
73120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
73220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
733548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber#include <ctype.h>
734548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huberstatic void hexdump(const void *_data, size_t size) {
735548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    const uint8_t *data = (const uint8_t *)_data;
736548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    size_t offset = 0;
737548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    while (offset < size) {
738548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        printf("0x%04x  ", offset);
739548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
740548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        size_t n = size - offset;
741548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        if (n > 16) {
742548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            n = 16;
743548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        }
744548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
745548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        for (size_t i = 0; i < 16; ++i) {
746548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            if (i == 8) {
747548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber                printf(" ");
748548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            }
749548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
750548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            if (offset + i < size) {
751548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber                printf("%02x ", data[offset + i]);
752548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            } else {
753548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber                printf("   ");
754548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            }
755548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        }
756548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
757548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        printf(" ");
758548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
759548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        for (size_t i = 0; i < n; ++i) {
760548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            if (isprint(data[offset + i])) {
761548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber                printf("%c", data[offset + i]);
762548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            } else {
763548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber                printf(".");
764548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            }
765548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        }
766548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
767548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        printf("\n");
768548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
769548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        offset += 16;
770548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    }
771548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber}
772548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
773548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
77403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData(
77503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        const uint8_t *data, size_t size) {
776548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    // hexdump(data, size);
777548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
77803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (mCodecSpecificData != NULL) {
779548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        LOGE("Already have codec specific data");
78003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
78103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
78203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
78303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (size < 4 || memcmp("\x00\x00\x00\x01", data, 4)) {
784548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        LOGE("Must start with a start code");
78503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
78603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
78703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
78803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    size_t picParamOffset = 4;
78903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    while (picParamOffset + 3 < size
79003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            && memcmp("\x00\x00\x00\x01", &data[picParamOffset], 4)) {
79103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        ++picParamOffset;
79203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
79303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
79403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (picParamOffset + 3 >= size) {
795548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        LOGE("Could not find start-code for pictureParameterSet");
79603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
79703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
79803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
79903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    size_t seqParamSetLength = picParamOffset - 4;
80003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    size_t picParamSetLength = size - picParamOffset - 4;
80103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
80203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    mCodecSpecificDataSize =
80303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        6 + 1 + seqParamSetLength + 2 + picParamSetLength + 2;
80403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
80503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    mCodecSpecificData = malloc(mCodecSpecificDataSize);
80603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    uint8_t *header = (uint8_t *)mCodecSpecificData;
80703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[0] = 1;
80803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[1] = 0x42;  // profile
80903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[2] = 0x80;
81003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[3] = 0x1e;  // level
81103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
81203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR
81303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[4] = 0xfc | 3;  // length size == 4 bytes
81403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else
81503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[4] = 0xfc | 1;  // length size == 2 bytes
81603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif
81703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
81803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[5] = 0xe0 | 1;
81903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[6] = seqParamSetLength >> 8;
82003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[7] = seqParamSetLength & 0xff;
82103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    memcpy(&header[8], &data[4], seqParamSetLength);
82203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header += 8 + seqParamSetLength;
82303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[0] = 1;
82403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[1] = picParamSetLength >> 8;
82503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[2] = picParamSetLength & 0xff;
82603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    memcpy(&header[3], &data[picParamOffset + 4], picParamSetLength);
82703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
82803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    return OK;
82903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
83003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
83120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::Track::threadEntry() {
83220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MetaData> meta = mSource->getFormat();
83320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const char *mime;
83420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    meta->findCString(kKeyMIMEType, &mime);
835050b28a593350047845a45a14cc5026221ac1620James Dong    bool is_mpeg4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
836050b28a593350047845a45a14cc5026221ac1620James Dong                    !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC);
83730ab66297501757d745b9ae10da61adcd891f497Andreas Huber    bool is_avc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
838956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    bool is_audio = !strncasecmp(mime, "audio/", 6);
83930ab66297501757d745b9ae10da61adcd891f497Andreas Huber    int32_t count = 0;
84013aec890216948b0c364f8f92792129d0335f506James Dong    const int64_t interleaveDurationUs = mOwner->interleaveDuration();
84113aec890216948b0c364f8f92792129d0335f506James Dong    int64_t chunkTimestampUs = 0;
84213aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nChunks = 0;
84313aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nZeroLengthFrames = 0;
844be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    int64_t lastTimestamp = 0;  // Timestamp of the previous sample
845be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    int64_t lastDuration = 0;   // Time spacing between the previous two samples
846be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    int32_t sampleCount = 1;    // Sample count in the current stts table entry
847be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    uint32_t previousSampleSize = 0;  // Size of the previous sample
848a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    int64_t previousPausedDurationUs = 0;
849d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong    sp<MetaData> meta_data;
85020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
85120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBuffer *buffer;
85220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (!mDone && mSource->read(&buffer) == OK) {
85320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (buffer->range_length() == 0) {
85420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer->release();
85520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer = NULL;
85613aec890216948b0c364f8f92792129d0335f506James Dong            ++nZeroLengthFrames;
85720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            continue;
85820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
85920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
860a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // If the codec specific data has not been received yet, delay pause.
861a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // After the codec specific data is received, discard what we received
862a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // when the track is to be paused.
863a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused && !mResumed) {
864a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer->release();
865a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer = NULL;
866a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            continue;
867a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
868a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
86930ab66297501757d745b9ae10da61adcd891f497Andreas Huber        ++count;
87030ab66297501757d745b9ae10da61adcd891f497Andreas Huber
87103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        int32_t isCodecConfig;
87203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig)
87303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                && isCodecConfig) {
874548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            CHECK(!mGotAllCodecSpecificData);
875548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
87603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            if (is_avc) {
87703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                status_t err = makeAVCCodecSpecificData(
87803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        (const uint8_t *)buffer->data()
87903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                            + buffer->range_offset(),
88003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        buffer->range_length());
881be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                CHECK_EQ(OK, err);
88203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            } else if (is_mpeg4) {
88303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificDataSize = buffer->range_length();
88403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificData = malloc(mCodecSpecificDataSize);
88503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                memcpy(mCodecSpecificData,
88603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        (const uint8_t *)buffer->data()
88703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                            + buffer->range_offset(),
88803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                       buffer->range_length());
88930ab66297501757d745b9ae10da61adcd891f497Andreas Huber            }
89030ab66297501757d745b9ae10da61adcd891f497Andreas Huber
89130ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer->release();
89230ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer = NULL;
89330ab66297501757d745b9ae10da61adcd891f497Andreas Huber
894548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            mGotAllCodecSpecificData = true;
89530ab66297501757d745b9ae10da61adcd891f497Andreas Huber            continue;
896548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        } else if (!mGotAllCodecSpecificData &&
897548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber                count == 1 && is_mpeg4 && mCodecSpecificData == NULL) {
89803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            // The TI mpeg4 encoder does not properly set the
89903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            // codec-specific-data flag.
90030ab66297501757d745b9ae10da61adcd891f497Andreas Huber
90120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            const uint8_t *data =
90220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                (const uint8_t *)buffer->data() + buffer->range_offset();
90320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
90420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            const size_t size = buffer->range_length();
90520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
90620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            size_t offset = 0;
90720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (offset + 3 < size) {
90820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (data[offset] == 0x00 && data[offset + 1] == 0x00
90920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    && data[offset + 2] == 0x01 && data[offset + 3] == 0xb6) {
91020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    break;
91120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
91220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
91320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                ++offset;
91420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
91520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9160c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber            // CHECK(offset + 3 < size);
917bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber            if (offset + 3 >= size) {
918bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber                // XXX assume the entire first chunk of data is the codec specific
919bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber                // data.
920bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber                offset = size;
921bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber            }
92220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
92320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mCodecSpecificDataSize = offset;
92420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mCodecSpecificData = malloc(offset);
92520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            memcpy(mCodecSpecificData, data, offset);
92620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
92720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer->set_range(buffer->range_offset() + offset, size - offset);
92803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
92903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            if (size == offset) {
93003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                buffer->release();
93103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                buffer = NULL;
93203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
93303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                continue;
93403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            }
935548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
936548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            mGotAllCodecSpecificData = true;
937548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        } else if (!mGotAllCodecSpecificData && is_avc && count < 3) {
93803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            // The TI video encoder does not flag codec specific data
93903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            // as such and also splits up SPS and PPS across two buffers.
94003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
94103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            const uint8_t *data =
94203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                (const uint8_t *)buffer->data() + buffer->range_offset();
94303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
94403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            size_t size = buffer->range_length();
94503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
94603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            CHECK(count == 2 || mCodecSpecificData == NULL);
94703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
94803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            size_t offset = mCodecSpecificDataSize;
94903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            mCodecSpecificDataSize += size + 4;
95003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            mCodecSpecificData =
95103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                realloc(mCodecSpecificData, mCodecSpecificDataSize);
95203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
95303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            memcpy((uint8_t *)mCodecSpecificData + offset,
95403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                   "\x00\x00\x00\x01", 4);
95503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
95603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            memcpy((uint8_t *)mCodecSpecificData + offset + 4, data, size);
95703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
95803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            buffer->release();
95903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            buffer = NULL;
96003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
96103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            if (count == 2) {
96203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                void *tmp = mCodecSpecificData;
96303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                size = mCodecSpecificDataSize;
96403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificData = NULL;
96503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificDataSize = 0;
96603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
96703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                status_t err = makeAVCCodecSpecificData(
96803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        (const uint8_t *)tmp, size);
96903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                free(tmp);
97003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                tmp = NULL;
971be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                CHECK_EQ(OK, err);
972548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
973548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber                mGotAllCodecSpecificData = true;
97403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            }
97503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
97603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            continue;
97720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
97820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
979a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (!mGotAllCodecSpecificData) {
980a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mGotAllCodecSpecificData = true;
981a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
982a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
983d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // Make a deep copy of the MediaBuffer and Metadata and release
984d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // the original as soon as we can
985d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        MediaBuffer *copy = new MediaBuffer(buffer->range_length());
986d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(),
987d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong                buffer->range_length());
988d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        copy->set_range(0, buffer->range_length());
989d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data = new MetaData(*buffer->meta_data().get());
990d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer->release();
991d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer = NULL;
992d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
993d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        if (is_avc) StripStartcode(copy);
994e136c3bb38e88315bf8797a464ebf2c788296b22James Dong
99520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        SampleInfo info;
99603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        info.size = is_avc
99703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR
998d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong                ? copy->range_length() + 4
99903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else
1000d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong                ? copy->range_length() + 2
100103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif
1002d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong                : copy->range_length();
1003050b28a593350047845a45a14cc5026221ac1620James Dong
1004d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        // Max file size or duration handling
1005d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        mEstimatedTrackSizeBytes += info.size;
1006d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileSizeLimit()) {
1007d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
1008d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
1009d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
1010d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileDurationLimit()) {
1011d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
1012d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
1013d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
1014d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1015050b28a593350047845a45a14cc5026221ac1620James Dong
1016d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        int32_t isSync = false;
1017d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data->findInt32(kKeyIsSyncFrame, &isSync);
1018d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
101948c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        int64_t timestampUs;
1020d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        CHECK(meta_data->findInt64(kKeyTime, &timestampUs));
1021d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
1022d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong////////////////////////////////////////////////////////////////////////////////
10233c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        if (mSampleInfos.empty()) {
1024f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mStartTimestampUs = timestampUs;
1025f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mOwner->setStartTimestampUs(mStartTimestampUs);
10263c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        }
102748c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber
1028a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mResumed) {
1029a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            previousPausedDurationUs += (timestampUs - mMaxTimeStampUs - 1000 * lastDuration);
1030a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mResumed = false;
1031a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
1032a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
1033a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        timestampUs -= previousPausedDurationUs;
1034a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        LOGV("time stamp: %lld and previous paused duration %lld",
1035a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                timestampUs, previousPausedDurationUs);
10363b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber        if (timestampUs > mMaxTimeStampUs) {
10373b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber            mMaxTimeStampUs = timestampUs;
10383b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber        }
10393b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber
104048c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        // Our timestamp is in ms.
104148c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        info.timestamp = (timestampUs + 500) / 1000;
104220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mSampleInfos.push_back(info);
1043be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        if (mSampleInfos.size() > 2) {
1044be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            if (lastDuration != info.timestamp - lastTimestamp) {
1045be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                SttsTableEntry sttsEntry(sampleCount, lastDuration);
1046be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mSttsTableEntries.push_back(sttsEntry);
1047be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                sampleCount = 1;
1048be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            } else {
1049be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                ++sampleCount;
1050be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
1051be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
1052be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        if (mSamplesHaveSameSize) {
1053be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            if (mSampleInfos.size() >= 2 && previousSampleSize != info.size) {
1054be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mSamplesHaveSameSize = false;
1055be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
1056be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            previousSampleSize = info.size;
1057be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
1058be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        lastDuration = info.timestamp - lastTimestamp;
1059be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        lastTimestamp = info.timestamp;
106020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1061d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        if (isSync != 0) {
1062d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong            mStssTableEntries.push_back(mSampleInfos.size());
1063d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        }
1064d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
106558ae9c530247668f8af36e30d228c716c226b3d4James Dong        if (mOwner->numTracks() == 1) {
106658ae9c530247668f8af36e30d228c716c226b3d4James Dong            off_t offset = is_avc? mOwner->addLengthPrefixedSample_l(copy)
106758ae9c530247668f8af36e30d228c716c226b3d4James Dong                                 : mOwner->addSample_l(copy);
106858ae9c530247668f8af36e30d228c716c226b3d4James Dong            if (mChunkOffsets.empty()) {
106958ae9c530247668f8af36e30d228c716c226b3d4James Dong                mChunkOffsets.push_back(offset);
107058ae9c530247668f8af36e30d228c716c226b3d4James Dong            }
107158ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy->release();
107258ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy = NULL;
107358ae9c530247668f8af36e30d228c716c226b3d4James Dong            continue;
107458ae9c530247668f8af36e30d228c716c226b3d4James Dong        }
107513aec890216948b0c364f8f92792129d0335f506James Dong
107613aec890216948b0c364f8f92792129d0335f506James Dong        mChunkSamples.push_back(copy);
107713aec890216948b0c364f8f92792129d0335f506James Dong        if (interleaveDurationUs == 0) {
107813aec890216948b0c364f8f92792129d0335f506James Dong            StscTableEntry stscEntry(++nChunks, 1, 1);
107913aec890216948b0c364f8f92792129d0335f506James Dong            mStscTableEntries.push_back(stscEntry);
108013aec890216948b0c364f8f92792129d0335f506James Dong            writeOneChunk(is_avc);
108113aec890216948b0c364f8f92792129d0335f506James Dong        } else {
108213aec890216948b0c364f8f92792129d0335f506James Dong            if (chunkTimestampUs == 0) {
108313aec890216948b0c364f8f92792129d0335f506James Dong                chunkTimestampUs = timestampUs;
108413aec890216948b0c364f8f92792129d0335f506James Dong            } else {
108513aec890216948b0c364f8f92792129d0335f506James Dong                if (timestampUs - chunkTimestampUs > interleaveDurationUs) {
108613aec890216948b0c364f8f92792129d0335f506James Dong                    ++nChunks;
1087365a963142093a1cd8efdcea76b5f65096a5b115James Dong                    mChunkDurations.push_back(timestampUs - chunkTimestampUs);
108813aec890216948b0c364f8f92792129d0335f506James Dong                    if (nChunks == 1 ||  // First chunk
108913aec890216948b0c364f8f92792129d0335f506James Dong                        (--(mStscTableEntries.end()))->samplesPerChunk !=
109013aec890216948b0c364f8f92792129d0335f506James Dong                         mChunkSamples.size()) {
109113aec890216948b0c364f8f92792129d0335f506James Dong                        StscTableEntry stscEntry(nChunks,
109213aec890216948b0c364f8f92792129d0335f506James Dong                                mChunkSamples.size(), 1);
109313aec890216948b0c364f8f92792129d0335f506James Dong                        mStscTableEntries.push_back(stscEntry);
109413aec890216948b0c364f8f92792129d0335f506James Dong                    }
109513aec890216948b0c364f8f92792129d0335f506James Dong                    writeOneChunk(is_avc);
109613aec890216948b0c364f8f92792129d0335f506James Dong                    chunkTimestampUs = timestampUs;
109713aec890216948b0c364f8f92792129d0335f506James Dong                }
109813aec890216948b0c364f8f92792129d0335f506James Dong            }
109913aec890216948b0c364f8f92792129d0335f506James Dong        }
110013aec890216948b0c364f8f92792129d0335f506James Dong
110120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
110225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
1103f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong    if (mSampleInfos.empty()) {
1104f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong        mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_STOP_PREMATURELY, 0);
1105f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong    }
1106be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
110713aec890216948b0c364f8f92792129d0335f506James Dong    // Last chunk
110858ae9c530247668f8af36e30d228c716c226b3d4James Dong    if (mOwner->numTracks() == 1) {
110958ae9c530247668f8af36e30d228c716c226b3d4James Dong        StscTableEntry stscEntry(1, mSampleInfos.size(), 1);
111058ae9c530247668f8af36e30d228c716c226b3d4James Dong        mStscTableEntries.push_back(stscEntry);
111158ae9c530247668f8af36e30d228c716c226b3d4James Dong    } else if (!mChunkSamples.empty()) {
111213aec890216948b0c364f8f92792129d0335f506James Dong        ++nChunks;
111313aec890216948b0c364f8f92792129d0335f506James Dong        StscTableEntry stscEntry(nChunks, mChunkSamples.size(), 1);
111413aec890216948b0c364f8f92792129d0335f506James Dong        mStscTableEntries.push_back(stscEntry);
111513aec890216948b0c364f8f92792129d0335f506James Dong        writeOneChunk(is_avc);
111613aec890216948b0c364f8f92792129d0335f506James Dong    }
111713aec890216948b0c364f8f92792129d0335f506James Dong
1118be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // We don't really know how long the last frame lasts, since
1119be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // there is no frame time after it, just repeat the previous
1120be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // frame's duration.
1121be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    if (mSampleInfos.size() == 1) {
1122be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        lastDuration = 0;  // A single sample's duration
1123be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    } else {
1124be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        ++sampleCount;  // Count for the last sample
1125be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    }
1126be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    SttsTableEntry sttsEntry(sampleCount, lastDuration);
1127be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    mSttsTableEntries.push_back(sttsEntry);
112825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = true;
1129956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    LOGI("Received total/0-length (%d/%d) buffers and encoded %d frames - %s",
1130956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            count, nZeroLengthFrames, mSampleInfos.size(), is_audio? "audio": "video");
1131365a963142093a1cd8efdcea76b5f65096a5b115James Dong
1132365a963142093a1cd8efdcea76b5f65096a5b115James Dong    logStatisticalData(is_audio);
1133365a963142093a1cd8efdcea76b5f65096a5b115James Dong}
1134365a963142093a1cd8efdcea76b5f65096a5b115James Dong
1135365a963142093a1cd8efdcea76b5f65096a5b115James Dongvoid MPEG4Writer::Track::findMinMaxFrameRates(float *minFps, float *maxFps) {
1136365a963142093a1cd8efdcea76b5f65096a5b115James Dong    int32_t minSampleDuration = 0x7FFFFFFF;
1137365a963142093a1cd8efdcea76b5f65096a5b115James Dong    int32_t maxSampleDuration = 0;
1138365a963142093a1cd8efdcea76b5f65096a5b115James Dong    for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin();
1139365a963142093a1cd8efdcea76b5f65096a5b115James Dong        it != mSttsTableEntries.end(); ++it) {
1140365a963142093a1cd8efdcea76b5f65096a5b115James Dong        int32_t sampleDuration = static_cast<int32_t>(it->sampleDuration);
1141365a963142093a1cd8efdcea76b5f65096a5b115James Dong        if (sampleDuration > maxSampleDuration) {
1142365a963142093a1cd8efdcea76b5f65096a5b115James Dong            maxSampleDuration = sampleDuration;
1143365a963142093a1cd8efdcea76b5f65096a5b115James Dong        } else if (sampleDuration < minSampleDuration) {
1144365a963142093a1cd8efdcea76b5f65096a5b115James Dong            minSampleDuration = sampleDuration;
1145365a963142093a1cd8efdcea76b5f65096a5b115James Dong        }
1146365a963142093a1cd8efdcea76b5f65096a5b115James Dong    }
1147365a963142093a1cd8efdcea76b5f65096a5b115James Dong    CHECK(minSampleDuration != 0 && maxSampleDuration != 0);
1148365a963142093a1cd8efdcea76b5f65096a5b115James Dong    *minFps = 1000.0 / maxSampleDuration;
1149365a963142093a1cd8efdcea76b5f65096a5b115James Dong    *maxFps = 1000.0 / minSampleDuration;
1150365a963142093a1cd8efdcea76b5f65096a5b115James Dong}
1151365a963142093a1cd8efdcea76b5f65096a5b115James Dong
1152365a963142093a1cd8efdcea76b5f65096a5b115James Dong// Don't count the last duration
1153365a963142093a1cd8efdcea76b5f65096a5b115James Dongvoid MPEG4Writer::Track::findMinMaxChunkDurations(int64_t *min, int64_t *max) {
1154365a963142093a1cd8efdcea76b5f65096a5b115James Dong    int64_t duration = mOwner->interleaveDuration();
1155365a963142093a1cd8efdcea76b5f65096a5b115James Dong    int64_t minChunkDuration = duration;
1156365a963142093a1cd8efdcea76b5f65096a5b115James Dong    int64_t maxChunkDuration = duration;
1157365a963142093a1cd8efdcea76b5f65096a5b115James Dong    if (mChunkDurations.size() > 1) {
1158365a963142093a1cd8efdcea76b5f65096a5b115James Dong        for (List<int64_t>::iterator it = mChunkDurations.begin();
1159365a963142093a1cd8efdcea76b5f65096a5b115James Dong            it != --mChunkDurations.end(); ++it) {
1160365a963142093a1cd8efdcea76b5f65096a5b115James Dong            if (minChunkDuration > (*it)) {
1161365a963142093a1cd8efdcea76b5f65096a5b115James Dong                minChunkDuration = (*it);
1162365a963142093a1cd8efdcea76b5f65096a5b115James Dong            } else if (maxChunkDuration < (*it)) {
1163365a963142093a1cd8efdcea76b5f65096a5b115James Dong                maxChunkDuration = (*it);
1164365a963142093a1cd8efdcea76b5f65096a5b115James Dong            }
1165365a963142093a1cd8efdcea76b5f65096a5b115James Dong        }
1166365a963142093a1cd8efdcea76b5f65096a5b115James Dong    }
1167365a963142093a1cd8efdcea76b5f65096a5b115James Dong    *min = minChunkDuration;
1168365a963142093a1cd8efdcea76b5f65096a5b115James Dong    *max = maxChunkDuration;
1169365a963142093a1cd8efdcea76b5f65096a5b115James Dong}
1170365a963142093a1cd8efdcea76b5f65096a5b115James Dong
1171365a963142093a1cd8efdcea76b5f65096a5b115James Dongvoid MPEG4Writer::Track::logStatisticalData(bool isAudio) {
1172365a963142093a1cd8efdcea76b5f65096a5b115James Dong    if (mMaxTimeStampUs <= 0 || mSampleInfos.empty()) {
1173365a963142093a1cd8efdcea76b5f65096a5b115James Dong        LOGI("nothing is recorded");
1174365a963142093a1cd8efdcea76b5f65096a5b115James Dong        return;
1175365a963142093a1cd8efdcea76b5f65096a5b115James Dong    }
1176365a963142093a1cd8efdcea76b5f65096a5b115James Dong
1177365a963142093a1cd8efdcea76b5f65096a5b115James Dong    bool collectStats = false;
1178365a963142093a1cd8efdcea76b5f65096a5b115James Dong    char value[PROPERTY_VALUE_MAX];
1179365a963142093a1cd8efdcea76b5f65096a5b115James Dong    if (property_get("media.stagefright.record-stats", value, NULL)
1180365a963142093a1cd8efdcea76b5f65096a5b115James Dong        && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
1181365a963142093a1cd8efdcea76b5f65096a5b115James Dong        collectStats = true;
1182365a963142093a1cd8efdcea76b5f65096a5b115James Dong    }
1183365a963142093a1cd8efdcea76b5f65096a5b115James Dong
1184365a963142093a1cd8efdcea76b5f65096a5b115James Dong    if (collectStats) {
1185365a963142093a1cd8efdcea76b5f65096a5b115James Dong        if (isAudio) {
1186365a963142093a1cd8efdcea76b5f65096a5b115James Dong            LOGI("audio track - duration %lld us", mMaxTimeStampUs);
1187365a963142093a1cd8efdcea76b5f65096a5b115James Dong        } else {
1188365a963142093a1cd8efdcea76b5f65096a5b115James Dong            float fps = (mSampleInfos.size() * 1000000.0) / mMaxTimeStampUs;
1189365a963142093a1cd8efdcea76b5f65096a5b115James Dong            float minFps;
1190365a963142093a1cd8efdcea76b5f65096a5b115James Dong            float maxFps;
1191365a963142093a1cd8efdcea76b5f65096a5b115James Dong            findMinMaxFrameRates(&minFps, &maxFps);
1192365a963142093a1cd8efdcea76b5f65096a5b115James Dong            LOGI("video track - duration %lld us", mMaxTimeStampUs);
1193365a963142093a1cd8efdcea76b5f65096a5b115James Dong            LOGI("min/avg/max frame rate (fps): %.2f/%.2f/%.2f",
1194365a963142093a1cd8efdcea76b5f65096a5b115James Dong                minFps, fps, maxFps);
1195365a963142093a1cd8efdcea76b5f65096a5b115James Dong        }
1196365a963142093a1cd8efdcea76b5f65096a5b115James Dong
1197365a963142093a1cd8efdcea76b5f65096a5b115James Dong        int64_t totalBytes = 0;
1198365a963142093a1cd8efdcea76b5f65096a5b115James Dong        for (List<SampleInfo>::iterator it = mSampleInfos.begin();
1199365a963142093a1cd8efdcea76b5f65096a5b115James Dong            it != mSampleInfos.end(); ++it) {
1200365a963142093a1cd8efdcea76b5f65096a5b115James Dong            totalBytes += it->size;
1201365a963142093a1cd8efdcea76b5f65096a5b115James Dong        }
1202365a963142093a1cd8efdcea76b5f65096a5b115James Dong        float bitRate = (totalBytes * 8000000.0) / mMaxTimeStampUs;
1203365a963142093a1cd8efdcea76b5f65096a5b115James Dong        LOGI("avg bit rate (bps): %.2f", bitRate);
1204365a963142093a1cd8efdcea76b5f65096a5b115James Dong
1205365a963142093a1cd8efdcea76b5f65096a5b115James Dong        int64_t duration = mOwner->interleaveDuration();
1206365a963142093a1cd8efdcea76b5f65096a5b115James Dong        if (duration != 0) {  // If interleaving is enabled
1207365a963142093a1cd8efdcea76b5f65096a5b115James Dong            int64_t minChunk, maxChunk;
1208365a963142093a1cd8efdcea76b5f65096a5b115James Dong            findMinMaxChunkDurations(&minChunk, &maxChunk);
1209365a963142093a1cd8efdcea76b5f65096a5b115James Dong            LOGI("min/avg/max chunk duration (ms): %lld/%lld/%lld",
1210365a963142093a1cd8efdcea76b5f65096a5b115James Dong                minChunk, duration, maxChunk);
1211365a963142093a1cd8efdcea76b5f65096a5b115James Dong        }
1212365a963142093a1cd8efdcea76b5f65096a5b115James Dong    }
121313aec890216948b0c364f8f92792129d0335f506James Dong}
121413aec890216948b0c364f8f92792129d0335f506James Dong
121513aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::Track::writeOneChunk(bool isAvc) {
121613aec890216948b0c364f8f92792129d0335f506James Dong    mOwner->lock();
121713aec890216948b0c364f8f92792129d0335f506James Dong    for (List<MediaBuffer *>::iterator it = mChunkSamples.begin();
121813aec890216948b0c364f8f92792129d0335f506James Dong         it != mChunkSamples.end(); ++it) {
121913aec890216948b0c364f8f92792129d0335f506James Dong        off_t offset = isAvc? mOwner->addLengthPrefixedSample_l(*it)
122013aec890216948b0c364f8f92792129d0335f506James Dong                            : mOwner->addSample_l(*it);
122113aec890216948b0c364f8f92792129d0335f506James Dong        if (it == mChunkSamples.begin()) {
122213aec890216948b0c364f8f92792129d0335f506James Dong            mChunkOffsets.push_back(offset);
122313aec890216948b0c364f8f92792129d0335f506James Dong        }
122413aec890216948b0c364f8f92792129d0335f506James Dong    }
122513aec890216948b0c364f8f92792129d0335f506James Dong    mOwner->unlock();
122613aec890216948b0c364f8f92792129d0335f506James Dong    while (!mChunkSamples.empty()) {
122713aec890216948b0c364f8f92792129d0335f506James Dong        List<MediaBuffer *>::iterator it = mChunkSamples.begin();
122813aec890216948b0c364f8f92792129d0335f506James Dong        (*it)->release();
122913aec890216948b0c364f8f92792129d0335f506James Dong        (*it) = NULL;
123013aec890216948b0c364f8f92792129d0335f506James Dong        mChunkSamples.erase(it);
123113aec890216948b0c364f8f92792129d0335f506James Dong    }
123213aec890216948b0c364f8f92792129d0335f506James Dong    mChunkSamples.clear();
123320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
123420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12353b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const {
12363b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber    return mMaxTimeStampUs;
123720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
123820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1239d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const {
1240d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return mEstimatedTrackSizeBytes;
1241d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
1242d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
12431acfe8649f8169caf2ff098c2dc2de880d9a3760James Dongvoid MPEG4Writer::Track::writeTrackHeader(
12441acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        int32_t trackID, bool use32BitOffset) {
124520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const char *mime;
124620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool success = mMeta->findCString(kKeyMIMEType, &mime);
12470c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(success);
124820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
124920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool is_audio = !strncasecmp(mime, "audio/", 6);
12501acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    int32_t timeScale = 1000;
12511acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    int32_t duration = getDurationUs() / timeScale;
125220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
125320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    time_t now = time(NULL);
125420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
125520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOwner->beginBox("trak");
125620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
125720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->beginBox("tkhd");
12581acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        // Flags = 7 to indicate that the track is enabled, and
12591acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        // part of the presentation
12601acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        mOwner->writeInt32(0x07);          // version=0, flags=7
126120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(now);           // creation time
126220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(now);           // modification time
126320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(trackID);
126420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);             // reserved
12651acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        mOwner->writeInt32(duration);
126620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);             // reserved
126720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);             // reserved
126820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt16(0);             // layer
126920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt16(0);             // alternate group
127020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt16(is_audio ? 0x100 : 0);  // volume
127120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt16(0);             // reserved
127220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
127320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0x10000);       // matrix
127420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
127520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
127620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
127720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0x10000);
127820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
127920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
128020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
128120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0x40000000);
128220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
128320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (is_audio) {
128420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);
128520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);
128620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        } else {
128720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            int32_t width, height;
128820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            bool success = mMeta->findInt32(kKeyWidth, &width);
128920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            success = success && mMeta->findInt32(kKeyHeight, &height);
12900c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber            CHECK(success);
129120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1292050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->writeInt32(width << 16);   // 32-bit fixed-point value
1293050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->writeInt32(height << 16);  // 32-bit fixed-point value
129420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
129520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->endBox();  // tkhd
129620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1297f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong      int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
1298f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong      if (mStartTimestampUs != moovStartTimeUs) {
12993c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        mOwner->beginBox("edts");
13003c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong          mOwner->beginBox("elst");
13011acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong            mOwner->writeInt32(0);           // version=0, flags=0: 32-bit time
13021acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong            mOwner->writeInt32(2);           // never ends with an empty list
1303f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            int64_t durationMs =
1304f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong                (mStartTimestampUs - moovStartTimeUs) / 1000;
1305f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mOwner->writeInt32(durationMs);  // edit duration
1306956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            mOwner->writeInt32(-1);          // empty edit box to signal starting time offset
13071acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong            mOwner->writeInt32(1 << 16);     // x1 rate
13081acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong            mOwner->writeInt32(duration);
13091acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong            mOwner->writeInt32(0);
13101acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong            mOwner->writeInt32(1 << 16);
13113c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong          mOwner->endBox();
13123c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        mOwner->endBox();
13133c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong      }
13143c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
131520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->beginBox("mdia");
131620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
131720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("mdhd");
131820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // version=0, flags=0
131920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(now);           // creation time
132020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(now);           // modification time
13211acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          mOwner->writeInt32(timeScale);     // timescale
13221acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          mOwner->writeInt32(duration);      // duration
13231acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // Language follows the three letter standard ISO-639-2/T
13241acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // 'e', 'n', 'g' for "English", for instance.
13251acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // Each character is packed as the difference between its ASCII value and 0x60.
13261acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // For "English", these are 00101, 01110, 00111.
13271acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // XXX: Where is the padding bit located: 0x15C7?
13281acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          mOwner->writeInt16(0);             // language code
132920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt16(0);             // predefined
133020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->endBox();
133120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
133220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("hdlr");
133320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // version=0, flags=0
1334050b28a593350047845a45a14cc5026221ac1620James Dong          mOwner->writeInt32(0);             // component type: should be mhlr
1335050b28a593350047845a45a14cc5026221ac1620James Dong          mOwner->writeFourcc(is_audio ? "soun" : "vide");  // component subtype
133620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // reserved
133720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // reserved
133820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // reserved
13391acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // Removing "r" for the name string just makes the string 4 byte aligned
13401acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          mOwner->writeCString(is_audio ? "SoundHandle": "VideoHandle");  // name
134120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->endBox();
134220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
134320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("minf");
134420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          if (is_audio) {
134520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->beginBox("smhd");
134620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt32(0);           // version=0, flags=0
134720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // balance
134820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // reserved
134920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->endBox();
135020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          } else {
135120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->beginBox("vmhd");
13521acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong              mOwner->writeInt32(0x01);        // version=0, flags=1
135320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // graphics mode
135420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // opcolor
135520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);
135620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);
135720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->endBox();
135820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          }
1359050b28a593350047845a45a14cc5026221ac1620James Dong
1360050b28a593350047845a45a14cc5026221ac1620James Dong          mOwner->beginBox("dinf");
1361050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->beginBox("dref");
1362050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->writeInt32(0);  // version=0, flags=0
13631acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong              mOwner->writeInt32(1);  // entry count (either url or urn)
13641acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong              // The table index here refers to the sample description index
13651acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong              // in the sample table entries.
1366050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->beginBox("url ");
13671acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                mOwner->writeInt32(1);  // version=0, flags=1 (self-contained)
1368050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->endBox();  // url
1369050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->endBox();  // dref
1370050b28a593350047845a45a14cc5026221ac1620James Dong          mOwner->endBox();  // dinf
1371050b28a593350047845a45a14cc5026221ac1620James Dong
137220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("stbl");
137320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
137420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stsd");
137520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);               // version=0, flags=0
137620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(1);               // entry count
137720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (is_audio) {
137825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                const char *fourcc = NULL;
137918291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) {
138025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    fourcc = "samr";
138118291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
138225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    fourcc = "sawb";
1383050b28a593350047845a45a14cc5026221ac1620James Dong                } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
1384050b28a593350047845a45a14cc5026221ac1620James Dong                    fourcc = "mp4a";
138525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                } else {
138625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    LOGE("Unknown mime type '%s'.", mime);
138725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    CHECK(!"should not be here, unknown mime type.");
138825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                }
138925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
139025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                mOwner->beginBox(fourcc);          // audio format
139120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
139220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
1393050b28a593350047845a45a14cc5026221ac1620James Dong                  mOwner->writeInt16(0x1);         // data ref index
139420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
139520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
1396050b28a593350047845a45a14cc5026221ac1620James Dong                  int32_t nChannels;
1397050b28a593350047845a45a14cc5026221ac1620James Dong                  CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels));
1398050b28a593350047845a45a14cc5026221ac1620James Dong                  mOwner->writeInt16(nChannels);   // channel count
139920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(16);          // sample size
140020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // predefined
140120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
140220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
140320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  int32_t samplerate;
140420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  bool success = mMeta->findInt32(kKeySampleRate, &samplerate);
14050c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                  CHECK(success);
140620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
140720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(samplerate << 16);
1408050b28a593350047845a45a14cc5026221ac1620James Dong                  if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
1409050b28a593350047845a45a14cc5026221ac1620James Dong                    mOwner->beginBox("esds");
1410050b28a593350047845a45a14cc5026221ac1620James Dong
1411050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt32(0);     // version=0, flags=0
1412050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x03);   // ES_DescrTag
1413050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(23 + mCodecSpecificDataSize);
1414050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt16(0x0000);// ES_ID
1415050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x00);
1416050b28a593350047845a45a14cc5026221ac1620James Dong
1417050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x04);   // DecoderConfigDescrTag
1418050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(15 + mCodecSpecificDataSize);
1419050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x40);   // objectTypeIndication ISO/IEC 14492-2
1420050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x15);   // streamType AudioStream
1421050b28a593350047845a45a14cc5026221ac1620James Dong
1422050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt16(0x03);  // XXX
1423050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x00);   // buffer size 24-bit
1424050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt32(96000); // max bit rate
1425050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt32(96000); // avg bit rate
1426050b28a593350047845a45a14cc5026221ac1620James Dong
1427050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x05);   // DecoderSpecificInfoTag
1428050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(mCodecSpecificDataSize);
1429050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
1430050b28a593350047845a45a14cc5026221ac1620James Dong
1431050b28a593350047845a45a14cc5026221ac1620James Dong                        static const uint8_t kData2[] = {
1432050b28a593350047845a45a14cc5026221ac1620James Dong                            0x06,  // SLConfigDescriptorTag
1433050b28a593350047845a45a14cc5026221ac1620James Dong                            0x01,
1434050b28a593350047845a45a14cc5026221ac1620James Dong                            0x02
1435050b28a593350047845a45a14cc5026221ac1620James Dong                        };
1436050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->write(kData2, sizeof(kData2));
1437050b28a593350047845a45a14cc5026221ac1620James Dong
1438050b28a593350047845a45a14cc5026221ac1620James Dong                    mOwner->endBox();  // esds
1439050b28a593350047845a45a14cc5026221ac1620James Dong                  }
144020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mOwner->endBox();
144120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
144218291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
144320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    mOwner->beginBox("mp4v");
144418291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
144520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    mOwner->beginBox("s263");
144630ab66297501757d745b9ae10da61adcd891f497Andreas Huber                } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
144730ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    mOwner->beginBox("avc1");
144820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                } else {
144925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    LOGE("Unknown mime type '%s'.", mime);
14500c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                    CHECK(!"should not be here, unknown mime type.");
145120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
145220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
145320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
145420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
14551acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                  mOwner->writeInt16(1);           // data ref index
145620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // predefined
145720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
145820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // predefined
145920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // predefined
146020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // predefined
146120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
146220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  int32_t width, height;
146320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  bool success = mMeta->findInt32(kKeyWidth, &width);
146420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  success = success && mMeta->findInt32(kKeyHeight, &height);
14650c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                  CHECK(success);
146620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
146720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(width);
146820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(height);
146920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0x480000);    // horiz resolution
147020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0x480000);    // vert resolution
147120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
147220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(1);           // frame count
147320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->write("                                ", 32);
147420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0x18);        // depth
147520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(-1);          // predefined
147620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14770c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                  CHECK(23 + mCodecSpecificDataSize < 128);
147820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
147918291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                  if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
148020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->beginBox("esds");
148120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
148220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt32(0);           // version=0, flags=0
148320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
148420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x03);  // ES_DescrTag
148520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(23 + mCodecSpecificDataSize);
148620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt16(0x0000);  // ES_ID
148720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x1f);
148820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
148920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x04);  // DecoderConfigDescrTag
149020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(15 + mCodecSpecificDataSize);
149120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x20);  // objectTypeIndication ISO/IEC 14492-2
149220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x11);  // streamType VisualStream
149320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
149420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        static const uint8_t kData[] = {
149520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x01, 0x77, 0x00,
149620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x00, 0x03, 0xe8, 0x00,
149720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x00, 0x03, 0xe8, 0x00
149820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        };
149920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->write(kData, sizeof(kData));
1500050b28a593350047845a45a14cc5026221ac1620James Dong
150120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x05);  // DecoderSpecificInfoTag
150220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
150320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(mCodecSpecificDataSize);
150420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
150520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
150620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        static const uint8_t kData2[] = {
150720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x06,  // SLConfigDescriptorTag
150820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x01,
150920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x02
151020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        };
151120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->write(kData2, sizeof(kData2));
151220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
151320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->endBox();  // esds
151418291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                  } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
151520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->beginBox("d263");
151620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
151720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt32(0);  // vendor
151820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt8(0);   // decoder version
151920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt8(10);  // level: 10
152020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt8(0);   // profile: 0
152120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
152220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->endBox();  // d263
152330ab66297501757d745b9ae10da61adcd891f497Andreas Huber                  } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
152430ab66297501757d745b9ae10da61adcd891f497Andreas Huber                      mOwner->beginBox("avcC");
152530ab66297501757d745b9ae10da61adcd891f497Andreas Huber                        mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
152630ab66297501757d745b9ae10da61adcd891f497Andreas Huber                      mOwner->endBox();  // avcC
152720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  }
152830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
15291acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                  mOwner->beginBox("pasp");
15301acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                    // This is useful if the pixel is not square
15311acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                    mOwner->writeInt32(1 << 16);  // hspacing
15321acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                    mOwner->writeInt32(1 << 16);  // vspacing
15331acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                  mOwner->endBox();  // pasp
153430ab66297501757d745b9ae10da61adcd891f497Andreas Huber                mOwner->endBox();  // mp4v, s263 or avc1
153520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
153620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stsd
153720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
153820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stts");
153920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
1540be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            mOwner->writeInt32(mSttsTableEntries.size());
1541be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin();
1542be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                 it != mSttsTableEntries.end(); ++it) {
1543be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mOwner->writeInt32(it->sampleCount);
1544be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mOwner->writeInt32(it->sampleDuration);
154520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
154620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stts
154720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1548050b28a593350047845a45a14cc5026221ac1620James Dong          if (!is_audio) {
1549050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->beginBox("stss");
1550050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->writeInt32(0);  // version=0, flags=0
1551050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->writeInt32(mStssTableEntries.size());  // number of sync frames
1552050b28a593350047845a45a14cc5026221ac1620James Dong              for (List<int32_t>::iterator it = mStssTableEntries.begin();
1553050b28a593350047845a45a14cc5026221ac1620James Dong                   it != mStssTableEntries.end(); ++it) {
1554050b28a593350047845a45a14cc5026221ac1620James Dong                  mOwner->writeInt32(*it);
1555050b28a593350047845a45a14cc5026221ac1620James Dong              }
1556050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->endBox();  // stss
1557050b28a593350047845a45a14cc5026221ac1620James Dong          }
1558050b28a593350047845a45a14cc5026221ac1620James Dong
155920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stsz");
156020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
1561be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            if (mSamplesHaveSameSize) {
1562be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                List<SampleInfo>::iterator it = mSampleInfos.begin();
1563be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mOwner->writeInt32(it->size);  // default sample size
1564be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            } else {
1565be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mOwner->writeInt32(0);
1566be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
156720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(mSampleInfos.size());
1568be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            if (!mSamplesHaveSameSize) {
1569be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                for (List<SampleInfo>::iterator it = mSampleInfos.begin();
1570be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                     it != mSampleInfos.end(); ++it) {
1571be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                    mOwner->writeInt32((*it).size);
1572be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                }
157320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
157420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stsz
157520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
157620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stsc");
157720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
157813aec890216948b0c364f8f92792129d0335f506James Dong            mOwner->writeInt32(mStscTableEntries.size());
157913aec890216948b0c364f8f92792129d0335f506James Dong            for (List<StscTableEntry>::iterator it = mStscTableEntries.begin();
158013aec890216948b0c364f8f92792129d0335f506James Dong                 it != mStscTableEntries.end(); ++it) {
158113aec890216948b0c364f8f92792129d0335f506James Dong                mOwner->writeInt32(it->firstChunk);
158213aec890216948b0c364f8f92792129d0335f506James Dong                mOwner->writeInt32(it->samplesPerChunk);
158313aec890216948b0c364f8f92792129d0335f506James Dong                mOwner->writeInt32(it->sampleDescriptionId);
158420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
158520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stsc
15861acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          mOwner->beginBox(use32BitOffset? "stco": "co64");
158720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
158813aec890216948b0c364f8f92792129d0335f506James Dong            mOwner->writeInt32(mChunkOffsets.size());
158913aec890216948b0c364f8f92792129d0335f506James Dong            for (List<off_t>::iterator it = mChunkOffsets.begin();
159013aec890216948b0c364f8f92792129d0335f506James Dong                 it != mChunkOffsets.end(); ++it) {
15911acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                if (use32BitOffset) {
15921acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                    mOwner->writeInt32(static_cast<int32_t>(*it));
15931acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                } else {
15941acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                    mOwner->writeInt64((*it));
15951acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                }
159620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
159720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // co64
159820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
159920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->endBox();  // stbl
16001acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong       mOwner->endBox();  // minf
160120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->endBox();  // mdia
160220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOwner->endBox();  // trak
160320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
160420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
160520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
1606