MPEG4Writer.cpp revision e136c3bb38e88315bf8797a464ebf2c788296b22
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>
3520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android {
3720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Writer::Track {
3920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic:
4025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    Track(MPEG4Writer *owner, const sp<MediaSource> &source);
4120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    ~Track();
4220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    status_t start();
4420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void stop();
4525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool reachedEOS();
4620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
473b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber    int64_t getDurationUs() const;
48d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t getEstimatedTrackSizeBytes() const;
4920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void writeTrackHeader(int32_t trackID);
5020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate:
5220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Writer *mOwner;
5320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MetaData> mMeta;
54693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    sp<MediaSource> mSource;
5520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    volatile bool mDone;
563b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber    int64_t mMaxTimeStampUs;
57d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t mEstimatedTrackSizeBytes;
5820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_t mThread;
6020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    struct SampleInfo {
6220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        size_t size;
6320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        int64_t timestamp;
6420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    };
6513aec890216948b0c364f8f92792129d0335f506James Dong    List<SampleInfo>    mSampleInfos;
66be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    bool                mSamplesHaveSameSize;
67be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
6813aec890216948b0c364f8f92792129d0335f506James Dong    List<MediaBuffer *> mChunkSamples;
6913aec890216948b0c364f8f92792129d0335f506James Dong    List<off_t>         mChunkOffsets;
7013aec890216948b0c364f8f92792129d0335f506James Dong
7113aec890216948b0c364f8f92792129d0335f506James Dong    struct StscTableEntry {
7213aec890216948b0c364f8f92792129d0335f506James Dong
7313aec890216948b0c364f8f92792129d0335f506James Dong        StscTableEntry(uint32_t chunk, uint32_t samples, uint32_t id)
7413aec890216948b0c364f8f92792129d0335f506James Dong            : firstChunk(chunk),
7513aec890216948b0c364f8f92792129d0335f506James Dong              samplesPerChunk(samples),
7613aec890216948b0c364f8f92792129d0335f506James Dong              sampleDescriptionId(id) {}
7713aec890216948b0c364f8f92792129d0335f506James Dong
7813aec890216948b0c364f8f92792129d0335f506James Dong        uint32_t firstChunk;
7913aec890216948b0c364f8f92792129d0335f506James Dong        uint32_t samplesPerChunk;
8013aec890216948b0c364f8f92792129d0335f506James Dong        uint32_t sampleDescriptionId;
8113aec890216948b0c364f8f92792129d0335f506James Dong    };
8213aec890216948b0c364f8f92792129d0335f506James Dong    List<StscTableEntry> mStscTableEntries;
8320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
84050b28a593350047845a45a14cc5026221ac1620James Dong    List<int32_t> mStssTableEntries;
85050b28a593350047845a45a14cc5026221ac1620James Dong
86be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    struct SttsTableEntry {
87be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
88be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        SttsTableEntry(uint32_t count, uint32_t duration)
89be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            : sampleCount(count), sampleDuration(duration) {}
90be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
91be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        uint32_t sampleCount;
92be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        uint32_t sampleDuration;
93be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    };
94be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    List<SttsTableEntry> mSttsTableEntries;
95be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
9620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *mCodecSpecificData;
9720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t mCodecSpecificDataSize;
98548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    bool mGotAllCodecSpecificData;
9920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool mReachedEOS;
1013c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    int64_t mStartTimestampUs;
10225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
10320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    static void *ThreadWrapper(void *me);
10420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void threadEntry();
10520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    status_t makeAVCCodecSpecificData(
10703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            const uint8_t *data, size_t size);
10813aec890216948b0c364f8f92792129d0335f506James Dong    void writeOneChunk(bool isAvc);
10903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
11020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track(const Track &);
11120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track &operator=(const Track &);
11220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
11320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
11403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#define USE_NALLEN_FOUR         1
11503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
11620111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::MPEG4Writer(const char *filename)
11720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mFile(fopen(filename, "wb")),
11820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOffset(0),
11913aec890216948b0c364f8f92792129d0335f506James Dong      mMdatOffset(0),
1207837c17063a4c50bc856ba59418516fdab731de7James Dong      mEstimatedMoovBoxSize(0),
12113aec890216948b0c364f8f92792129d0335f506James Dong      mInterleaveDurationUs(500000) {
1220c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(mFile != NULL);
12320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
12420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12530ab66297501757d745b9ae10da61adcd891f497Andreas HuberMPEG4Writer::MPEG4Writer(int fd)
12630ab66297501757d745b9ae10da61adcd891f497Andreas Huber    : mFile(fdopen(fd, "wb")),
12730ab66297501757d745b9ae10da61adcd891f497Andreas Huber      mOffset(0),
12813aec890216948b0c364f8f92792129d0335f506James Dong      mMdatOffset(0),
1297837c17063a4c50bc856ba59418516fdab731de7James Dong      mEstimatedMoovBoxSize(0),
13013aec890216948b0c364f8f92792129d0335f506James Dong      mInterleaveDurationUs(500000) {
13130ab66297501757d745b9ae10da61adcd891f497Andreas Huber    CHECK(mFile != NULL);
13230ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
13330ab66297501757d745b9ae10da61adcd891f497Andreas Huber
13420111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() {
13520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    stop();
13620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
13720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
13820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber         it != mTracks.end(); ++it) {
13920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        delete *it;
14020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
14120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.clear();
14220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
14320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1442dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huberstatus_t MPEG4Writer::addSource(const sp<MediaSource> &source) {
14525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    Track *track = new Track(this, source);
14620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.push_back(track);
1472dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
1482dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    return OK;
14920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
15020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
15125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberstatus_t MPEG4Writer::start() {
15220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mFile == NULL) {
15325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return UNKNOWN_ERROR;
15420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
15520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1563c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    mStartTimestampUs = 0;
1577837c17063a4c50bc856ba59418516fdab731de7James Dong    mStreamableFile = true;
1587837c17063a4c50bc856ba59418516fdab731de7James Dong    mWriteMoovBoxToMemory = false;
1597837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBuffer = NULL;
1607837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
1617837c17063a4c50bc856ba59418516fdab731de7James Dong
16220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    beginBox("ftyp");
16320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      writeFourcc("isom");
16420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      writeInt32(0);
16520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      writeFourcc("isom");
16620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    endBox();
16720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1687837c17063a4c50bc856ba59418516fdab731de7James Dong    mFreeBoxOffset = mOffset;
16920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1707837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mEstimatedMoovBoxSize == 0) {
1717837c17063a4c50bc856ba59418516fdab731de7James Dong        // XXX: Estimate the moov box size
1727837c17063a4c50bc856ba59418516fdab731de7James Dong        //      based on max file size or duration limit
1737837c17063a4c50bc856ba59418516fdab731de7James Dong        mEstimatedMoovBoxSize = 0x0F00;
1747837c17063a4c50bc856ba59418516fdab731de7James Dong    }
1757837c17063a4c50bc856ba59418516fdab731de7James Dong    CHECK(mEstimatedMoovBoxSize >= 8);
1767837c17063a4c50bc856ba59418516fdab731de7James Dong    fseeko(mFile, mFreeBoxOffset, SEEK_SET);
1777837c17063a4c50bc856ba59418516fdab731de7James Dong    writeInt32(mEstimatedMoovBoxSize);
1787837c17063a4c50bc856ba59418516fdab731de7James Dong    write("free", 4);
1797837c17063a4c50bc856ba59418516fdab731de7James Dong
1807837c17063a4c50bc856ba59418516fdab731de7James Dong    mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize;
1817837c17063a4c50bc856ba59418516fdab731de7James Dong    mOffset = mMdatOffset;
1827837c17063a4c50bc856ba59418516fdab731de7James Dong    fseeko(mFile, mMdatOffset, SEEK_SET);
1837837c17063a4c50bc856ba59418516fdab731de7James Dong    write("\x00\x00\x00\x01mdat????????", 16);
18420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
18520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber         it != mTracks.end(); ++it) {
18625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        status_t err = (*it)->start();
18725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
18825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        if (err != OK) {
18925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            for (List<Track *>::iterator it2 = mTracks.begin();
19025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                 it2 != it; ++it2) {
19125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                (*it2)->stop();
19225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            }
19325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
19425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            return err;
19525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        }
19620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
19725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
19825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
19920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
20020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
20120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::stop() {
20220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mFile == NULL) {
20320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return;
20420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
20520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
20620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int64_t max_duration = 0;
20720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
20820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber         it != mTracks.end(); ++it) {
20920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        (*it)->stop();
21020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2113b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber        int64_t duration = (*it)->getDurationUs();
21220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (duration > max_duration) {
21320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            max_duration = duration;
21420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
21520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
21620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2177837c17063a4c50bc856ba59418516fdab731de7James Dong
21820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // Fix up the size of the 'mdat' chunk.
2197837c17063a4c50bc856ba59418516fdab731de7James Dong    fseeko(mFile, mMdatOffset + 8, SEEK_SET);
22020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int64_t size = mOffset - mMdatOffset;
22120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size = hton64(size);
22220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fwrite(&size, 1, 8, mFile);
2237837c17063a4c50bc856ba59418516fdab731de7James Dong    fseeko(mFile, mOffset, SEEK_SET);
22420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
22520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    time_t now = time(NULL);
2267837c17063a4c50bc856ba59418516fdab731de7James Dong    const off_t moovOffset = mOffset;
2277837c17063a4c50bc856ba59418516fdab731de7James Dong    mWriteMoovBoxToMemory = true;
2287837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize);
2297837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
2307837c17063a4c50bc856ba59418516fdab731de7James Dong    CHECK(mMoovBoxBuffer != NULL);
23120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
23220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    beginBox("moov");
23320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
23420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      beginBox("mvhd");
23520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // version=0, flags=0
23620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(now);           // creation time
23720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(now);           // modification time
23820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(1000);          // timescale
2393b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber        writeInt32(max_duration / 1000);
24020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0x10000);       // rate
24120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt16(0x100);         // volume
24220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt16(0);             // reserved
24320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // reserved
24420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // reserved
24520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0x10000);       // matrix
24620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
24720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
24820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
24920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0x10000);
25020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
25120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
25220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
25320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0x40000000);
25420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
25520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
25620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
25720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
25820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
25920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
26020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(mTracks.size() + 1);  // nextTrackID
26120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      endBox();  // mvhd
26220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
26320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      int32_t id = 1;
26420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      for (List<Track *>::iterator it = mTracks.begin();
26520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber           it != mTracks.end(); ++it, ++id) {
26620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          (*it)->writeTrackHeader(id);
26720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      }
26820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    endBox();  // moov
26920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2707837c17063a4c50bc856ba59418516fdab731de7James Dong    mWriteMoovBoxToMemory = false;
2717837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mStreamableFile) {
2727837c17063a4c50bc856ba59418516fdab731de7James Dong        CHECK(mMoovBoxBufferOffset + 8 <= mEstimatedMoovBoxSize);
2737837c17063a4c50bc856ba59418516fdab731de7James Dong
2747837c17063a4c50bc856ba59418516fdab731de7James Dong        // Moov box
2757837c17063a4c50bc856ba59418516fdab731de7James Dong        fseeko(mFile, mFreeBoxOffset, SEEK_SET);
2767837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset = mFreeBoxOffset;
2777837c17063a4c50bc856ba59418516fdab731de7James Dong        write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, mFile);
2787837c17063a4c50bc856ba59418516fdab731de7James Dong
2797837c17063a4c50bc856ba59418516fdab731de7James Dong        // Free box
2807837c17063a4c50bc856ba59418516fdab731de7James Dong        mFreeBoxOffset = mStreamableFile? mOffset: mFreeBoxOffset;
2817837c17063a4c50bc856ba59418516fdab731de7James Dong        fseeko(mFile, mFreeBoxOffset, SEEK_SET);
2827837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset);
2837837c17063a4c50bc856ba59418516fdab731de7James Dong        write("free", 4);
2847837c17063a4c50bc856ba59418516fdab731de7James Dong
2857837c17063a4c50bc856ba59418516fdab731de7James Dong        // Free temp memory
2867837c17063a4c50bc856ba59418516fdab731de7James Dong        free(mMoovBoxBuffer);
2877837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBuffer = NULL;
2887837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBufferOffset = 0;
2897837c17063a4c50bc856ba59418516fdab731de7James Dong    }
2907837c17063a4c50bc856ba59418516fdab731de7James Dong
2910c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(mBoxes.empty());
29220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2937837c17063a4c50bc856ba59418516fdab731de7James Dong    fflush(mFile);
29420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fclose(mFile);
29520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mFile = NULL;
29620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
29720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
29813aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) {
29913aec890216948b0c364f8f92792129d0335f506James Dong    mInterleaveDurationUs = durationUs;
30013aec890216948b0c364f8f92792129d0335f506James Dong    return OK;
30113aec890216948b0c364f8f92792129d0335f506James Dong}
30213aec890216948b0c364f8f92792129d0335f506James Dong
30313aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() {
30413aec890216948b0c364f8f92792129d0335f506James Dong    mLock.lock();
30513aec890216948b0c364f8f92792129d0335f506James Dong}
30613aec890216948b0c364f8f92792129d0335f506James Dong
30713aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() {
30813aec890216948b0c364f8f92792129d0335f506James Dong    mLock.unlock();
30913aec890216948b0c364f8f92792129d0335f506James Dong}
31020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
31113aec890216948b0c364f8f92792129d0335f506James Dongoff_t MPEG4Writer::addSample_l(MediaBuffer *buffer) {
31220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    off_t old_offset = mOffset;
31320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
31420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fwrite((const uint8_t *)buffer->data() + buffer->range_offset(),
31520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber           1, buffer->range_length(), mFile);
31620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
31720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += buffer->range_length();
31820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
31920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return old_offset;
32020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
32120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
32203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) {
32303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (buffer->range_length() < 4) {
32403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return;
32503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
32603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
32703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    const uint8_t *ptr =
32803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        (const uint8_t *)buffer->data() + buffer->range_offset();
32903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
33003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) {
33103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        buffer->set_range(
33203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                buffer->range_offset() + 4, buffer->range_length() - 4);
33303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
33403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
33503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
33613aec890216948b0c364f8f92792129d0335f506James Dongoff_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) {
33730ab66297501757d745b9ae10da61adcd891f497Andreas Huber    off_t old_offset = mOffset;
33830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
33930ab66297501757d745b9ae10da61adcd891f497Andreas Huber    size_t length = buffer->range_length();
34003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
34103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR
34203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    uint8_t x = length >> 24;
34303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    fwrite(&x, 1, 1, mFile);
34403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    x = (length >> 16) & 0xff;
34503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    fwrite(&x, 1, 1, mFile);
34603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    x = (length >> 8) & 0xff;
34703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    fwrite(&x, 1, 1, mFile);
34803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    x = length & 0xff;
34903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    fwrite(&x, 1, 1, mFile);
35003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else
35130ab66297501757d745b9ae10da61adcd891f497Andreas Huber    CHECK(length < 65536);
35230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
35330ab66297501757d745b9ae10da61adcd891f497Andreas Huber    uint8_t x = length >> 8;
35430ab66297501757d745b9ae10da61adcd891f497Andreas Huber    fwrite(&x, 1, 1, mFile);
35530ab66297501757d745b9ae10da61adcd891f497Andreas Huber    x = length & 0xff;
35630ab66297501757d745b9ae10da61adcd891f497Andreas Huber    fwrite(&x, 1, 1, mFile);
35703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif
35830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
35930ab66297501757d745b9ae10da61adcd891f497Andreas Huber    fwrite((const uint8_t *)buffer->data() + buffer->range_offset(),
36030ab66297501757d745b9ae10da61adcd891f497Andreas Huber           1, length, mFile);
36130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
36203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR
36303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    mOffset += length + 4;
36403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else
36530ab66297501757d745b9ae10da61adcd891f497Andreas Huber    mOffset += length + 2;
36603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif
36730ab66297501757d745b9ae10da61adcd891f497Andreas Huber
36830ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return old_offset;
36930ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
37030ab66297501757d745b9ae10da61adcd891f497Andreas Huber
3717837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write(
3727837c17063a4c50bc856ba59418516fdab731de7James Dong        const void *ptr, size_t size, size_t nmemb, FILE *stream) {
3737837c17063a4c50bc856ba59418516fdab731de7James Dong
3747837c17063a4c50bc856ba59418516fdab731de7James Dong    const size_t bytes = size * nmemb;
3757837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
3767837c17063a4c50bc856ba59418516fdab731de7James Dong        if (8 + mMoovBoxBufferOffset + bytes > mEstimatedMoovBoxSize) {
3777837c17063a4c50bc856ba59418516fdab731de7James Dong            for (List<off_t>::iterator it = mBoxes.begin();
3787837c17063a4c50bc856ba59418516fdab731de7James Dong                 it != mBoxes.end(); ++it) {
3797837c17063a4c50bc856ba59418516fdab731de7James Dong                (*it) += mOffset;
3807837c17063a4c50bc856ba59418516fdab731de7James Dong            }
3817837c17063a4c50bc856ba59418516fdab731de7James Dong            fseeko(mFile, mOffset, SEEK_SET);
3827837c17063a4c50bc856ba59418516fdab731de7James Dong            fwrite(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, stream);
3837837c17063a4c50bc856ba59418516fdab731de7James Dong            fwrite(ptr, size, nmemb, stream);
3847837c17063a4c50bc856ba59418516fdab731de7James Dong            mOffset += (bytes + mMoovBoxBufferOffset);
3857837c17063a4c50bc856ba59418516fdab731de7James Dong            free(mMoovBoxBuffer);
3867837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBuffer = NULL;
3877837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset = 0;
3887837c17063a4c50bc856ba59418516fdab731de7James Dong            mWriteMoovBoxToMemory = false;
3897837c17063a4c50bc856ba59418516fdab731de7James Dong            mStreamableFile = false;
3907837c17063a4c50bc856ba59418516fdab731de7James Dong        } else {
3917837c17063a4c50bc856ba59418516fdab731de7James Dong            memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes);
3927837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset += bytes;
3937837c17063a4c50bc856ba59418516fdab731de7James Dong        }
3947837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
3957837c17063a4c50bc856ba59418516fdab731de7James Dong        fwrite(ptr, size, nmemb, stream);
3967837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset += bytes;
3977837c17063a4c50bc856ba59418516fdab731de7James Dong    }
3987837c17063a4c50bc856ba59418516fdab731de7James Dong    return bytes;
3997837c17063a4c50bc856ba59418516fdab731de7James Dong}
4007837c17063a4c50bc856ba59418516fdab731de7James Dong
40120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) {
4020c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(fourcc), 4);
40320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4047837c17063a4c50bc856ba59418516fdab731de7James Dong    mBoxes.push_back(mWriteMoovBoxToMemory?
4057837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset: mOffset);
40620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
40720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeInt32(0);
40820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeFourcc(fourcc);
40920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
41020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
41120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() {
4120c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(!mBoxes.empty());
41320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
41420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    off_t offset = *--mBoxes.end();
41520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mBoxes.erase(--mBoxes.end());
41620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4177837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
4187837c17063a4c50bc856ba59418516fdab731de7James Dong       int32_t x = htonl(mMoovBoxBufferOffset - offset);
4197837c17063a4c50bc856ba59418516fdab731de7James Dong       memcpy(mMoovBoxBuffer + offset, &x, 4);
4207837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
4217837c17063a4c50bc856ba59418516fdab731de7James Dong        fseeko(mFile, offset, SEEK_SET);
4227837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mOffset - offset);
4237837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset -= 4;
4247837c17063a4c50bc856ba59418516fdab731de7James Dong        fseeko(mFile, mOffset, SEEK_SET);
4257837c17063a4c50bc856ba59418516fdab731de7James Dong    }
42620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
42720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
42820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) {
4297837c17063a4c50bc856ba59418516fdab731de7James Dong    write(&x, 1, 1, mFile);
43020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
43120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
43220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) {
43320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htons(x);
4347837c17063a4c50bc856ba59418516fdab731de7James Dong    write(&x, 1, 2, mFile);
43520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
43620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
43720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) {
43820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htonl(x);
4397837c17063a4c50bc856ba59418516fdab731de7James Dong    write(&x, 1, 4, mFile);
44020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
44120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
44220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) {
44320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = hton64(x);
4447837c17063a4c50bc856ba59418516fdab731de7James Dong    write(&x, 1, 8, mFile);
44520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
44620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
44720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) {
44820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t n = strlen(s);
4497837c17063a4c50bc856ba59418516fdab731de7James Dong    write(s, 1, n + 1, mFile);
45020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
45120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
45220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) {
4530c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(s), 4);
4547837c17063a4c50bc856ba59418516fdab731de7James Dong    write(s, 1, 4, mFile);
45520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
45620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
45720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) {
4587837c17063a4c50bc856ba59418516fdab731de7James Dong    write(data, 1, size, mFile);
45920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
46020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
461d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() {
462d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
463d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileSizeLimitBytes == 0) {
464d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
465d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
466d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
467956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize);
468d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
469d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
470d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes();
471d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
472d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return (nTotalBytesEstimate >= mMaxFileSizeLimitBytes);
473d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
474d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
475d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() {
476d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
477d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileDurationLimitUs == 0) {
478d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
479d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
480d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
481d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
482d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
483d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) {
484d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            return true;
485d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
486d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
487d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return false;
488d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
489d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
49025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() {
49125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool allDone = true;
49225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
49325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber         it != mTracks.end(); ++it) {
49425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        if (!(*it)->reachedEOS()) {
49525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            allDone = false;
49625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            break;
49725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        }
49825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
49925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
50025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return allDone;
50125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
50225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
5033c0131f02b6f008321608044c53bccce2ac5f6ddJames Dongvoid MPEG4Writer::setStartTimestamp(int64_t timeUs) {
5043c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    LOGI("setStartTimestamp: %lld", timeUs);
5053c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
5063c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    if (mStartTimestampUs != 0) {
5073c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        return;  // Sorry, too late
5083c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    }
5093c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    mStartTimestampUs = timeUs;
5103c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
5113c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
5123c0131f02b6f008321608044c53bccce2ac5f6ddJames Dongint64_t MPEG4Writer::getStartTimestamp() {
5133c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    LOGI("getStartTimestamp: %lld", mStartTimestampUs);
5143c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
5153c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    return mStartTimestampUs;
5163c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
5173c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
51820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
51920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
52020111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track(
52125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        MPEG4Writer *owner, const sp<MediaSource> &source)
52220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mOwner(owner),
52325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mMeta(source->getFormat()),
52420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSource(source),
52520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDone(false),
5263b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber      mMaxTimeStampUs(0),
527956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      mEstimatedTrackSizeBytes(0),
528be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong      mSamplesHaveSameSize(true),
52920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCodecSpecificData(NULL),
53025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mCodecSpecificDataSize(0),
531548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber      mGotAllCodecSpecificData(false),
53225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mReachedEOS(false) {
53320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
53420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
53520111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() {
53620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    stop();
53720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
53820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mCodecSpecificData != NULL) {
53920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        free(mCodecSpecificData);
54020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mCodecSpecificData = NULL;
54120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
54220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
54320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
54425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberstatus_t MPEG4Writer::Track::start() {
54525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    status_t err = mSource->start();
54625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
54725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    if (err != OK) {
54825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        mDone = mReachedEOS = true;
54925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return err;
55025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
55120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
55220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_t attr;
55320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_init(&attr);
55420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
55520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
55620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = false;
5573b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber    mMaxTimeStampUs = 0;
55825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = false;
559956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    mEstimatedTrackSizeBytes = 0;
56020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
56125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    pthread_create(&mThread, &attr, ThreadWrapper, this);
56220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_destroy(&attr);
56325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
56425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
56520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
56620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
56720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::Track::stop() {
56820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mDone) {
56920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return;
57020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
57120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
57220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = true;
57320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
57420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *dummy;
57520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_join(mThread, &dummy);
57620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
57720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mSource->stop();
57820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
57920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
58025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() {
58125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return mReachedEOS;
58225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
58325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
58420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static
58520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) {
58620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = static_cast<Track *>(me);
58720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
58820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    track->threadEntry();
58920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
59020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return NULL;
59120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
59220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
593548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber#include <ctype.h>
594548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huberstatic void hexdump(const void *_data, size_t size) {
595548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    const uint8_t *data = (const uint8_t *)_data;
596548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    size_t offset = 0;
597548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    while (offset < size) {
598548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        printf("0x%04x  ", offset);
599548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
600548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        size_t n = size - offset;
601548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        if (n > 16) {
602548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            n = 16;
603548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        }
604548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
605548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        for (size_t i = 0; i < 16; ++i) {
606548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            if (i == 8) {
607548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber                printf(" ");
608548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            }
609548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
610548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            if (offset + i < size) {
611548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber                printf("%02x ", data[offset + i]);
612548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            } else {
613548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber                printf("   ");
614548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            }
615548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        }
616548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
617548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        printf(" ");
618548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
619548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        for (size_t i = 0; i < n; ++i) {
620548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            if (isprint(data[offset + i])) {
621548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber                printf("%c", data[offset + i]);
622548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            } else {
623548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber                printf(".");
624548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            }
625548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        }
626548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
627548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        printf("\n");
628548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
629548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        offset += 16;
630548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    }
631548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber}
632548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
633548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
63403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData(
63503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        const uint8_t *data, size_t size) {
636548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    // hexdump(data, size);
637548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
63803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (mCodecSpecificData != NULL) {
639548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        LOGE("Already have codec specific data");
64003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
64103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
64203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
64303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (size < 4 || memcmp("\x00\x00\x00\x01", data, 4)) {
644548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        LOGE("Must start with a start code");
64503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
64603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
64703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
64803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    size_t picParamOffset = 4;
64903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    while (picParamOffset + 3 < size
65003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            && memcmp("\x00\x00\x00\x01", &data[picParamOffset], 4)) {
65103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        ++picParamOffset;
65203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
65303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
65403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (picParamOffset + 3 >= size) {
655548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        LOGE("Could not find start-code for pictureParameterSet");
65603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
65703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
65803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
65903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    size_t seqParamSetLength = picParamOffset - 4;
66003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    size_t picParamSetLength = size - picParamOffset - 4;
66103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
66203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    mCodecSpecificDataSize =
66303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        6 + 1 + seqParamSetLength + 2 + picParamSetLength + 2;
66403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
66503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    mCodecSpecificData = malloc(mCodecSpecificDataSize);
66603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    uint8_t *header = (uint8_t *)mCodecSpecificData;
66703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[0] = 1;
66803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[1] = 0x42;  // profile
66903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[2] = 0x80;
67003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[3] = 0x1e;  // level
67103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
67203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR
67303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[4] = 0xfc | 3;  // length size == 4 bytes
67403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else
67503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[4] = 0xfc | 1;  // length size == 2 bytes
67603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif
67703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
67803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[5] = 0xe0 | 1;
67903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[6] = seqParamSetLength >> 8;
68003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[7] = seqParamSetLength & 0xff;
68103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    memcpy(&header[8], &data[4], seqParamSetLength);
68203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header += 8 + seqParamSetLength;
68303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[0] = 1;
68403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[1] = picParamSetLength >> 8;
68503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[2] = picParamSetLength & 0xff;
68603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    memcpy(&header[3], &data[picParamOffset + 4], picParamSetLength);
68703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
68803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    return OK;
68903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
69003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
69120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::Track::threadEntry() {
69220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MetaData> meta = mSource->getFormat();
69320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const char *mime;
69420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    meta->findCString(kKeyMIMEType, &mime);
695050b28a593350047845a45a14cc5026221ac1620James Dong    bool is_mpeg4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
696050b28a593350047845a45a14cc5026221ac1620James Dong                    !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC);
69730ab66297501757d745b9ae10da61adcd891f497Andreas Huber    bool is_avc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
698956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    bool is_audio = !strncasecmp(mime, "audio/", 6);
69930ab66297501757d745b9ae10da61adcd891f497Andreas Huber    int32_t count = 0;
70013aec890216948b0c364f8f92792129d0335f506James Dong    const int64_t interleaveDurationUs = mOwner->interleaveDuration();
70113aec890216948b0c364f8f92792129d0335f506James Dong    int64_t chunkTimestampUs = 0;
70213aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nChunks = 0;
70313aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nZeroLengthFrames = 0;
704be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    int64_t lastTimestamp = 0;  // Timestamp of the previous sample
705be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    int64_t lastDuration = 0;   // Time spacing between the previous two samples
706be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    int32_t sampleCount = 1;    // Sample count in the current stts table entry
707be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    uint32_t previousSampleSize = 0;  // Size of the previous sample
70820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
70920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBuffer *buffer;
71020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (!mDone && mSource->read(&buffer) == OK) {
71120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (buffer->range_length() == 0) {
71220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer->release();
71320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer = NULL;
71413aec890216948b0c364f8f92792129d0335f506James Dong            ++nZeroLengthFrames;
71520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            continue;
71620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
71720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
71830ab66297501757d745b9ae10da61adcd891f497Andreas Huber        ++count;
71930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
72003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        int32_t isCodecConfig;
72103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig)
72203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                && isCodecConfig) {
723548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            CHECK(!mGotAllCodecSpecificData);
724548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
72503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            if (is_avc) {
72603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                status_t err = makeAVCCodecSpecificData(
72703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        (const uint8_t *)buffer->data()
72803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                            + buffer->range_offset(),
72903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        buffer->range_length());
730be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                CHECK_EQ(OK, err);
73103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            } else if (is_mpeg4) {
73203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificDataSize = buffer->range_length();
73303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificData = malloc(mCodecSpecificDataSize);
73403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                memcpy(mCodecSpecificData,
73503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        (const uint8_t *)buffer->data()
73603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                            + buffer->range_offset(),
73703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                       buffer->range_length());
73830ab66297501757d745b9ae10da61adcd891f497Andreas Huber            }
73930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
74030ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer->release();
74130ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer = NULL;
74230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
743548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            mGotAllCodecSpecificData = true;
74430ab66297501757d745b9ae10da61adcd891f497Andreas Huber            continue;
745548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        } else if (!mGotAllCodecSpecificData &&
746548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber                count == 1 && is_mpeg4 && mCodecSpecificData == NULL) {
74703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            // The TI mpeg4 encoder does not properly set the
74803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            // codec-specific-data flag.
74930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
75020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            const uint8_t *data =
75120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                (const uint8_t *)buffer->data() + buffer->range_offset();
75220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
75320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            const size_t size = buffer->range_length();
75420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
75520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            size_t offset = 0;
75620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (offset + 3 < size) {
75720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (data[offset] == 0x00 && data[offset + 1] == 0x00
75820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    && data[offset + 2] == 0x01 && data[offset + 3] == 0xb6) {
75920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    break;
76020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
76120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
76220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                ++offset;
76320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
76420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7650c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber            // CHECK(offset + 3 < size);
766bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber            if (offset + 3 >= size) {
767bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber                // XXX assume the entire first chunk of data is the codec specific
768bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber                // data.
769bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber                offset = size;
770bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber            }
77120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
77220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mCodecSpecificDataSize = offset;
77320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mCodecSpecificData = malloc(offset);
77420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            memcpy(mCodecSpecificData, data, offset);
77520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
77620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer->set_range(buffer->range_offset() + offset, size - offset);
77703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
77803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            if (size == offset) {
77903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                buffer->release();
78003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                buffer = NULL;
78103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
78203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                continue;
78303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            }
784548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
785548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            mGotAllCodecSpecificData = true;
786548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        } else if (!mGotAllCodecSpecificData && is_avc && count < 3) {
78703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            // The TI video encoder does not flag codec specific data
78803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            // as such and also splits up SPS and PPS across two buffers.
78903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
79003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            const uint8_t *data =
79103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                (const uint8_t *)buffer->data() + buffer->range_offset();
79203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
79303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            size_t size = buffer->range_length();
79403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
79503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            CHECK(count == 2 || mCodecSpecificData == NULL);
79603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
79703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            size_t offset = mCodecSpecificDataSize;
79803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            mCodecSpecificDataSize += size + 4;
79903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            mCodecSpecificData =
80003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                realloc(mCodecSpecificData, mCodecSpecificDataSize);
80103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
80203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            memcpy((uint8_t *)mCodecSpecificData + offset,
80303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                   "\x00\x00\x00\x01", 4);
80403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
80503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            memcpy((uint8_t *)mCodecSpecificData + offset + 4, data, size);
80603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
80703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            buffer->release();
80803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            buffer = NULL;
80903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
81003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            if (count == 2) {
81103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                void *tmp = mCodecSpecificData;
81203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                size = mCodecSpecificDataSize;
81303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificData = NULL;
81403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificDataSize = 0;
81503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
81603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                status_t err = makeAVCCodecSpecificData(
81703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        (const uint8_t *)tmp, size);
81803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                free(tmp);
81903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                tmp = NULL;
820be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                CHECK_EQ(OK, err);
821548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
822548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber                mGotAllCodecSpecificData = true;
82303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            }
82403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
82503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            continue;
82620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
82720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
828e136c3bb38e88315bf8797a464ebf2c788296b22James Dong        if (is_avc) StripStartcode(buffer);
829e136c3bb38e88315bf8797a464ebf2c788296b22James Dong
83020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        SampleInfo info;
83103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        info.size = is_avc
83203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR
83313aec890216948b0c364f8f92792129d0335f506James Dong                ? buffer->range_length() + 4
83403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else
83513aec890216948b0c364f8f92792129d0335f506James Dong                ? buffer->range_length() + 2
83603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif
83713aec890216948b0c364f8f92792129d0335f506James Dong                : buffer->range_length();
838050b28a593350047845a45a14cc5026221ac1620James Dong
839d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        // Max file size or duration handling
840d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        mEstimatedTrackSizeBytes += info.size;
841d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileSizeLimit()) {
842d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            buffer->release();
843d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            buffer = NULL;
844d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
845d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
846d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
847d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileDurationLimit()) {
848d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            buffer->release();
849d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            buffer = NULL;
850d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
851d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
852d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
853d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
854050b28a593350047845a45a14cc5026221ac1620James Dong
85548c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        int64_t timestampUs;
85648c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        CHECK(buffer->meta_data()->findInt64(kKeyTime, &timestampUs));
8573c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        if (mSampleInfos.empty()) {
8583c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong            mOwner->setStartTimestamp(timestampUs);
8593c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong            mStartTimestampUs = (timestampUs - mOwner->getStartTimestamp());
8603c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        }
86148c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber
8623b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber        if (timestampUs > mMaxTimeStampUs) {
8633b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber            mMaxTimeStampUs = timestampUs;
8643b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber        }
8653b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber
86648c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        // Our timestamp is in ms.
86748c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        info.timestamp = (timestampUs + 500) / 1000;
86820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mSampleInfos.push_back(info);
869be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        if (mSampleInfos.size() > 2) {
870be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            if (lastDuration != info.timestamp - lastTimestamp) {
871be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                SttsTableEntry sttsEntry(sampleCount, lastDuration);
872be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mSttsTableEntries.push_back(sttsEntry);
873be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                sampleCount = 1;
874be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            } else {
875be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                ++sampleCount;
876be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
877be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
878be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        if (mSamplesHaveSameSize) {
879be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            if (mSampleInfos.size() >= 2 && previousSampleSize != info.size) {
880be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mSamplesHaveSameSize = false;
881be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
882be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            previousSampleSize = info.size;
883be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
884be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        lastDuration = info.timestamp - lastTimestamp;
885be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        lastTimestamp = info.timestamp;
88620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
88713aec890216948b0c364f8f92792129d0335f506James Dong////////////////////////////////////////////////////////////////////////////////
88813aec890216948b0c364f8f92792129d0335f506James Dong        // Make a deep copy of the MediaBuffer less Metadata
88913aec890216948b0c364f8f92792129d0335f506James Dong        MediaBuffer *copy = new MediaBuffer(buffer->range_length());
89013aec890216948b0c364f8f92792129d0335f506James Dong        memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(),
89113aec890216948b0c364f8f92792129d0335f506James Dong                buffer->range_length());
89213aec890216948b0c364f8f92792129d0335f506James Dong        copy->set_range(0, buffer->range_length());
89313aec890216948b0c364f8f92792129d0335f506James Dong
89413aec890216948b0c364f8f92792129d0335f506James Dong        mChunkSamples.push_back(copy);
89513aec890216948b0c364f8f92792129d0335f506James Dong        if (interleaveDurationUs == 0) {
89613aec890216948b0c364f8f92792129d0335f506James Dong            StscTableEntry stscEntry(++nChunks, 1, 1);
89713aec890216948b0c364f8f92792129d0335f506James Dong            mStscTableEntries.push_back(stscEntry);
89813aec890216948b0c364f8f92792129d0335f506James Dong            writeOneChunk(is_avc);
89913aec890216948b0c364f8f92792129d0335f506James Dong        } else {
90013aec890216948b0c364f8f92792129d0335f506James Dong            if (chunkTimestampUs == 0) {
90113aec890216948b0c364f8f92792129d0335f506James Dong                chunkTimestampUs = timestampUs;
90213aec890216948b0c364f8f92792129d0335f506James Dong            } else {
90313aec890216948b0c364f8f92792129d0335f506James Dong                if (timestampUs - chunkTimestampUs > interleaveDurationUs) {
90413aec890216948b0c364f8f92792129d0335f506James Dong                    ++nChunks;
90513aec890216948b0c364f8f92792129d0335f506James Dong                    if (nChunks == 1 ||  // First chunk
90613aec890216948b0c364f8f92792129d0335f506James Dong                        (--(mStscTableEntries.end()))->samplesPerChunk !=
90713aec890216948b0c364f8f92792129d0335f506James Dong                         mChunkSamples.size()) {
90813aec890216948b0c364f8f92792129d0335f506James Dong                        StscTableEntry stscEntry(nChunks,
90913aec890216948b0c364f8f92792129d0335f506James Dong                                mChunkSamples.size(), 1);
91013aec890216948b0c364f8f92792129d0335f506James Dong                        mStscTableEntries.push_back(stscEntry);
91113aec890216948b0c364f8f92792129d0335f506James Dong                    }
91213aec890216948b0c364f8f92792129d0335f506James Dong                    writeOneChunk(is_avc);
91313aec890216948b0c364f8f92792129d0335f506James Dong                    chunkTimestampUs = timestampUs;
91413aec890216948b0c364f8f92792129d0335f506James Dong                }
91513aec890216948b0c364f8f92792129d0335f506James Dong            }
91613aec890216948b0c364f8f92792129d0335f506James Dong        }
91713aec890216948b0c364f8f92792129d0335f506James Dong
918050b28a593350047845a45a14cc5026221ac1620James Dong        int32_t isSync = false;
91913aec890216948b0c364f8f92792129d0335f506James Dong        if (buffer->meta_data()->findInt32(kKeyIsSyncFrame, &isSync) &&
92013aec890216948b0c364f8f92792129d0335f506James Dong            isSync != 0) {
921050b28a593350047845a45a14cc5026221ac1620James Dong            mStssTableEntries.push_back(mSampleInfos.size());
922050b28a593350047845a45a14cc5026221ac1620James Dong        }
923be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
92420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        buffer->release();
92520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        buffer = NULL;
92620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
92725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
928f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong    if (mSampleInfos.empty()) {
929f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong        mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_STOP_PREMATURELY, 0);
930f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong    }
931be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
93213aec890216948b0c364f8f92792129d0335f506James Dong    // Last chunk
93313aec890216948b0c364f8f92792129d0335f506James Dong    if (!mChunkSamples.empty()) {
93413aec890216948b0c364f8f92792129d0335f506James Dong        ++nChunks;
93513aec890216948b0c364f8f92792129d0335f506James Dong        StscTableEntry stscEntry(nChunks, mChunkSamples.size(), 1);
93613aec890216948b0c364f8f92792129d0335f506James Dong        mStscTableEntries.push_back(stscEntry);
93713aec890216948b0c364f8f92792129d0335f506James Dong        writeOneChunk(is_avc);
93813aec890216948b0c364f8f92792129d0335f506James Dong    }
93913aec890216948b0c364f8f92792129d0335f506James Dong
940be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // We don't really know how long the last frame lasts, since
941be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // there is no frame time after it, just repeat the previous
942be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // frame's duration.
943be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    if (mSampleInfos.size() == 1) {
944be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        lastDuration = 0;  // A single sample's duration
945be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    } else {
946be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        ++sampleCount;  // Count for the last sample
947be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    }
948be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    SttsTableEntry sttsEntry(sampleCount, lastDuration);
949be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    mSttsTableEntries.push_back(sttsEntry);
95025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = true;
951956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    LOGI("Received total/0-length (%d/%d) buffers and encoded %d frames - %s",
952956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            count, nZeroLengthFrames, mSampleInfos.size(), is_audio? "audio": "video");
95313aec890216948b0c364f8f92792129d0335f506James Dong}
95413aec890216948b0c364f8f92792129d0335f506James Dong
95513aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::Track::writeOneChunk(bool isAvc) {
95613aec890216948b0c364f8f92792129d0335f506James Dong    mOwner->lock();
95713aec890216948b0c364f8f92792129d0335f506James Dong    for (List<MediaBuffer *>::iterator it = mChunkSamples.begin();
95813aec890216948b0c364f8f92792129d0335f506James Dong         it != mChunkSamples.end(); ++it) {
95913aec890216948b0c364f8f92792129d0335f506James Dong        off_t offset = isAvc? mOwner->addLengthPrefixedSample_l(*it)
96013aec890216948b0c364f8f92792129d0335f506James Dong                            : mOwner->addSample_l(*it);
96113aec890216948b0c364f8f92792129d0335f506James Dong        if (it == mChunkSamples.begin()) {
96213aec890216948b0c364f8f92792129d0335f506James Dong            mChunkOffsets.push_back(offset);
96313aec890216948b0c364f8f92792129d0335f506James Dong        }
96413aec890216948b0c364f8f92792129d0335f506James Dong    }
96513aec890216948b0c364f8f92792129d0335f506James Dong    mOwner->unlock();
96613aec890216948b0c364f8f92792129d0335f506James Dong    while (!mChunkSamples.empty()) {
96713aec890216948b0c364f8f92792129d0335f506James Dong        List<MediaBuffer *>::iterator it = mChunkSamples.begin();
96813aec890216948b0c364f8f92792129d0335f506James Dong        (*it)->release();
96913aec890216948b0c364f8f92792129d0335f506James Dong        (*it) = NULL;
97013aec890216948b0c364f8f92792129d0335f506James Dong        mChunkSamples.erase(it);
97113aec890216948b0c364f8f92792129d0335f506James Dong    }
97213aec890216948b0c364f8f92792129d0335f506James Dong    mChunkSamples.clear();
97320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
97420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9753b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const {
9763b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber    return mMaxTimeStampUs;
97720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
97820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
979d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const {
980d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return mEstimatedTrackSizeBytes;
981d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
982d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
98320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::Track::writeTrackHeader(int32_t trackID) {
98420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const char *mime;
98520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool success = mMeta->findCString(kKeyMIMEType, &mime);
9860c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(success);
98720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
98820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool is_audio = !strncasecmp(mime, "audio/", 6);
98920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
99020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    time_t now = time(NULL);
99120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
99220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOwner->beginBox("trak");
99320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
99420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->beginBox("tkhd");
99520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);             // version=0, flags=0
99620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(now);           // creation time
99720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(now);           // modification time
99820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(trackID);
99920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);             // reserved
10003b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber        mOwner->writeInt32(getDurationUs() / 1000);
100120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);             // reserved
100220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);             // reserved
100320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt16(0);             // layer
100420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt16(0);             // alternate group
100520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt16(is_audio ? 0x100 : 0);  // volume
100620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt16(0);             // reserved
100720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
100820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0x10000);       // matrix
100920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
101020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
101120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
101220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0x10000);
101320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
101420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
101520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
101620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0x40000000);
101720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
101820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (is_audio) {
101920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);
102020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);
102120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        } else {
102220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            int32_t width, height;
102320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            bool success = mMeta->findInt32(kKeyWidth, &width);
102420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            success = success && mMeta->findInt32(kKeyHeight, &height);
10250c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber            CHECK(success);
102620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1027050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->writeInt32(width << 16);   // 32-bit fixed-point value
1028050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->writeInt32(height << 16);  // 32-bit fixed-point value
102920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
103020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->endBox();  // tkhd
103120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10323c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong      if (mStartTimestampUs != 0) {
10333c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        mOwner->beginBox("edts");
10343c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong          mOwner->writeInt32(0);             // version=0, flags=0
10353c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong          mOwner->beginBox("elst");
10363c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong            mOwner->writeInt32(0);           // version=0, flags=0
10373c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong            mOwner->writeInt32(1);           // a single entry
10383c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong            mOwner->writeInt32(mStartTimestampUs / 1000);  // edit duration
1039956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            mOwner->writeInt32(-1);          // empty edit box to signal starting time offset
10403c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong            mOwner->writeInt32(1);           // x1 rate
10413c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong          mOwner->endBox();
10423c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        mOwner->endBox();
10433c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong      }
10443c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
104520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->beginBox("mdia");
104620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
104720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("mdhd");
104820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // version=0, flags=0
104920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(now);           // creation time
105020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(now);           // modification time
105120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(1000);          // timescale
10523b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber          mOwner->writeInt32(getDurationUs() / 1000);
105320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt16(0);             // language code XXX
105420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt16(0);             // predefined
105520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->endBox();
105620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
105720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("hdlr");
105820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // version=0, flags=0
1059050b28a593350047845a45a14cc5026221ac1620James Dong          mOwner->writeInt32(0);             // component type: should be mhlr
1060050b28a593350047845a45a14cc5026221ac1620James Dong          mOwner->writeFourcc(is_audio ? "soun" : "vide");  // component subtype
106120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // reserved
106220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // reserved
106320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // reserved
1064956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong          mOwner->writeCString(is_audio ? "SoundHandler": "");  // name
106520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->endBox();
106620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
106720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("minf");
106820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          if (is_audio) {
106920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->beginBox("smhd");
107020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt32(0);           // version=0, flags=0
107120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // balance
107220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // reserved
107320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->endBox();
107420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          } else {
107520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->beginBox("vmhd");
107620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt32(0x00000001);  // version=0, flags=1
107720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // graphics mode
107820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // opcolor
107920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);
108020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);
108120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->endBox();
108220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          }
1083050b28a593350047845a45a14cc5026221ac1620James Dong
1084050b28a593350047845a45a14cc5026221ac1620James Dong          mOwner->beginBox("dinf");
1085050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->beginBox("dref");
1086050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->writeInt32(0);  // version=0, flags=0
1087050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->writeInt32(1);
1088050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->beginBox("url ");
1089050b28a593350047845a45a14cc5026221ac1620James Dong                mOwner->writeInt32(1);  // version=0, flags=1
1090050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->endBox();  // url
1091050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->endBox();  // dref
1092050b28a593350047845a45a14cc5026221ac1620James Dong          mOwner->endBox();  // dinf
1093050b28a593350047845a45a14cc5026221ac1620James Dong
1094050b28a593350047845a45a14cc5026221ac1620James Dong       mOwner->endBox();  // minf
109520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
109620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("stbl");
109720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
109820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stsd");
109920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);               // version=0, flags=0
110020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(1);               // entry count
110120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (is_audio) {
110225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                const char *fourcc = NULL;
110318291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) {
110425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    fourcc = "samr";
110518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
110625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    fourcc = "sawb";
1107050b28a593350047845a45a14cc5026221ac1620James Dong                } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
1108050b28a593350047845a45a14cc5026221ac1620James Dong                    fourcc = "mp4a";
110925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                } else {
111025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    LOGE("Unknown mime type '%s'.", mime);
111125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    CHECK(!"should not be here, unknown mime type.");
111225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                }
111325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
111425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                mOwner->beginBox(fourcc);          // audio format
111520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
111620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
1117050b28a593350047845a45a14cc5026221ac1620James Dong                  mOwner->writeInt16(0x1);         // data ref index
111820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
111920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
1120050b28a593350047845a45a14cc5026221ac1620James Dong                  int32_t nChannels;
1121050b28a593350047845a45a14cc5026221ac1620James Dong                  CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels));
1122050b28a593350047845a45a14cc5026221ac1620James Dong                  mOwner->writeInt16(nChannels);   // channel count
112320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(16);          // sample size
112420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // predefined
112520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
112620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
112720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  int32_t samplerate;
112820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  bool success = mMeta->findInt32(kKeySampleRate, &samplerate);
11290c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                  CHECK(success);
113020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
113120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(samplerate << 16);
1132050b28a593350047845a45a14cc5026221ac1620James Dong                  if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
1133050b28a593350047845a45a14cc5026221ac1620James Dong                    mOwner->beginBox("esds");
1134050b28a593350047845a45a14cc5026221ac1620James Dong
1135050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt32(0);     // version=0, flags=0
1136050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x03);   // ES_DescrTag
1137050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(23 + mCodecSpecificDataSize);
1138050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt16(0x0000);// ES_ID
1139050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x00);
1140050b28a593350047845a45a14cc5026221ac1620James Dong
1141050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x04);   // DecoderConfigDescrTag
1142050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(15 + mCodecSpecificDataSize);
1143050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x40);   // objectTypeIndication ISO/IEC 14492-2
1144050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x15);   // streamType AudioStream
1145050b28a593350047845a45a14cc5026221ac1620James Dong
1146050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt16(0x03);  // XXX
1147050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x00);   // buffer size 24-bit
1148050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt32(96000); // max bit rate
1149050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt32(96000); // avg bit rate
1150050b28a593350047845a45a14cc5026221ac1620James Dong
1151050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x05);   // DecoderSpecificInfoTag
1152050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(mCodecSpecificDataSize);
1153050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
1154050b28a593350047845a45a14cc5026221ac1620James Dong
1155050b28a593350047845a45a14cc5026221ac1620James Dong                        static const uint8_t kData2[] = {
1156050b28a593350047845a45a14cc5026221ac1620James Dong                            0x06,  // SLConfigDescriptorTag
1157050b28a593350047845a45a14cc5026221ac1620James Dong                            0x01,
1158050b28a593350047845a45a14cc5026221ac1620James Dong                            0x02
1159050b28a593350047845a45a14cc5026221ac1620James Dong                        };
1160050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->write(kData2, sizeof(kData2));
1161050b28a593350047845a45a14cc5026221ac1620James Dong
1162050b28a593350047845a45a14cc5026221ac1620James Dong                    mOwner->endBox();  // esds
1163050b28a593350047845a45a14cc5026221ac1620James Dong                  }
116420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mOwner->endBox();
116520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
116618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
116720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    mOwner->beginBox("mp4v");
116818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
116920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    mOwner->beginBox("s263");
117030ab66297501757d745b9ae10da61adcd891f497Andreas Huber                } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
117130ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    mOwner->beginBox("avc1");
117220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                } else {
117325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    LOGE("Unknown mime type '%s'.", mime);
11740c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                    CHECK(!"should not be here, unknown mime type.");
117520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
117620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
117720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
117820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
117920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // data ref index
118020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // predefined
118120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
118220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // predefined
118320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // predefined
118420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // predefined
118520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
118620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  int32_t width, height;
118720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  bool success = mMeta->findInt32(kKeyWidth, &width);
118820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  success = success && mMeta->findInt32(kKeyHeight, &height);
11890c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                  CHECK(success);
119020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
119120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(width);
119220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(height);
119320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0x480000);    // horiz resolution
119420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0x480000);    // vert resolution
119520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
119620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(1);           // frame count
119720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->write("                                ", 32);
119820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0x18);        // depth
119920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(-1);          // predefined
120020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12010c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                  CHECK(23 + mCodecSpecificDataSize < 128);
120220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
120318291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                  if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
120420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->beginBox("esds");
120520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
120620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt32(0);           // version=0, flags=0
120720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
120820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x03);  // ES_DescrTag
120920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(23 + mCodecSpecificDataSize);
121020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt16(0x0000);  // ES_ID
121120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x1f);
121220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
121320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x04);  // DecoderConfigDescrTag
121420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(15 + mCodecSpecificDataSize);
121520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x20);  // objectTypeIndication ISO/IEC 14492-2
121620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x11);  // streamType VisualStream
121720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
121820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        static const uint8_t kData[] = {
121920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x01, 0x77, 0x00,
122020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x00, 0x03, 0xe8, 0x00,
122120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x00, 0x03, 0xe8, 0x00
122220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        };
122320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->write(kData, sizeof(kData));
1224050b28a593350047845a45a14cc5026221ac1620James Dong
122520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x05);  // DecoderSpecificInfoTag
122620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
122720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(mCodecSpecificDataSize);
122820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
122920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
123020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        static const uint8_t kData2[] = {
123120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x06,  // SLConfigDescriptorTag
123220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x01,
123320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x02
123420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        };
123520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->write(kData2, sizeof(kData2));
123620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
123720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->endBox();  // esds
123818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                  } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
123920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->beginBox("d263");
124020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
124120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt32(0);  // vendor
124220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt8(0);   // decoder version
124320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt8(10);  // level: 10
124420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt8(0);   // profile: 0
124520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
124620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->endBox();  // d263
124730ab66297501757d745b9ae10da61adcd891f497Andreas Huber                  } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
124830ab66297501757d745b9ae10da61adcd891f497Andreas Huber                      mOwner->beginBox("avcC");
124930ab66297501757d745b9ae10da61adcd891f497Andreas Huber                        mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
125030ab66297501757d745b9ae10da61adcd891f497Andreas Huber                      mOwner->endBox();  // avcC
125120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  }
125230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
125330ab66297501757d745b9ae10da61adcd891f497Andreas Huber                mOwner->endBox();  // mp4v, s263 or avc1
125420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
125520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stsd
125620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
125720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stts");
125820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
1259be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            mOwner->writeInt32(mSttsTableEntries.size());
1260be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin();
1261be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                 it != mSttsTableEntries.end(); ++it) {
1262be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mOwner->writeInt32(it->sampleCount);
1263be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mOwner->writeInt32(it->sampleDuration);
126420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
126520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stts
126620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1267050b28a593350047845a45a14cc5026221ac1620James Dong          if (!is_audio) {
1268050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->beginBox("stss");
1269050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->writeInt32(0);  // version=0, flags=0
1270050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->writeInt32(mStssTableEntries.size());  // number of sync frames
1271050b28a593350047845a45a14cc5026221ac1620James Dong              for (List<int32_t>::iterator it = mStssTableEntries.begin();
1272050b28a593350047845a45a14cc5026221ac1620James Dong                   it != mStssTableEntries.end(); ++it) {
1273050b28a593350047845a45a14cc5026221ac1620James Dong                  mOwner->writeInt32(*it);
1274050b28a593350047845a45a14cc5026221ac1620James Dong              }
1275050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->endBox();  // stss
1276050b28a593350047845a45a14cc5026221ac1620James Dong          }
1277050b28a593350047845a45a14cc5026221ac1620James Dong
127820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stsz");
127920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
1280be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            if (mSamplesHaveSameSize) {
1281be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                List<SampleInfo>::iterator it = mSampleInfos.begin();
1282be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mOwner->writeInt32(it->size);  // default sample size
1283be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            } else {
1284be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mOwner->writeInt32(0);
1285be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
128620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(mSampleInfos.size());
1287be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            if (!mSamplesHaveSameSize) {
1288be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                for (List<SampleInfo>::iterator it = mSampleInfos.begin();
1289be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                     it != mSampleInfos.end(); ++it) {
1290be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                    mOwner->writeInt32((*it).size);
1291be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                }
129220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
129320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stsz
129420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
129520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stsc");
129620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
129713aec890216948b0c364f8f92792129d0335f506James Dong            mOwner->writeInt32(mStscTableEntries.size());
129813aec890216948b0c364f8f92792129d0335f506James Dong            for (List<StscTableEntry>::iterator it = mStscTableEntries.begin();
129913aec890216948b0c364f8f92792129d0335f506James Dong                 it != mStscTableEntries.end(); ++it) {
130013aec890216948b0c364f8f92792129d0335f506James Dong                mOwner->writeInt32(it->firstChunk);
130113aec890216948b0c364f8f92792129d0335f506James Dong                mOwner->writeInt32(it->samplesPerChunk);
130213aec890216948b0c364f8f92792129d0335f506James Dong                mOwner->writeInt32(it->sampleDescriptionId);
130320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
130420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stsc
130520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
130620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("co64");
130720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
130813aec890216948b0c364f8f92792129d0335f506James Dong            mOwner->writeInt32(mChunkOffsets.size());
130913aec890216948b0c364f8f92792129d0335f506James Dong            for (List<off_t>::iterator it = mChunkOffsets.begin();
131013aec890216948b0c364f8f92792129d0335f506James Dong                 it != mChunkOffsets.end(); ++it) {
131113aec890216948b0c364f8f92792129d0335f506James Dong                mOwner->writeInt64((*it));
131220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
131320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // co64
131420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
131520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->endBox();  // stbl
131620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->endBox();  // mdia
131720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOwner->endBox();  // trak
131820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
131920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
132020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
1321