MPEG4Writer.cpp revision 2dce41ad26cb3e9e15c9e456a84bcf5309548ca0
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
1720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <arpa/inet.h>
1820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <ctype.h>
2020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <pthread.h>
2120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MPEG4Writer.h>
2320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBuffer.h>
2420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h>
250c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber#include <media/stagefright/MediaDebug.h>
2618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h>
2720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaSource.h>
2820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/Utils.h>
2920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android {
3120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Writer::Track {
3320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic:
3425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    Track(MPEG4Writer *owner, const sp<MediaSource> &source);
3520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    ~Track();
3620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    status_t start();
3820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void stop();
3925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool reachedEOS();
4020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int64_t getDuration() const;
4220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void writeTrackHeader(int32_t trackID);
4320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate:
4520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Writer *mOwner;
4620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MetaData> mMeta;
47693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    sp<MediaSource> mSource;
4820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    volatile bool mDone;
4920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_t mThread;
5120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    struct SampleInfo {
5320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        size_t size;
5420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        off_t offset;
5520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        int64_t timestamp;
5620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    };
5720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    List<SampleInfo> mSampleInfos;
5820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *mCodecSpecificData;
6020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t mCodecSpecificDataSize;
6120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool mReachedEOS;
6325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
6420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    static void *ThreadWrapper(void *me);
6520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void threadEntry();
6620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track(const Track &);
6820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track &operator=(const Track &);
6920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
7020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7120111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::MPEG4Writer(const char *filename)
7220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mFile(fopen(filename, "wb")),
7320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOffset(0),
7420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mMdatOffset(0) {
750c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(mFile != NULL);
7620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
7720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7830ab66297501757d745b9ae10da61adcd891f497Andreas HuberMPEG4Writer::MPEG4Writer(int fd)
7930ab66297501757d745b9ae10da61adcd891f497Andreas Huber    : mFile(fdopen(fd, "wb")),
8030ab66297501757d745b9ae10da61adcd891f497Andreas Huber      mOffset(0),
8130ab66297501757d745b9ae10da61adcd891f497Andreas Huber      mMdatOffset(0) {
8230ab66297501757d745b9ae10da61adcd891f497Andreas Huber    CHECK(mFile != NULL);
8330ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
8430ab66297501757d745b9ae10da61adcd891f497Andreas Huber
8520111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() {
8620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    stop();
8720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
8920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber         it != mTracks.end(); ++it) {
9020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        delete *it;
9120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
9220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.clear();
9320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
9420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
952dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huberstatus_t MPEG4Writer::addSource(const sp<MediaSource> &source) {
9625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    Track *track = new Track(this, source);
9720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.push_back(track);
982dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
992dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    return OK;
10020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
10120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberstatus_t MPEG4Writer::start() {
10320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mFile == NULL) {
10425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return UNKNOWN_ERROR;
10520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
10620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    beginBox("ftyp");
10820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      writeFourcc("isom");
10920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      writeInt32(0);
11020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      writeFourcc("isom");
11120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    endBox();
11220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
11320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mMdatOffset = mOffset;
11420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    write("\x00\x00\x00\x01mdat????????", 16);
11520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
11620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
11720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber         it != mTracks.end(); ++it) {
11825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        status_t err = (*it)->start();
11925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
12025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        if (err != OK) {
12125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            for (List<Track *>::iterator it2 = mTracks.begin();
12225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                 it2 != it; ++it2) {
12325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                (*it2)->stop();
12425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            }
12525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
12625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            return err;
12725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        }
12820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
12925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
13025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
13120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
13220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
13320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::stop() {
13420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mFile == NULL) {
13520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return;
13620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
13720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
13820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int64_t max_duration = 0;
13920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
14020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber         it != mTracks.end(); ++it) {
14120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        (*it)->stop();
14220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        int64_t duration = (*it)->getDuration();
14420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (duration > max_duration) {
14520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            max_duration = duration;
14620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
14720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
14820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // Fix up the size of the 'mdat' chunk.
15020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fseek(mFile, mMdatOffset + 8, SEEK_SET);
15120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int64_t size = mOffset - mMdatOffset;
15220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size = hton64(size);
15320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fwrite(&size, 1, 8, mFile);
15420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fseek(mFile, mOffset, SEEK_SET);
15520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
15620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    time_t now = time(NULL);
15720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
15820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    beginBox("moov");
15920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
16020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      beginBox("mvhd");
16120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // version=0, flags=0
16220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(now);           // creation time
16320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(now);           // modification time
16420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(1000);          // timescale
16520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(max_duration);
16620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0x10000);       // rate
16720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt16(0x100);         // volume
16820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt16(0);             // reserved
16920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // reserved
17020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // reserved
17120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0x10000);       // matrix
17220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
17320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
17420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
17520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0x10000);
17620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
17720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
17820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
17920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0x40000000);
18020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
18120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
18220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
18320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
18420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
18520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
18620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(mTracks.size() + 1);  // nextTrackID
18720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      endBox();  // mvhd
18820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
18920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      int32_t id = 1;
19020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      for (List<Track *>::iterator it = mTracks.begin();
19120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber           it != mTracks.end(); ++it, ++id) {
19220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          (*it)->writeTrackHeader(id);
19320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      }
19420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    endBox();  // moov
19520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1960c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(mBoxes.empty());
19720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
19820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fclose(mFile);
19920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mFile = NULL;
20020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
20120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
20220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberoff_t MPEG4Writer::addSample(MediaBuffer *buffer) {
20320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Mutex::Autolock autoLock(mLock);
20420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
20520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    off_t old_offset = mOffset;
20620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
20720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fwrite((const uint8_t *)buffer->data() + buffer->range_offset(),
20820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber           1, buffer->range_length(), mFile);
20920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
21020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += buffer->range_length();
21120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
21220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return old_offset;
21320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
21420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
21530ab66297501757d745b9ae10da61adcd891f497Andreas Huberoff_t MPEG4Writer::addLengthPrefixedSample(MediaBuffer *buffer) {
21630ab66297501757d745b9ae10da61adcd891f497Andreas Huber    Mutex::Autolock autoLock(mLock);
21730ab66297501757d745b9ae10da61adcd891f497Andreas Huber
21830ab66297501757d745b9ae10da61adcd891f497Andreas Huber    off_t old_offset = mOffset;
21930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
22030ab66297501757d745b9ae10da61adcd891f497Andreas Huber    size_t length = buffer->range_length();
22130ab66297501757d745b9ae10da61adcd891f497Andreas Huber    CHECK(length < 65536);
22230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
22330ab66297501757d745b9ae10da61adcd891f497Andreas Huber    uint8_t x = length >> 8;
22430ab66297501757d745b9ae10da61adcd891f497Andreas Huber    fwrite(&x, 1, 1, mFile);
22530ab66297501757d745b9ae10da61adcd891f497Andreas Huber    x = length & 0xff;
22630ab66297501757d745b9ae10da61adcd891f497Andreas Huber    fwrite(&x, 1, 1, mFile);
22730ab66297501757d745b9ae10da61adcd891f497Andreas Huber
22830ab66297501757d745b9ae10da61adcd891f497Andreas Huber    fwrite((const uint8_t *)buffer->data() + buffer->range_offset(),
22930ab66297501757d745b9ae10da61adcd891f497Andreas Huber           1, length, mFile);
23030ab66297501757d745b9ae10da61adcd891f497Andreas Huber
23130ab66297501757d745b9ae10da61adcd891f497Andreas Huber    mOffset += length + 2;
23230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
23330ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return old_offset;
23430ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
23530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
23620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) {
2370c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(fourcc), 4);
23820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
23920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mBoxes.push_back(mOffset);
24020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
24120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeInt32(0);
24220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeFourcc(fourcc);
24320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
24420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
24520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() {
2460c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(!mBoxes.empty());
24720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
24820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    off_t offset = *--mBoxes.end();
24920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mBoxes.erase(--mBoxes.end());
25020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
25120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fseek(mFile, offset, SEEK_SET);
25220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeInt32(mOffset - offset);
25320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset -= 4;
25420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fseek(mFile, mOffset, SEEK_SET);
25520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
25620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
25720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) {
25820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fwrite(&x, 1, 1, mFile);
25920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    ++mOffset;
26020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
26120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
26220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) {
26320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htons(x);
26420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fwrite(&x, 1, 2, mFile);
26520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += 2;
26620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
26720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
26820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) {
26920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htonl(x);
27020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fwrite(&x, 1, 4, mFile);
27120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += 4;
27220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
27320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
27420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) {
27520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = hton64(x);
27620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fwrite(&x, 1, 8, mFile);
27720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += 8;
27820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
27920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
28020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) {
28120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t n = strlen(s);
28220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
28320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fwrite(s, 1, n + 1, mFile);
28420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += n + 1;
28520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
28620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
28720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) {
2880c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(s), 4);
28920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fwrite(s, 1, 4, mFile);
29020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += 4;
29120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
29220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
29320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) {
29420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fwrite(data, 1, size, mFile);
29520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += size;
29620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
29720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
29825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() {
29925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool allDone = true;
30025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
30125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber         it != mTracks.end(); ++it) {
30225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        if (!(*it)->reachedEOS()) {
30325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            allDone = false;
30425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            break;
30525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        }
30625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
30725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
30825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return allDone;
30925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
31025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
31120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
31220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
31320111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track(
31425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        MPEG4Writer *owner, const sp<MediaSource> &source)
31520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mOwner(owner),
31625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mMeta(source->getFormat()),
31720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSource(source),
31820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDone(false),
31920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCodecSpecificData(NULL),
32025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mCodecSpecificDataSize(0),
32125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mReachedEOS(false) {
32220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
32320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
32420111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() {
32520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    stop();
32620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
32720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mCodecSpecificData != NULL) {
32820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        free(mCodecSpecificData);
32920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mCodecSpecificData = NULL;
33020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
33120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
33220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
33325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberstatus_t MPEG4Writer::Track::start() {
33425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    status_t err = mSource->start();
33525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
33625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    if (err != OK) {
33725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        mDone = mReachedEOS = true;
33825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return err;
33925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
34020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
34120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_t attr;
34220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_init(&attr);
34320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
34420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
34520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = false;
34625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = false;
34720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
34825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    pthread_create(&mThread, &attr, ThreadWrapper, this);
34920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_destroy(&attr);
35025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
35125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
35220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
35320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
35420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::Track::stop() {
35520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mDone) {
35620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return;
35720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
35820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
35920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = true;
36020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
36120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *dummy;
36220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_join(mThread, &dummy);
36320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
36420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mSource->stop();
36520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
36620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
36725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() {
36825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return mReachedEOS;
36925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
37025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
37120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static
37220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) {
37320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = static_cast<Track *>(me);
37420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
37520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    track->threadEntry();
37620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
37720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return NULL;
37820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
37920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
38020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::Track::threadEntry() {
38120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MetaData> meta = mSource->getFormat();
38220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const char *mime;
38320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    meta->findCString(kKeyMIMEType, &mime);
38430ab66297501757d745b9ae10da61adcd891f497Andreas Huber    bool is_mpeg4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4);
38530ab66297501757d745b9ae10da61adcd891f497Andreas Huber    bool is_avc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
38630ab66297501757d745b9ae10da61adcd891f497Andreas Huber    int32_t count = 0;
38720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
38820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBuffer *buffer;
38920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (!mDone && mSource->read(&buffer) == OK) {
39020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (buffer->range_length() == 0) {
39120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer->release();
39220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer = NULL;
39320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
39420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            continue;
39520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
39620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
39730ab66297501757d745b9ae10da61adcd891f497Andreas Huber        ++count;
39830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
39930ab66297501757d745b9ae10da61adcd891f497Andreas Huber        if (is_avc && count < 3) {
40030ab66297501757d745b9ae10da61adcd891f497Andreas Huber            size_t size = buffer->range_length();
40130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
40230ab66297501757d745b9ae10da61adcd891f497Andreas Huber            switch (count) {
40330ab66297501757d745b9ae10da61adcd891f497Andreas Huber                case 1:
40430ab66297501757d745b9ae10da61adcd891f497Andreas Huber                {
40530ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    CHECK_EQ(mCodecSpecificData, NULL);
40630ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    mCodecSpecificData = malloc(size + 8);
40730ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    uint8_t *header = (uint8_t *)mCodecSpecificData;
40830ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    header[0] = 1;
40930ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    header[1] = 0x42;  // profile
41030ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    header[2] = 0x80;
41130ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    header[3] = 0x1e;  // level
41230ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    header[4] = 0xfc | 3;
41330ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    header[5] = 0xe0 | 1;
41430ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    header[6] = size >> 8;
41530ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    header[7] = size & 0xff;
41630ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    memcpy(&header[8],
41730ab66297501757d745b9ae10da61adcd891f497Andreas Huber                            (const uint8_t *)buffer->data() + buffer->range_offset(),
41830ab66297501757d745b9ae10da61adcd891f497Andreas Huber                            size);
41930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
42030ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    mCodecSpecificDataSize = size + 8;
42130ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    break;
42230ab66297501757d745b9ae10da61adcd891f497Andreas Huber                }
42330ab66297501757d745b9ae10da61adcd891f497Andreas Huber
42430ab66297501757d745b9ae10da61adcd891f497Andreas Huber                case 2:
42530ab66297501757d745b9ae10da61adcd891f497Andreas Huber                {
42630ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    size_t offset = mCodecSpecificDataSize;
42730ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    mCodecSpecificDataSize += size + 3;
42830ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    mCodecSpecificData = realloc(mCodecSpecificData, mCodecSpecificDataSize);
42930ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    uint8_t *header = (uint8_t *)mCodecSpecificData;
43030ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    header[offset] = 1;
43130ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    header[offset + 1] = size >> 8;
43230ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    header[offset + 2] = size & 0xff;
43330ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    memcpy(&header[offset + 3],
43430ab66297501757d745b9ae10da61adcd891f497Andreas Huber                            (const uint8_t *)buffer->data() + buffer->range_offset(),
43530ab66297501757d745b9ae10da61adcd891f497Andreas Huber                            size);
43630ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    break;
43730ab66297501757d745b9ae10da61adcd891f497Andreas Huber                }
43830ab66297501757d745b9ae10da61adcd891f497Andreas Huber            }
43930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
44030ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer->release();
44130ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer = NULL;
44230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
44330ab66297501757d745b9ae10da61adcd891f497Andreas Huber            continue;
44430ab66297501757d745b9ae10da61adcd891f497Andreas Huber        }
44530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
44620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (mCodecSpecificData == NULL && is_mpeg4) {
44720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            const uint8_t *data =
44820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                (const uint8_t *)buffer->data() + buffer->range_offset();
44920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
45020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            const size_t size = buffer->range_length();
45120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
45220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            size_t offset = 0;
45320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (offset + 3 < size) {
45420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (data[offset] == 0x00 && data[offset + 1] == 0x00
45520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    && data[offset + 2] == 0x01 && data[offset + 3] == 0xb6) {
45620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    break;
45720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
45820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
45920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                ++offset;
46020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
46120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4620c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber            // CHECK(offset + 3 < size);
463bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber            if (offset + 3 >= size) {
464bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber                // XXX assume the entire first chunk of data is the codec specific
465bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber                // data.
466bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber                offset = size;
467bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber            }
46820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
46920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mCodecSpecificDataSize = offset;
47020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mCodecSpecificData = malloc(offset);
47120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            memcpy(mCodecSpecificData, data, offset);
47220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
47320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer->set_range(buffer->range_offset() + offset, size - offset);
47420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
47520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
47630ab66297501757d745b9ae10da61adcd891f497Andreas Huber        off_t offset = is_avc ? mOwner->addLengthPrefixedSample(buffer)
47730ab66297501757d745b9ae10da61adcd891f497Andreas Huber                              : mOwner->addSample(buffer);
47820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
47920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        SampleInfo info;
48030ab66297501757d745b9ae10da61adcd891f497Andreas Huber        info.size = is_avc ? buffer->range_length() + 2 : buffer->range_length();
48120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        info.offset = offset;
48220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
48348c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        int64_t timestampUs;
48448c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        CHECK(buffer->meta_data()->findInt64(kKeyTime, &timestampUs));
48548c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber
48648c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        // Our timestamp is in ms.
48748c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        info.timestamp = (timestampUs + 500) / 1000;
48820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
48920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mSampleInfos.push_back(info);
49020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
49120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        buffer->release();
49220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        buffer = NULL;
49320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
49425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
49525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = true;
49620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
49720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
49820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberint64_t MPEG4Writer::Track::getDuration() const {
49920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return 10000;  // XXX
50020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
50120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
50220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::Track::writeTrackHeader(int32_t trackID) {
50320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const char *mime;
50420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool success = mMeta->findCString(kKeyMIMEType, &mime);
5050c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(success);
50620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
50720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool is_audio = !strncasecmp(mime, "audio/", 6);
50820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
50920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    time_t now = time(NULL);
51020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
51120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOwner->beginBox("trak");
51220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
51320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->beginBox("tkhd");
51420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);             // version=0, flags=0
51520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(now);           // creation time
51620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(now);           // modification time
51720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(trackID);
51820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);             // reserved
51920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(getDuration());
52020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);             // reserved
52120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);             // reserved
52220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt16(0);             // layer
52320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt16(0);             // alternate group
52420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt16(is_audio ? 0x100 : 0);  // volume
52520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt16(0);             // reserved
52620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
52720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0x10000);       // matrix
52820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
52920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
53020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
53120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0x10000);
53220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
53320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
53420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
53520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0x40000000);
53620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
53720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (is_audio) {
53820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);
53920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);
54020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        } else {
54120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            int32_t width, height;
54220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            bool success = mMeta->findInt32(kKeyWidth, &width);
54320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            success = success && mMeta->findInt32(kKeyHeight, &height);
5440c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber            CHECK(success);
54520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
54620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(width);
54720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(height);
54820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
54920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->endBox();  // tkhd
55020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
55120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->beginBox("mdia");
55220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
55320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("mdhd");
55420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // version=0, flags=0
55520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(now);           // creation time
55620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(now);           // modification time
55720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(1000);          // timescale
55820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(getDuration());
55920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt16(0);             // language code XXX
56020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt16(0);             // predefined
56120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->endBox();
56220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
56320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("hdlr");
56420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // version=0, flags=0
56520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // predefined
56620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeFourcc(is_audio ? "soun" : "vide");
56720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // reserved
56820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // reserved
56920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // reserved
57020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeCString("");          // name
57120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->endBox();
57220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
57320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("minf");
57420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
57520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("dinf");
57620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->beginBox("dref");
57720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt32(0);  // version=0, flags=0
57820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt32(1);
57920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->beginBox("url ");
58020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mOwner->writeInt32(1);  // version=0, flags=1
58120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->endBox();  // url
58220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->endBox();  // dref
58320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // dinf
58420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
58520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          if (is_audio) {
58620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->beginBox("smhd");
58720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt32(0);           // version=0, flags=0
58820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // balance
58920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // reserved
59020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->endBox();
59120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          } else {
59220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->beginBox("vmhd");
59320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt32(0x00000001);  // version=0, flags=1
59420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // graphics mode
59520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // opcolor
59620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);
59720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);
59820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->endBox();
59920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          }
60020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->endBox();  // minf
60120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
60220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("stbl");
60320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
60420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stsd");
60520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);               // version=0, flags=0
60620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(1);               // entry count
60720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (is_audio) {
60825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                const char *fourcc = NULL;
60918291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) {
61025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    fourcc = "samr";
61118291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
61225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    fourcc = "sawb";
61325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                } else {
61425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    LOGE("Unknown mime type '%s'.", mime);
61525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    CHECK(!"should not be here, unknown mime type.");
61625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                }
61725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
61825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                mOwner->beginBox(fourcc);          // audio format
61920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
62020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
62120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // data ref index
62220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
62320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
62420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(2);           // channel count
62520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(16);          // sample size
62620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // predefined
62720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
62820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
62920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  int32_t samplerate;
63020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  bool success = mMeta->findInt32(kKeySampleRate, &samplerate);
6310c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                  CHECK(success);
63220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
63320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(samplerate << 16);
63420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mOwner->endBox();
63520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
63618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
63720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    mOwner->beginBox("mp4v");
63818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
63920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    mOwner->beginBox("s263");
64030ab66297501757d745b9ae10da61adcd891f497Andreas Huber                } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
64130ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    mOwner->beginBox("avc1");
64220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                } else {
64325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    LOGE("Unknown mime type '%s'.", mime);
6440c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                    CHECK(!"should not be here, unknown mime type.");
64520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
64620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
64720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
64820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
64920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // data ref index
65020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // predefined
65120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
65220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // predefined
65320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // predefined
65420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // predefined
65520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
65620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  int32_t width, height;
65720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  bool success = mMeta->findInt32(kKeyWidth, &width);
65820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  success = success && mMeta->findInt32(kKeyHeight, &height);
6590c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                  CHECK(success);
66020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
66120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(width);
66220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(height);
66320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0x480000);    // horiz resolution
66420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0x480000);    // vert resolution
66520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
66620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(1);           // frame count
66720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->write("                                ", 32);
66820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0x18);        // depth
66920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(-1);          // predefined
67020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6710c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                  CHECK(23 + mCodecSpecificDataSize < 128);
67220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
67318291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                  if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
67420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->beginBox("esds");
67520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
67620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt32(0);           // version=0, flags=0
67720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
67820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x03);  // ES_DescrTag
67920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(23 + mCodecSpecificDataSize);
68020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt16(0x0000);  // ES_ID
68120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x1f);
68220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
68320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x04);  // DecoderConfigDescrTag
68420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(15 + mCodecSpecificDataSize);
68520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x20);  // objectTypeIndication ISO/IEC 14492-2
68620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x11);  // streamType VisualStream
68720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
68820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        static const uint8_t kData[] = {
68920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x01, 0x77, 0x00,
69020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x00, 0x03, 0xe8, 0x00,
69120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x00, 0x03, 0xe8, 0x00
69220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        };
69320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->write(kData, sizeof(kData));
69420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
69520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x05);  // DecoderSpecificInfoTag
69620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
69720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(mCodecSpecificDataSize);
69820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
69920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
70020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        static const uint8_t kData2[] = {
70120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x06,  // SLConfigDescriptorTag
70220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x01,
70320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x02
70420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        };
70520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->write(kData2, sizeof(kData2));
70620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
70720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->endBox();  // esds
70818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                  } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
70920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->beginBox("d263");
71020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
71120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt32(0);  // vendor
71220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt8(0);   // decoder version
71320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt8(10);  // level: 10
71420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt8(0);   // profile: 0
71520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
71620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->endBox();  // d263
71730ab66297501757d745b9ae10da61adcd891f497Andreas Huber                  } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
71830ab66297501757d745b9ae10da61adcd891f497Andreas Huber                      mOwner->beginBox("avcC");
71930ab66297501757d745b9ae10da61adcd891f497Andreas Huber                        mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
72030ab66297501757d745b9ae10da61adcd891f497Andreas Huber                      mOwner->endBox();  // avcC
72120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  }
72230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
72330ab66297501757d745b9ae10da61adcd891f497Andreas Huber                mOwner->endBox();  // mp4v, s263 or avc1
72420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
72520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stsd
72620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
72720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stts");
72820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
72920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(mSampleInfos.size() - 1);
73020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
73120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            List<SampleInfo>::iterator it = mSampleInfos.begin();
73220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            int64_t last = (*it).timestamp;
73320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            ++it;
73420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (it != mSampleInfos.end()) {
73520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mOwner->writeInt32(1);
73620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mOwner->writeInt32((*it).timestamp - last);
73720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
73820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                last = (*it).timestamp;
73920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
74020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                ++it;
74120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
74220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stts
74320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
74420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stsz");
74520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
74620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // default sample size
74720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(mSampleInfos.size());
74820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            for (List<SampleInfo>::iterator it = mSampleInfos.begin();
74920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                 it != mSampleInfos.end(); ++it) {
75020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mOwner->writeInt32((*it).size);
75120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
75220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stsz
75320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
75420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stsc");
75520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
75620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(mSampleInfos.size());
75720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            int32_t n = 1;
75820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            for (List<SampleInfo>::iterator it = mSampleInfos.begin();
75920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                 it != mSampleInfos.end(); ++it, ++n) {
76020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mOwner->writeInt32(n);
76120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mOwner->writeInt32(1);
76220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mOwner->writeInt32(1);
76320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
76420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stsc
76520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
76620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("co64");
76720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
76820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(mSampleInfos.size());
76920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            for (List<SampleInfo>::iterator it = mSampleInfos.begin();
77020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                 it != mSampleInfos.end(); ++it, ++n) {
77120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mOwner->writeInt64((*it).offset);
77220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
77320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // co64
77420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
77520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->endBox();  // stbl
77620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->endBox();  // mdia
77720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOwner->endBox();  // trak
77820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
77920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
78020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
781