MPEG4Writer.cpp revision 30ab66297501757d745b9ae10da61adcd891f497
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
9525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Hubervoid MPEG4Writer::addSource(const sp<MediaSource> &source) {
9625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    Track *track = new Track(this, source);
9720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.push_back(track);
9820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
9920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberstatus_t MPEG4Writer::start() {
10120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mFile == NULL) {
10225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return UNKNOWN_ERROR;
10320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
10420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    beginBox("ftyp");
10620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      writeFourcc("isom");
10720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      writeInt32(0);
10820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      writeFourcc("isom");
10920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    endBox();
11020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
11120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mMdatOffset = mOffset;
11220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    write("\x00\x00\x00\x01mdat????????", 16);
11320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
11420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
11520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber         it != mTracks.end(); ++it) {
11625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        status_t err = (*it)->start();
11725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
11825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        if (err != OK) {
11925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            for (List<Track *>::iterator it2 = mTracks.begin();
12025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                 it2 != it; ++it2) {
12125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                (*it2)->stop();
12225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            }
12325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
12425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            return err;
12525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        }
12620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
12725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
12825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
12920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
13020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
13120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::stop() {
13220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mFile == NULL) {
13320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return;
13420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
13520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
13620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int64_t max_duration = 0;
13720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
13820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber         it != mTracks.end(); ++it) {
13920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        (*it)->stop();
14020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        int64_t duration = (*it)->getDuration();
14220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (duration > max_duration) {
14320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            max_duration = duration;
14420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
14520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
14620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // Fix up the size of the 'mdat' chunk.
14820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fseek(mFile, mMdatOffset + 8, SEEK_SET);
14920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int64_t size = mOffset - mMdatOffset;
15020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size = hton64(size);
15120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fwrite(&size, 1, 8, mFile);
15220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fseek(mFile, mOffset, SEEK_SET);
15320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
15420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    time_t now = time(NULL);
15520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
15620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    beginBox("moov");
15720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
15820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      beginBox("mvhd");
15920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // version=0, flags=0
16020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(now);           // creation time
16120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(now);           // modification time
16220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(1000);          // timescale
16320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(max_duration);
16420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0x10000);       // rate
16520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt16(0x100);         // volume
16620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt16(0);             // reserved
16720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // reserved
16820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // reserved
16920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0x10000);       // matrix
17020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
17120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
17220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
17320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0x10000);
17420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
17520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
17620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
17720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0x40000000);
17820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
17920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
18020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
18120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
18220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
18320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
18420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(mTracks.size() + 1);  // nextTrackID
18520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      endBox();  // mvhd
18620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
18720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      int32_t id = 1;
18820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      for (List<Track *>::iterator it = mTracks.begin();
18920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber           it != mTracks.end(); ++it, ++id) {
19020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          (*it)->writeTrackHeader(id);
19120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      }
19220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    endBox();  // moov
19320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1940c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(mBoxes.empty());
19520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
19620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fclose(mFile);
19720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mFile = NULL;
19820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
19920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
20020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberoff_t MPEG4Writer::addSample(MediaBuffer *buffer) {
20120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Mutex::Autolock autoLock(mLock);
20220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
20320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    off_t old_offset = mOffset;
20420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
20520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fwrite((const uint8_t *)buffer->data() + buffer->range_offset(),
20620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber           1, buffer->range_length(), mFile);
20720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
20820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += buffer->range_length();
20920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
21020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return old_offset;
21120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
21220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
21330ab66297501757d745b9ae10da61adcd891f497Andreas Huberoff_t MPEG4Writer::addLengthPrefixedSample(MediaBuffer *buffer) {
21430ab66297501757d745b9ae10da61adcd891f497Andreas Huber    Mutex::Autolock autoLock(mLock);
21530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
21630ab66297501757d745b9ae10da61adcd891f497Andreas Huber    off_t old_offset = mOffset;
21730ab66297501757d745b9ae10da61adcd891f497Andreas Huber
21830ab66297501757d745b9ae10da61adcd891f497Andreas Huber    size_t length = buffer->range_length();
21930ab66297501757d745b9ae10da61adcd891f497Andreas Huber    CHECK(length < 65536);
22030ab66297501757d745b9ae10da61adcd891f497Andreas Huber
22130ab66297501757d745b9ae10da61adcd891f497Andreas Huber    uint8_t x = length >> 8;
22230ab66297501757d745b9ae10da61adcd891f497Andreas Huber    fwrite(&x, 1, 1, mFile);
22330ab66297501757d745b9ae10da61adcd891f497Andreas Huber    x = length & 0xff;
22430ab66297501757d745b9ae10da61adcd891f497Andreas Huber    fwrite(&x, 1, 1, mFile);
22530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
22630ab66297501757d745b9ae10da61adcd891f497Andreas Huber    fwrite((const uint8_t *)buffer->data() + buffer->range_offset(),
22730ab66297501757d745b9ae10da61adcd891f497Andreas Huber           1, length, mFile);
22830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
22930ab66297501757d745b9ae10da61adcd891f497Andreas Huber    mOffset += length + 2;
23030ab66297501757d745b9ae10da61adcd891f497Andreas Huber
23130ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return old_offset;
23230ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
23330ab66297501757d745b9ae10da61adcd891f497Andreas Huber
23420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) {
2350c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(fourcc), 4);
23620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
23720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mBoxes.push_back(mOffset);
23820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
23920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeInt32(0);
24020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeFourcc(fourcc);
24120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
24220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
24320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() {
2440c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(!mBoxes.empty());
24520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
24620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    off_t offset = *--mBoxes.end();
24720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mBoxes.erase(--mBoxes.end());
24820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
24920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fseek(mFile, offset, SEEK_SET);
25020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeInt32(mOffset - offset);
25120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset -= 4;
25220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fseek(mFile, mOffset, SEEK_SET);
25320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
25420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
25520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) {
25620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fwrite(&x, 1, 1, mFile);
25720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    ++mOffset;
25820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
25920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
26020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) {
26120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htons(x);
26220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fwrite(&x, 1, 2, mFile);
26320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += 2;
26420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
26520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
26620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) {
26720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htonl(x);
26820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fwrite(&x, 1, 4, mFile);
26920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += 4;
27020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
27120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
27220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) {
27320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = hton64(x);
27420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fwrite(&x, 1, 8, mFile);
27520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += 8;
27620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
27720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
27820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) {
27920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t n = strlen(s);
28020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
28120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fwrite(s, 1, n + 1, mFile);
28220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += n + 1;
28320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
28420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
28520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) {
2860c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(s), 4);
28720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fwrite(s, 1, 4, mFile);
28820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += 4;
28920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
29020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
29120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) {
29220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fwrite(data, 1, size, mFile);
29320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += size;
29420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
29520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
29625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() {
29725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool allDone = true;
29825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
29925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber         it != mTracks.end(); ++it) {
30025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        if (!(*it)->reachedEOS()) {
30125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            allDone = false;
30225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            break;
30325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        }
30425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
30525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
30625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return allDone;
30725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
30825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
30920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
31020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
31120111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track(
31225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        MPEG4Writer *owner, const sp<MediaSource> &source)
31320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mOwner(owner),
31425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mMeta(source->getFormat()),
31520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSource(source),
31620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDone(false),
31720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCodecSpecificData(NULL),
31825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mCodecSpecificDataSize(0),
31925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mReachedEOS(false) {
32020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
32120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
32220111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() {
32320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    stop();
32420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
32520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mCodecSpecificData != NULL) {
32620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        free(mCodecSpecificData);
32720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mCodecSpecificData = NULL;
32820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
32920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
33020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
33125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberstatus_t MPEG4Writer::Track::start() {
33225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    status_t err = mSource->start();
33325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
33425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    if (err != OK) {
33525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        mDone = mReachedEOS = true;
33625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return err;
33725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
33820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
33920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_t attr;
34020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_init(&attr);
34120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
34220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
34320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = false;
34425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = false;
34520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
34625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    pthread_create(&mThread, &attr, ThreadWrapper, this);
34720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_destroy(&attr);
34825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
34925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
35020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
35120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
35220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::Track::stop() {
35320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mDone) {
35420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return;
35520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
35620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
35720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = true;
35820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
35920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *dummy;
36020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_join(mThread, &dummy);
36120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
36220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mSource->stop();
36320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
36420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
36525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() {
36625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return mReachedEOS;
36725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
36825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
36920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static
37020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) {
37120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = static_cast<Track *>(me);
37220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
37320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    track->threadEntry();
37420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
37520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return NULL;
37620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
37720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
37820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::Track::threadEntry() {
37920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MetaData> meta = mSource->getFormat();
38020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const char *mime;
38120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    meta->findCString(kKeyMIMEType, &mime);
38230ab66297501757d745b9ae10da61adcd891f497Andreas Huber    bool is_mpeg4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4);
38330ab66297501757d745b9ae10da61adcd891f497Andreas Huber    bool is_avc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
38430ab66297501757d745b9ae10da61adcd891f497Andreas Huber    int32_t count = 0;
38520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
38620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBuffer *buffer;
38720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (!mDone && mSource->read(&buffer) == OK) {
38820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (buffer->range_length() == 0) {
38920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer->release();
39020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer = NULL;
39120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
39220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            continue;
39320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
39420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
39530ab66297501757d745b9ae10da61adcd891f497Andreas Huber        ++count;
39630ab66297501757d745b9ae10da61adcd891f497Andreas Huber
39730ab66297501757d745b9ae10da61adcd891f497Andreas Huber        if (is_avc && count < 3) {
39830ab66297501757d745b9ae10da61adcd891f497Andreas Huber            size_t size = buffer->range_length();
39930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
40030ab66297501757d745b9ae10da61adcd891f497Andreas Huber            switch (count) {
40130ab66297501757d745b9ae10da61adcd891f497Andreas Huber                case 1:
40230ab66297501757d745b9ae10da61adcd891f497Andreas Huber                {
40330ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    CHECK_EQ(mCodecSpecificData, NULL);
40430ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    mCodecSpecificData = malloc(size + 8);
40530ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    uint8_t *header = (uint8_t *)mCodecSpecificData;
40630ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    header[0] = 1;
40730ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    header[1] = 0x42;  // profile
40830ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    header[2] = 0x80;
40930ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    header[3] = 0x1e;  // level
41030ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    header[4] = 0xfc | 3;
41130ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    header[5] = 0xe0 | 1;
41230ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    header[6] = size >> 8;
41330ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    header[7] = size & 0xff;
41430ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    memcpy(&header[8],
41530ab66297501757d745b9ae10da61adcd891f497Andreas Huber                            (const uint8_t *)buffer->data() + buffer->range_offset(),
41630ab66297501757d745b9ae10da61adcd891f497Andreas Huber                            size);
41730ab66297501757d745b9ae10da61adcd891f497Andreas Huber
41830ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    mCodecSpecificDataSize = size + 8;
41930ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    break;
42030ab66297501757d745b9ae10da61adcd891f497Andreas Huber                }
42130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
42230ab66297501757d745b9ae10da61adcd891f497Andreas Huber                case 2:
42330ab66297501757d745b9ae10da61adcd891f497Andreas Huber                {
42430ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    size_t offset = mCodecSpecificDataSize;
42530ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    mCodecSpecificDataSize += size + 3;
42630ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    mCodecSpecificData = realloc(mCodecSpecificData, mCodecSpecificDataSize);
42730ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    uint8_t *header = (uint8_t *)mCodecSpecificData;
42830ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    header[offset] = 1;
42930ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    header[offset + 1] = size >> 8;
43030ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    header[offset + 2] = size & 0xff;
43130ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    memcpy(&header[offset + 3],
43230ab66297501757d745b9ae10da61adcd891f497Andreas Huber                            (const uint8_t *)buffer->data() + buffer->range_offset(),
43330ab66297501757d745b9ae10da61adcd891f497Andreas Huber                            size);
43430ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    break;
43530ab66297501757d745b9ae10da61adcd891f497Andreas Huber                }
43630ab66297501757d745b9ae10da61adcd891f497Andreas Huber            }
43730ab66297501757d745b9ae10da61adcd891f497Andreas Huber
43830ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer->release();
43930ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer = NULL;
44030ab66297501757d745b9ae10da61adcd891f497Andreas Huber
44130ab66297501757d745b9ae10da61adcd891f497Andreas Huber            continue;
44230ab66297501757d745b9ae10da61adcd891f497Andreas Huber        }
44330ab66297501757d745b9ae10da61adcd891f497Andreas Huber
44420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (mCodecSpecificData == NULL && is_mpeg4) {
44520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            const uint8_t *data =
44620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                (const uint8_t *)buffer->data() + buffer->range_offset();
44720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
44820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            const size_t size = buffer->range_length();
44920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
45020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            size_t offset = 0;
45120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (offset + 3 < size) {
45220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (data[offset] == 0x00 && data[offset + 1] == 0x00
45320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    && data[offset + 2] == 0x01 && data[offset + 3] == 0xb6) {
45420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    break;
45520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
45620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
45720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                ++offset;
45820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
45920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4600c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber            // CHECK(offset + 3 < size);
461bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber            if (offset + 3 >= size) {
462bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber                // XXX assume the entire first chunk of data is the codec specific
463bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber                // data.
464bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber                offset = size;
465bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber            }
46620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
46720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mCodecSpecificDataSize = offset;
46820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mCodecSpecificData = malloc(offset);
46920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            memcpy(mCodecSpecificData, data, offset);
47020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
47120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer->set_range(buffer->range_offset() + offset, size - offset);
47220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
47320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
47430ab66297501757d745b9ae10da61adcd891f497Andreas Huber        off_t offset = is_avc ? mOwner->addLengthPrefixedSample(buffer)
47530ab66297501757d745b9ae10da61adcd891f497Andreas Huber                              : mOwner->addSample(buffer);
47620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
47720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        SampleInfo info;
47830ab66297501757d745b9ae10da61adcd891f497Andreas Huber        info.size = is_avc ? buffer->range_length() + 2 : buffer->range_length();
47920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        info.offset = offset;
48020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
48148c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        int64_t timestampUs;
48248c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        CHECK(buffer->meta_data()->findInt64(kKeyTime, &timestampUs));
48348c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber
48448c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        // Our timestamp is in ms.
48548c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        info.timestamp = (timestampUs + 500) / 1000;
48620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
48720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mSampleInfos.push_back(info);
48820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
48920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        buffer->release();
49020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        buffer = NULL;
49120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
49225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
49325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = true;
49420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
49520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
49620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberint64_t MPEG4Writer::Track::getDuration() const {
49720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return 10000;  // XXX
49820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
49920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
50020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::Track::writeTrackHeader(int32_t trackID) {
50120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const char *mime;
50220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool success = mMeta->findCString(kKeyMIMEType, &mime);
5030c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(success);
50420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
50520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool is_audio = !strncasecmp(mime, "audio/", 6);
50620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
50720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    time_t now = time(NULL);
50820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
50920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOwner->beginBox("trak");
51020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
51120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->beginBox("tkhd");
51220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);             // version=0, flags=0
51320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(now);           // creation time
51420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(now);           // modification time
51520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(trackID);
51620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);             // reserved
51720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(getDuration());
51820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);             // reserved
51920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);             // reserved
52020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt16(0);             // layer
52120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt16(0);             // alternate group
52220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt16(is_audio ? 0x100 : 0);  // volume
52320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt16(0);             // reserved
52420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
52520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0x10000);       // matrix
52620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
52720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
52820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
52920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0x10000);
53020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
53120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
53220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
53320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0x40000000);
53420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
53520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (is_audio) {
53620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);
53720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);
53820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        } else {
53920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            int32_t width, height;
54020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            bool success = mMeta->findInt32(kKeyWidth, &width);
54120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            success = success && mMeta->findInt32(kKeyHeight, &height);
5420c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber            CHECK(success);
54320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
54420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(width);
54520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(height);
54620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
54720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->endBox();  // tkhd
54820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
54920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->beginBox("mdia");
55020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
55120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("mdhd");
55220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // version=0, flags=0
55320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(now);           // creation time
55420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(now);           // modification time
55520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(1000);          // timescale
55620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(getDuration());
55720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt16(0);             // language code XXX
55820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt16(0);             // predefined
55920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->endBox();
56020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
56120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("hdlr");
56220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // version=0, flags=0
56320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // predefined
56420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeFourcc(is_audio ? "soun" : "vide");
56520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // reserved
56620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // reserved
56720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // reserved
56820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeCString("");          // name
56920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->endBox();
57020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
57120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("minf");
57220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
57320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("dinf");
57420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->beginBox("dref");
57520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt32(0);  // version=0, flags=0
57620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt32(1);
57720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->beginBox("url ");
57820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mOwner->writeInt32(1);  // version=0, flags=1
57920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->endBox();  // url
58020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->endBox();  // dref
58120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // dinf
58220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
58320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          if (is_audio) {
58420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->beginBox("smhd");
58520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt32(0);           // version=0, flags=0
58620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // balance
58720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // reserved
58820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->endBox();
58920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          } else {
59020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->beginBox("vmhd");
59120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt32(0x00000001);  // version=0, flags=1
59220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // graphics mode
59320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // opcolor
59420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);
59520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);
59620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->endBox();
59720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          }
59820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->endBox();  // minf
59920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
60020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("stbl");
60120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
60220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stsd");
60320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);               // version=0, flags=0
60420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(1);               // entry count
60520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (is_audio) {
60625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                const char *fourcc = NULL;
60718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) {
60825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    fourcc = "samr";
60918291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
61025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    fourcc = "sawb";
61125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                } else {
61225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    LOGE("Unknown mime type '%s'.", mime);
61325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    CHECK(!"should not be here, unknown mime type.");
61425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                }
61525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
61625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                mOwner->beginBox(fourcc);          // audio format
61720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
61820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
61920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // data ref index
62020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
62120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
62220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(2);           // channel count
62320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(16);          // sample size
62420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // predefined
62520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
62620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
62720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  int32_t samplerate;
62820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  bool success = mMeta->findInt32(kKeySampleRate, &samplerate);
6290c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                  CHECK(success);
63020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
63120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(samplerate << 16);
63220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mOwner->endBox();
63320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
63418291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
63520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    mOwner->beginBox("mp4v");
63618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
63720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    mOwner->beginBox("s263");
63830ab66297501757d745b9ae10da61adcd891f497Andreas Huber                } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
63930ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    mOwner->beginBox("avc1");
64020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                } else {
64125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    LOGE("Unknown mime type '%s'.", mime);
6420c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                    CHECK(!"should not be here, unknown mime type.");
64320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
64420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
64520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
64620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
64720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // data ref index
64820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // predefined
64920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
65020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // predefined
65120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // predefined
65220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // predefined
65320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
65420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  int32_t width, height;
65520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  bool success = mMeta->findInt32(kKeyWidth, &width);
65620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  success = success && mMeta->findInt32(kKeyHeight, &height);
6570c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                  CHECK(success);
65820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
65920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(width);
66020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(height);
66120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0x480000);    // horiz resolution
66220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0x480000);    // vert resolution
66320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
66420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(1);           // frame count
66520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->write("                                ", 32);
66620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0x18);        // depth
66720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(-1);          // predefined
66820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6690c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                  CHECK(23 + mCodecSpecificDataSize < 128);
67020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
67118291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                  if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
67220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->beginBox("esds");
67320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
67420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt32(0);           // version=0, flags=0
67520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
67620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x03);  // ES_DescrTag
67720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(23 + mCodecSpecificDataSize);
67820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt16(0x0000);  // ES_ID
67920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x1f);
68020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
68120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x04);  // DecoderConfigDescrTag
68220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(15 + mCodecSpecificDataSize);
68320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x20);  // objectTypeIndication ISO/IEC 14492-2
68420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x11);  // streamType VisualStream
68520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
68620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        static const uint8_t kData[] = {
68720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x01, 0x77, 0x00,
68820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x00, 0x03, 0xe8, 0x00,
68920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x00, 0x03, 0xe8, 0x00
69020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        };
69120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->write(kData, sizeof(kData));
69220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
69320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x05);  // DecoderSpecificInfoTag
69420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
69520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(mCodecSpecificDataSize);
69620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
69720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
69820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        static const uint8_t kData2[] = {
69920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x06,  // SLConfigDescriptorTag
70020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x01,
70120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x02
70220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        };
70320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->write(kData2, sizeof(kData2));
70420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
70520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->endBox();  // esds
70618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                  } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
70720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->beginBox("d263");
70820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
70920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt32(0);  // vendor
71020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt8(0);   // decoder version
71120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt8(10);  // level: 10
71220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt8(0);   // profile: 0
71320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
71420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->endBox();  // d263
71530ab66297501757d745b9ae10da61adcd891f497Andreas Huber                  } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
71630ab66297501757d745b9ae10da61adcd891f497Andreas Huber                      mOwner->beginBox("avcC");
71730ab66297501757d745b9ae10da61adcd891f497Andreas Huber                        mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
71830ab66297501757d745b9ae10da61adcd891f497Andreas Huber                      mOwner->endBox();  // avcC
71920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  }
72030ab66297501757d745b9ae10da61adcd891f497Andreas Huber
72130ab66297501757d745b9ae10da61adcd891f497Andreas Huber                mOwner->endBox();  // mp4v, s263 or avc1
72220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
72320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stsd
72420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
72520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stts");
72620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
72720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(mSampleInfos.size() - 1);
72820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
72920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            List<SampleInfo>::iterator it = mSampleInfos.begin();
73020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            int64_t last = (*it).timestamp;
73120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            ++it;
73220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (it != mSampleInfos.end()) {
73320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mOwner->writeInt32(1);
73420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mOwner->writeInt32((*it).timestamp - last);
73520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
73620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                last = (*it).timestamp;
73720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
73820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                ++it;
73920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
74020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stts
74120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
74220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stsz");
74320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
74420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // default sample size
74520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(mSampleInfos.size());
74620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            for (List<SampleInfo>::iterator it = mSampleInfos.begin();
74720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                 it != mSampleInfos.end(); ++it) {
74820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mOwner->writeInt32((*it).size);
74920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
75020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stsz
75120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
75220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stsc");
75320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
75420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(mSampleInfos.size());
75520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            int32_t n = 1;
75620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            for (List<SampleInfo>::iterator it = mSampleInfos.begin();
75720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                 it != mSampleInfos.end(); ++it, ++n) {
75820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mOwner->writeInt32(n);
75920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mOwner->writeInt32(1);
76020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mOwner->writeInt32(1);
76120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
76220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stsc
76320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
76420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("co64");
76520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
76620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(mSampleInfos.size());
76720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            for (List<SampleInfo>::iterator it = mSampleInfos.begin();
76820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                 it != mSampleInfos.end(); ++it, ++n) {
76920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mOwner->writeInt64((*it).offset);
77020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
77120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // co64
77220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
77320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->endBox();  // stbl
77420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->endBox();  // mdia
77520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOwner->endBox();  // trak
77620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
77720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
77820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
779