MPEG4Writer.cpp revision 050b28a593350047845a45a14cc5026221ac1620
120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber/*
220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Copyright (C) 2009 The Android Open Source Project
320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * you may not use this file except in compliance with the License.
620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * You may obtain a copy of the License at
720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
1020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Unless required by applicable law or agreed to in writing, software
1120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
1220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * See the License for the specific language governing permissions and
1420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * limitations under the License.
1520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber */
1620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
17050b28a593350047845a45a14cc5026221ac1620James Dong//#define LOG_NDEBUG 0
18050b28a593350047845a45a14cc5026221ac1620James Dong#define LOG_TAG "MPEG4Writer"
19050b28a593350047845a45a14cc5026221ac1620James Dong#include <utils/Log.h>
20050b28a593350047845a45a14cc5026221ac1620James Dong
2120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <arpa/inet.h>
2220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <ctype.h>
2420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <pthread.h>
2520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MPEG4Writer.h>
2720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBuffer.h>
2820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h>
290c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber#include <media/stagefright/MediaDebug.h>
3018291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h>
3103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#include <media/stagefright/MediaErrors.h>
3220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaSource.h>
3320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/Utils.h>
3420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android {
3620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Writer::Track {
3820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic:
3925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    Track(MPEG4Writer *owner, const sp<MediaSource> &source);
4020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    ~Track();
4120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    status_t start();
4320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void stop();
4425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool reachedEOS();
4520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
463b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber    int64_t getDurationUs() const;
4720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void writeTrackHeader(int32_t trackID);
4820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate:
5020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Writer *mOwner;
5120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MetaData> mMeta;
52693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    sp<MediaSource> mSource;
5320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    volatile bool mDone;
543b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber    int64_t mMaxTimeStampUs;
5520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_t mThread;
5720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    struct SampleInfo {
5920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        size_t size;
6020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        off_t offset;
6120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        int64_t timestamp;
6220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    };
6320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    List<SampleInfo> mSampleInfos;
6420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
65050b28a593350047845a45a14cc5026221ac1620James Dong    List<int32_t> mStssTableEntries;
66050b28a593350047845a45a14cc5026221ac1620James Dong
6720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *mCodecSpecificData;
6820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t mCodecSpecificDataSize;
69548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    bool mGotAllCodecSpecificData;
7020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool mReachedEOS;
7225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
7320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    static void *ThreadWrapper(void *me);
7420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void threadEntry();
7520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    status_t makeAVCCodecSpecificData(
7703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            const uint8_t *data, size_t size);
7803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
7920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track(const Track &);
8020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track &operator=(const Track &);
8120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
8220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#define USE_NALLEN_FOUR         1
8403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
8520111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::MPEG4Writer(const char *filename)
8620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mFile(fopen(filename, "wb")),
8720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOffset(0),
8820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mMdatOffset(0) {
890c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(mFile != NULL);
9020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
9120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9230ab66297501757d745b9ae10da61adcd891f497Andreas HuberMPEG4Writer::MPEG4Writer(int fd)
9330ab66297501757d745b9ae10da61adcd891f497Andreas Huber    : mFile(fdopen(fd, "wb")),
9430ab66297501757d745b9ae10da61adcd891f497Andreas Huber      mOffset(0),
9530ab66297501757d745b9ae10da61adcd891f497Andreas Huber      mMdatOffset(0) {
9630ab66297501757d745b9ae10da61adcd891f497Andreas Huber    CHECK(mFile != NULL);
9730ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
9830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
9920111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() {
10020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    stop();
10120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
10320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber         it != mTracks.end(); ++it) {
10420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        delete *it;
10520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
10620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.clear();
10720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
10820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1092dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huberstatus_t MPEG4Writer::addSource(const sp<MediaSource> &source) {
11025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    Track *track = new Track(this, source);
11120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.push_back(track);
1122dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
1132dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    return OK;
11420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
11520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
11625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberstatus_t MPEG4Writer::start() {
11720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mFile == NULL) {
11825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return UNKNOWN_ERROR;
11920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
12020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    beginBox("ftyp");
12220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      writeFourcc("isom");
12320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      writeInt32(0);
12420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      writeFourcc("isom");
12520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    endBox();
12620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mMdatOffset = mOffset;
12820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    write("\x00\x00\x00\x01mdat????????", 16);
12920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
13020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
13120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber         it != mTracks.end(); ++it) {
13225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        status_t err = (*it)->start();
13325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
13425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        if (err != OK) {
13525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            for (List<Track *>::iterator it2 = mTracks.begin();
13625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                 it2 != it; ++it2) {
13725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                (*it2)->stop();
13825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            }
13925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
14025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            return err;
14125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        }
14220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
14325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
14425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
14520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
14620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::stop() {
14820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mFile == NULL) {
14920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return;
15020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
15120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
15220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int64_t max_duration = 0;
15320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
15420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber         it != mTracks.end(); ++it) {
15520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        (*it)->stop();
15620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1573b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber        int64_t duration = (*it)->getDurationUs();
15820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (duration > max_duration) {
15920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            max_duration = duration;
16020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
16120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
16220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
16320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // Fix up the size of the 'mdat' chunk.
16420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fseek(mFile, mMdatOffset + 8, SEEK_SET);
16520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int64_t size = mOffset - mMdatOffset;
16620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size = hton64(size);
16720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fwrite(&size, 1, 8, mFile);
16820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fseek(mFile, mOffset, SEEK_SET);
16920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
17020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    time_t now = time(NULL);
17120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
17220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    beginBox("moov");
17320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
17420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      beginBox("mvhd");
17520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // version=0, flags=0
17620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(now);           // creation time
17720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(now);           // modification time
17820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(1000);          // timescale
1793b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber        writeInt32(max_duration / 1000);
18020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0x10000);       // rate
18120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt16(0x100);         // volume
18220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt16(0);             // reserved
18320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // reserved
18420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // reserved
18520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0x10000);       // matrix
18620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
18720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
18820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
18920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0x10000);
19020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
19120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
19220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
19320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0x40000000);
19420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
19520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
19620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
19720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
19820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
19920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
20020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(mTracks.size() + 1);  // nextTrackID
20120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      endBox();  // mvhd
20220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
20320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      int32_t id = 1;
20420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      for (List<Track *>::iterator it = mTracks.begin();
20520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber           it != mTracks.end(); ++it, ++id) {
20620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          (*it)->writeTrackHeader(id);
20720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      }
20820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    endBox();  // moov
20920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2100c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(mBoxes.empty());
21120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
21220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fclose(mFile);
21320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mFile = NULL;
21420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
21520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
21620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberoff_t MPEG4Writer::addSample(MediaBuffer *buffer) {
21720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Mutex::Autolock autoLock(mLock);
21820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
21920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    off_t old_offset = mOffset;
22020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
22120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fwrite((const uint8_t *)buffer->data() + buffer->range_offset(),
22220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber           1, buffer->range_length(), mFile);
22320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
22420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += buffer->range_length();
22520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
22620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return old_offset;
22720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
22820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
22903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) {
23003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (buffer->range_length() < 4) {
23103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return;
23203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
23303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
23403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    const uint8_t *ptr =
23503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        (const uint8_t *)buffer->data() + buffer->range_offset();
23603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
23703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) {
23803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        buffer->set_range(
23903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                buffer->range_offset() + 4, buffer->range_length() - 4);
24003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
24103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
24203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
24330ab66297501757d745b9ae10da61adcd891f497Andreas Huberoff_t MPEG4Writer::addLengthPrefixedSample(MediaBuffer *buffer) {
24430ab66297501757d745b9ae10da61adcd891f497Andreas Huber    Mutex::Autolock autoLock(mLock);
24530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
24603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    StripStartcode(buffer);
24703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
24830ab66297501757d745b9ae10da61adcd891f497Andreas Huber    off_t old_offset = mOffset;
24930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
25030ab66297501757d745b9ae10da61adcd891f497Andreas Huber    size_t length = buffer->range_length();
25103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
25203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR
25303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    uint8_t x = length >> 24;
25403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    fwrite(&x, 1, 1, mFile);
25503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    x = (length >> 16) & 0xff;
25603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    fwrite(&x, 1, 1, mFile);
25703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    x = (length >> 8) & 0xff;
25803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    fwrite(&x, 1, 1, mFile);
25903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    x = length & 0xff;
26003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    fwrite(&x, 1, 1, mFile);
26103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else
26230ab66297501757d745b9ae10da61adcd891f497Andreas Huber    CHECK(length < 65536);
26330ab66297501757d745b9ae10da61adcd891f497Andreas Huber
26430ab66297501757d745b9ae10da61adcd891f497Andreas Huber    uint8_t x = length >> 8;
26530ab66297501757d745b9ae10da61adcd891f497Andreas Huber    fwrite(&x, 1, 1, mFile);
26630ab66297501757d745b9ae10da61adcd891f497Andreas Huber    x = length & 0xff;
26730ab66297501757d745b9ae10da61adcd891f497Andreas Huber    fwrite(&x, 1, 1, mFile);
26803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif
26930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
27030ab66297501757d745b9ae10da61adcd891f497Andreas Huber    fwrite((const uint8_t *)buffer->data() + buffer->range_offset(),
27130ab66297501757d745b9ae10da61adcd891f497Andreas Huber           1, length, mFile);
27230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
27303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR
27403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    mOffset += length + 4;
27503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else
27630ab66297501757d745b9ae10da61adcd891f497Andreas Huber    mOffset += length + 2;
27703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif
27830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
27930ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return old_offset;
28030ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
28130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
28220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) {
2830c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(fourcc), 4);
28420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
28520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mBoxes.push_back(mOffset);
28620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
28720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeInt32(0);
28820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeFourcc(fourcc);
28920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
29020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
29120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() {
2920c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(!mBoxes.empty());
29320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
29420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    off_t offset = *--mBoxes.end();
29520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mBoxes.erase(--mBoxes.end());
29620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
29720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fseek(mFile, offset, SEEK_SET);
29820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeInt32(mOffset - offset);
29920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset -= 4;
30020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fseek(mFile, mOffset, SEEK_SET);
30120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
30220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
30320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) {
30420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fwrite(&x, 1, 1, mFile);
30520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    ++mOffset;
30620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
30720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
30820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) {
30920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htons(x);
31020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fwrite(&x, 1, 2, mFile);
31120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += 2;
31220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
31320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
31420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) {
31520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htonl(x);
31620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fwrite(&x, 1, 4, mFile);
31720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += 4;
31820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
31920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
32020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) {
32120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = hton64(x);
32220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fwrite(&x, 1, 8, mFile);
32320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += 8;
32420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
32520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
32620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) {
32720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t n = strlen(s);
32820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
32920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fwrite(s, 1, n + 1, mFile);
33020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += n + 1;
33120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
33220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
33320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) {
3340c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(s), 4);
33520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fwrite(s, 1, 4, mFile);
33620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += 4;
33720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
33820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
33920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) {
34020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fwrite(data, 1, size, mFile);
34120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += size;
34220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
34320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
34425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() {
34525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool allDone = true;
34625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
34725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber         it != mTracks.end(); ++it) {
34825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        if (!(*it)->reachedEOS()) {
34925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            allDone = false;
35025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            break;
35125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        }
35225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
35325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
35425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return allDone;
35525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
35625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
35720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
35820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
35920111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track(
36025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        MPEG4Writer *owner, const sp<MediaSource> &source)
36120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mOwner(owner),
36225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mMeta(source->getFormat()),
36320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSource(source),
36420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDone(false),
3653b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber      mMaxTimeStampUs(0),
36620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCodecSpecificData(NULL),
36725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mCodecSpecificDataSize(0),
368548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber      mGotAllCodecSpecificData(false),
36925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mReachedEOS(false) {
37020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
37120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
37220111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() {
37320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    stop();
37420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
37520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mCodecSpecificData != NULL) {
37620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        free(mCodecSpecificData);
37720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mCodecSpecificData = NULL;
37820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
37920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
38020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
38125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberstatus_t MPEG4Writer::Track::start() {
38225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    status_t err = mSource->start();
38325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
38425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    if (err != OK) {
38525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        mDone = mReachedEOS = true;
38625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return err;
38725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
38820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
38920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_t attr;
39020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_init(&attr);
39120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
39220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
39320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = false;
3943b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber    mMaxTimeStampUs = 0;
39525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = false;
39620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
39725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    pthread_create(&mThread, &attr, ThreadWrapper, this);
39820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_destroy(&attr);
39925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
40025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
40120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
40220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
40320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::Track::stop() {
40420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mDone) {
40520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return;
40620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
40720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
40820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = true;
40920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
41020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *dummy;
41120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_join(mThread, &dummy);
41220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
41320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mSource->stop();
41420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
41520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
41625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() {
41725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return mReachedEOS;
41825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
41925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
42020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static
42120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) {
42220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = static_cast<Track *>(me);
42320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
42420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    track->threadEntry();
42520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
42620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return NULL;
42720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
42820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
429548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber#include <ctype.h>
430548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huberstatic void hexdump(const void *_data, size_t size) {
431548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    const uint8_t *data = (const uint8_t *)_data;
432548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    size_t offset = 0;
433548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    while (offset < size) {
434548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        printf("0x%04x  ", offset);
435548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
436548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        size_t n = size - offset;
437548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        if (n > 16) {
438548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            n = 16;
439548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        }
440548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
441548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        for (size_t i = 0; i < 16; ++i) {
442548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            if (i == 8) {
443548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber                printf(" ");
444548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            }
445548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
446548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            if (offset + i < size) {
447548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber                printf("%02x ", data[offset + i]);
448548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            } else {
449548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber                printf("   ");
450548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            }
451548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        }
452548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
453548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        printf(" ");
454548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
455548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        for (size_t i = 0; i < n; ++i) {
456548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            if (isprint(data[offset + i])) {
457548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber                printf("%c", data[offset + i]);
458548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            } else {
459548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber                printf(".");
460548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            }
461548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        }
462548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
463548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        printf("\n");
464548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
465548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        offset += 16;
466548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    }
467548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber}
468548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
469548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
47003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData(
47103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        const uint8_t *data, size_t size) {
472548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    // hexdump(data, size);
473548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
47403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (mCodecSpecificData != NULL) {
475548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        LOGE("Already have codec specific data");
47603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
47703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
47803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
47903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (size < 4 || memcmp("\x00\x00\x00\x01", data, 4)) {
480548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        LOGE("Must start with a start code");
48103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
48203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
48303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
48403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    size_t picParamOffset = 4;
48503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    while (picParamOffset + 3 < size
48603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            && memcmp("\x00\x00\x00\x01", &data[picParamOffset], 4)) {
48703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        ++picParamOffset;
48803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
48903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
49003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (picParamOffset + 3 >= size) {
491548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        LOGE("Could not find start-code for pictureParameterSet");
49203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
49303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
49403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
49503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    size_t seqParamSetLength = picParamOffset - 4;
49603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    size_t picParamSetLength = size - picParamOffset - 4;
49703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
49803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    mCodecSpecificDataSize =
49903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        6 + 1 + seqParamSetLength + 2 + picParamSetLength + 2;
50003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
50103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    mCodecSpecificData = malloc(mCodecSpecificDataSize);
50203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    uint8_t *header = (uint8_t *)mCodecSpecificData;
50303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[0] = 1;
50403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[1] = 0x42;  // profile
50503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[2] = 0x80;
50603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[3] = 0x1e;  // level
50703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
50803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR
50903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[4] = 0xfc | 3;  // length size == 4 bytes
51003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else
51103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[4] = 0xfc | 1;  // length size == 2 bytes
51203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif
51303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
51403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[5] = 0xe0 | 1;
51503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[6] = seqParamSetLength >> 8;
51603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[7] = seqParamSetLength & 0xff;
51703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    memcpy(&header[8], &data[4], seqParamSetLength);
51803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header += 8 + seqParamSetLength;
51903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[0] = 1;
52003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[1] = picParamSetLength >> 8;
52103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[2] = picParamSetLength & 0xff;
52203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    memcpy(&header[3], &data[picParamOffset + 4], picParamSetLength);
52303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
52403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    return OK;
52503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
52603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
52720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::Track::threadEntry() {
52820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MetaData> meta = mSource->getFormat();
52920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const char *mime;
53020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    meta->findCString(kKeyMIMEType, &mime);
531050b28a593350047845a45a14cc5026221ac1620James Dong    bool is_mpeg4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
532050b28a593350047845a45a14cc5026221ac1620James Dong                    !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC);
53330ab66297501757d745b9ae10da61adcd891f497Andreas Huber    bool is_avc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
53430ab66297501757d745b9ae10da61adcd891f497Andreas Huber    int32_t count = 0;
53520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
53620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBuffer *buffer;
53720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (!mDone && mSource->read(&buffer) == OK) {
53820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (buffer->range_length() == 0) {
53920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer->release();
54020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer = NULL;
54120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
54220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            continue;
54320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
54420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
54530ab66297501757d745b9ae10da61adcd891f497Andreas Huber        ++count;
54630ab66297501757d745b9ae10da61adcd891f497Andreas Huber
54703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        int32_t isCodecConfig;
54803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig)
54903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                && isCodecConfig) {
550548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            CHECK(!mGotAllCodecSpecificData);
551548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
55203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            if (is_avc) {
55303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                status_t err = makeAVCCodecSpecificData(
55403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        (const uint8_t *)buffer->data()
55503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                            + buffer->range_offset(),
55603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        buffer->range_length());
55703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
55803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                if (err != OK) {
55903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                    LOGE("failed to parse avc codec specific data.");
56030ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    break;
56130ab66297501757d745b9ae10da61adcd891f497Andreas Huber                }
56203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            } else if (is_mpeg4) {
56303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificDataSize = buffer->range_length();
56403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificData = malloc(mCodecSpecificDataSize);
56503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                memcpy(mCodecSpecificData,
56603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        (const uint8_t *)buffer->data()
56703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                            + buffer->range_offset(),
56803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                       buffer->range_length());
56930ab66297501757d745b9ae10da61adcd891f497Andreas Huber            }
57030ab66297501757d745b9ae10da61adcd891f497Andreas Huber
57130ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer->release();
57230ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer = NULL;
57330ab66297501757d745b9ae10da61adcd891f497Andreas Huber
574548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            mGotAllCodecSpecificData = true;
57530ab66297501757d745b9ae10da61adcd891f497Andreas Huber            continue;
576548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        } else if (!mGotAllCodecSpecificData &&
577548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber                count == 1 && is_mpeg4 && mCodecSpecificData == NULL) {
57803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            // The TI mpeg4 encoder does not properly set the
57903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            // codec-specific-data flag.
58030ab66297501757d745b9ae10da61adcd891f497Andreas Huber
58120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            const uint8_t *data =
58220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                (const uint8_t *)buffer->data() + buffer->range_offset();
58320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
58420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            const size_t size = buffer->range_length();
58520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
58620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            size_t offset = 0;
58720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (offset + 3 < size) {
58820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (data[offset] == 0x00 && data[offset + 1] == 0x00
58920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    && data[offset + 2] == 0x01 && data[offset + 3] == 0xb6) {
59020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    break;
59120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
59220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
59320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                ++offset;
59420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
59520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5960c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber            // CHECK(offset + 3 < size);
597bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber            if (offset + 3 >= size) {
598bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber                // XXX assume the entire first chunk of data is the codec specific
599bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber                // data.
600bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber                offset = size;
601bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber            }
60220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
60320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mCodecSpecificDataSize = offset;
60420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mCodecSpecificData = malloc(offset);
60520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            memcpy(mCodecSpecificData, data, offset);
60620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
60720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer->set_range(buffer->range_offset() + offset, size - offset);
60803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
60903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            if (size == offset) {
61003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                buffer->release();
61103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                buffer = NULL;
61203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
61303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                continue;
61403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            }
615548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
616548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            mGotAllCodecSpecificData = true;
617548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        } else if (!mGotAllCodecSpecificData && is_avc && count < 3) {
61803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            // The TI video encoder does not flag codec specific data
61903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            // as such and also splits up SPS and PPS across two buffers.
62003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
62103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            const uint8_t *data =
62203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                (const uint8_t *)buffer->data() + buffer->range_offset();
62303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
62403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            size_t size = buffer->range_length();
62503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
62603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            CHECK(count == 2 || mCodecSpecificData == NULL);
62703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
62803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            size_t offset = mCodecSpecificDataSize;
62903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            mCodecSpecificDataSize += size + 4;
63003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            mCodecSpecificData =
63103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                realloc(mCodecSpecificData, mCodecSpecificDataSize);
63203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
63303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            memcpy((uint8_t *)mCodecSpecificData + offset,
63403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                   "\x00\x00\x00\x01", 4);
63503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
63603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            memcpy((uint8_t *)mCodecSpecificData + offset + 4, data, size);
63703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
63803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            buffer->release();
63903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            buffer = NULL;
64003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
64103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            if (count == 2) {
64203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                void *tmp = mCodecSpecificData;
64303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                size = mCodecSpecificDataSize;
64403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificData = NULL;
64503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificDataSize = 0;
64603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
64703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                status_t err = makeAVCCodecSpecificData(
64803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        (const uint8_t *)tmp, size);
64903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
65003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                free(tmp);
65103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                tmp = NULL;
65203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
65303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                if (err != OK) {
65403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                    LOGE("failed to parse avc codec specific data.");
65503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                    break;
65603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                }
657548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
658548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber                mGotAllCodecSpecificData = true;
65903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            }
66003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
66103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            continue;
66220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
66320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
66430ab66297501757d745b9ae10da61adcd891f497Andreas Huber        off_t offset = is_avc ? mOwner->addLengthPrefixedSample(buffer)
66530ab66297501757d745b9ae10da61adcd891f497Andreas Huber                              : mOwner->addSample(buffer);
66620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
66720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        SampleInfo info;
66803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        info.size = is_avc
66903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR
67003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            ? buffer->range_length() + 4
67103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else
67203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            ? buffer->range_length() + 2
67303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif
67403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            : buffer->range_length();
67503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
67620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        info.offset = offset;
67720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
678050b28a593350047845a45a14cc5026221ac1620James Dong
679050b28a593350047845a45a14cc5026221ac1620James Dong        bool is_audio = !strncasecmp(mime, "audio/", 6);
680050b28a593350047845a45a14cc5026221ac1620James Dong
68148c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        int64_t timestampUs;
68248c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        CHECK(buffer->meta_data()->findInt64(kKeyTime, &timestampUs));
68348c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber
6843b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber        if (timestampUs > mMaxTimeStampUs) {
6853b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber            mMaxTimeStampUs = timestampUs;
6863b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber        }
6873b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber
68848c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        // Our timestamp is in ms.
68948c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        info.timestamp = (timestampUs + 500) / 1000;
69020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
69120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mSampleInfos.push_back(info);
69220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
693050b28a593350047845a45a14cc5026221ac1620James Dong        int32_t isSync = false;
694050b28a593350047845a45a14cc5026221ac1620James Dong        buffer->meta_data()->findInt32(kKeyIsSyncFrame, &isSync);
695050b28a593350047845a45a14cc5026221ac1620James Dong        if (isSync) {
696050b28a593350047845a45a14cc5026221ac1620James Dong            mStssTableEntries.push_back(mSampleInfos.size());
697050b28a593350047845a45a14cc5026221ac1620James Dong        }
698050b28a593350047845a45a14cc5026221ac1620James Dong        // Our timestamp is in ms.
69920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        buffer->release();
70020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        buffer = NULL;
70120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
70225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
70325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = true;
70420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
70520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7063b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const {
7073b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber    return mMaxTimeStampUs;
70820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
70920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
71020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::Track::writeTrackHeader(int32_t trackID) {
71120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const char *mime;
71220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool success = mMeta->findCString(kKeyMIMEType, &mime);
7130c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(success);
71420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
71520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool is_audio = !strncasecmp(mime, "audio/", 6);
71620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
71720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    time_t now = time(NULL);
71820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
71920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOwner->beginBox("trak");
72020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
72120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->beginBox("tkhd");
72220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);             // version=0, flags=0
72320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(now);           // creation time
72420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(now);           // modification time
72520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(trackID);
72620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);             // reserved
7273b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber        mOwner->writeInt32(getDurationUs() / 1000);
72820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);             // reserved
72920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);             // reserved
73020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt16(0);             // layer
73120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt16(0);             // alternate group
73220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt16(is_audio ? 0x100 : 0);  // volume
73320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt16(0);             // reserved
73420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
73520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0x10000);       // matrix
73620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
73720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
73820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
73920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0x10000);
74020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
74120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
74220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
74320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0x40000000);
74420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
74520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (is_audio) {
74620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);
74720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);
74820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        } else {
74920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            int32_t width, height;
75020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            bool success = mMeta->findInt32(kKeyWidth, &width);
75120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            success = success && mMeta->findInt32(kKeyHeight, &height);
7520c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber            CHECK(success);
75320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
754050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->writeInt32(width << 16);   // 32-bit fixed-point value
755050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->writeInt32(height << 16);  // 32-bit fixed-point value
75620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
75720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->endBox();  // tkhd
75820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
75920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->beginBox("mdia");
76020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
76120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("mdhd");
76220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // version=0, flags=0
76320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(now);           // creation time
76420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(now);           // modification time
76520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(1000);          // timescale
7663b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber          mOwner->writeInt32(getDurationUs() / 1000);
76720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt16(0);             // language code XXX
76820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt16(0);             // predefined
76920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->endBox();
77020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
77120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("hdlr");
77220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // version=0, flags=0
773050b28a593350047845a45a14cc5026221ac1620James Dong          mOwner->writeInt32(0);             // component type: should be mhlr
774050b28a593350047845a45a14cc5026221ac1620James Dong          mOwner->writeFourcc(is_audio ? "soun" : "vide");  // component subtype
77520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // reserved
77620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // reserved
77720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // reserved
778050b28a593350047845a45a14cc5026221ac1620James Dong          mOwner->writeCString("SoundHandler");          // name
77920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->endBox();
78020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
78120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("minf");
78220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          if (is_audio) {
78320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->beginBox("smhd");
78420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt32(0);           // version=0, flags=0
78520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // balance
78620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // reserved
78720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->endBox();
78820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          } else {
78920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->beginBox("vmhd");
79020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt32(0x00000001);  // version=0, flags=1
79120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // graphics mode
79220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // opcolor
79320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);
79420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);
79520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->endBox();
79620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          }
797050b28a593350047845a45a14cc5026221ac1620James Dong
798050b28a593350047845a45a14cc5026221ac1620James Dong          mOwner->beginBox("dinf");
799050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->beginBox("dref");
800050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->writeInt32(0);  // version=0, flags=0
801050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->writeInt32(1);
802050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->beginBox("url ");
803050b28a593350047845a45a14cc5026221ac1620James Dong                mOwner->writeInt32(1);  // version=0, flags=1
804050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->endBox();  // url
805050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->endBox();  // dref
806050b28a593350047845a45a14cc5026221ac1620James Dong          mOwner->endBox();  // dinf
807050b28a593350047845a45a14cc5026221ac1620James Dong
808050b28a593350047845a45a14cc5026221ac1620James Dong       mOwner->endBox();  // minf
80920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
81020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("stbl");
81120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
81220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stsd");
81320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);               // version=0, flags=0
81420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(1);               // entry count
81520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (is_audio) {
81625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                const char *fourcc = NULL;
81718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) {
81825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    fourcc = "samr";
81918291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
82025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    fourcc = "sawb";
821050b28a593350047845a45a14cc5026221ac1620James Dong                } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
822050b28a593350047845a45a14cc5026221ac1620James Dong                    fourcc = "mp4a";
82325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                } else {
82425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    LOGE("Unknown mime type '%s'.", mime);
82525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    CHECK(!"should not be here, unknown mime type.");
82625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                }
82725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
82825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                mOwner->beginBox(fourcc);          // audio format
82920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
83020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
831050b28a593350047845a45a14cc5026221ac1620James Dong                  mOwner->writeInt16(0x1);         // data ref index
83220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
83320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
834050b28a593350047845a45a14cc5026221ac1620James Dong                  int32_t nChannels;
835050b28a593350047845a45a14cc5026221ac1620James Dong                  CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels));
836050b28a593350047845a45a14cc5026221ac1620James Dong                  mOwner->writeInt16(nChannels);   // channel count
83720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(16);          // sample size
83820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // predefined
83920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
84020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
84120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  int32_t samplerate;
84220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  bool success = mMeta->findInt32(kKeySampleRate, &samplerate);
8430c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                  CHECK(success);
84420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
84520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(samplerate << 16);
846050b28a593350047845a45a14cc5026221ac1620James Dong                  if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
847050b28a593350047845a45a14cc5026221ac1620James Dong                    mOwner->beginBox("esds");
848050b28a593350047845a45a14cc5026221ac1620James Dong
849050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt32(0);     // version=0, flags=0
850050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x03);   // ES_DescrTag
851050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(23 + mCodecSpecificDataSize);
852050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt16(0x0000);// ES_ID
853050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x00);
854050b28a593350047845a45a14cc5026221ac1620James Dong
855050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x04);   // DecoderConfigDescrTag
856050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(15 + mCodecSpecificDataSize);
857050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x40);   // objectTypeIndication ISO/IEC 14492-2
858050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x15);   // streamType AudioStream
859050b28a593350047845a45a14cc5026221ac1620James Dong
860050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt16(0x03);  // XXX
861050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x00);   // buffer size 24-bit
862050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt32(96000); // max bit rate
863050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt32(96000); // avg bit rate
864050b28a593350047845a45a14cc5026221ac1620James Dong
865050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x05);   // DecoderSpecificInfoTag
866050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(mCodecSpecificDataSize);
867050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
868050b28a593350047845a45a14cc5026221ac1620James Dong
869050b28a593350047845a45a14cc5026221ac1620James Dong                        static const uint8_t kData2[] = {
870050b28a593350047845a45a14cc5026221ac1620James Dong                            0x06,  // SLConfigDescriptorTag
871050b28a593350047845a45a14cc5026221ac1620James Dong                            0x01,
872050b28a593350047845a45a14cc5026221ac1620James Dong                            0x02
873050b28a593350047845a45a14cc5026221ac1620James Dong                        };
874050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->write(kData2, sizeof(kData2));
875050b28a593350047845a45a14cc5026221ac1620James Dong
876050b28a593350047845a45a14cc5026221ac1620James Dong                    mOwner->endBox();  // esds
877050b28a593350047845a45a14cc5026221ac1620James Dong                  }
87820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mOwner->endBox();
87920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
88018291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
88120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    mOwner->beginBox("mp4v");
88218291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
88320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    mOwner->beginBox("s263");
88430ab66297501757d745b9ae10da61adcd891f497Andreas Huber                } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
88530ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    mOwner->beginBox("avc1");
88620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                } else {
88725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    LOGE("Unknown mime type '%s'.", mime);
8880c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                    CHECK(!"should not be here, unknown mime type.");
88920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
89020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
89120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
89220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
89320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // data ref index
89420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // predefined
89520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
89620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // predefined
89720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // predefined
89820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // predefined
89920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
90020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  int32_t width, height;
90120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  bool success = mMeta->findInt32(kKeyWidth, &width);
90220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  success = success && mMeta->findInt32(kKeyHeight, &height);
9030c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                  CHECK(success);
90420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
90520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(width);
90620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(height);
90720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0x480000);    // horiz resolution
90820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0x480000);    // vert resolution
90920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
91020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(1);           // frame count
91120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->write("                                ", 32);
91220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0x18);        // depth
91320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(-1);          // predefined
91420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9150c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                  CHECK(23 + mCodecSpecificDataSize < 128);
91620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
91718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                  if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
91820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->beginBox("esds");
91920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
92020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt32(0);           // version=0, flags=0
92120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
92220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x03);  // ES_DescrTag
92320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(23 + mCodecSpecificDataSize);
92420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt16(0x0000);  // ES_ID
92520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x1f);
92620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
92720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x04);  // DecoderConfigDescrTag
92820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(15 + mCodecSpecificDataSize);
92920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x20);  // objectTypeIndication ISO/IEC 14492-2
93020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x11);  // streamType VisualStream
93120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
93220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        static const uint8_t kData[] = {
93320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x01, 0x77, 0x00,
93420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x00, 0x03, 0xe8, 0x00,
93520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x00, 0x03, 0xe8, 0x00
93620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        };
93720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->write(kData, sizeof(kData));
938050b28a593350047845a45a14cc5026221ac1620James Dong
93920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x05);  // DecoderSpecificInfoTag
94020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
94120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(mCodecSpecificDataSize);
94220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
94320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
94420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        static const uint8_t kData2[] = {
94520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x06,  // SLConfigDescriptorTag
94620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x01,
94720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x02
94820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        };
94920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->write(kData2, sizeof(kData2));
95020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
95120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->endBox();  // esds
95218291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                  } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
95320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->beginBox("d263");
95420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
95520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt32(0);  // vendor
95620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt8(0);   // decoder version
95720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt8(10);  // level: 10
95820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt8(0);   // profile: 0
95920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
96020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->endBox();  // d263
96130ab66297501757d745b9ae10da61adcd891f497Andreas Huber                  } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
96230ab66297501757d745b9ae10da61adcd891f497Andreas Huber                      mOwner->beginBox("avcC");
96330ab66297501757d745b9ae10da61adcd891f497Andreas Huber                        mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
96430ab66297501757d745b9ae10da61adcd891f497Andreas Huber                      mOwner->endBox();  // avcC
96520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  }
96630ab66297501757d745b9ae10da61adcd891f497Andreas Huber
96730ab66297501757d745b9ae10da61adcd891f497Andreas Huber                mOwner->endBox();  // mp4v, s263 or avc1
96820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
96920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stsd
97020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
97120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stts");
97220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
97303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            mOwner->writeInt32(mSampleInfos.size());
97420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
97520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            List<SampleInfo>::iterator it = mSampleInfos.begin();
97620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            int64_t last = (*it).timestamp;
97703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            int64_t lastDuration = 1;
97803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
97920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            ++it;
98020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (it != mSampleInfos.end()) {
98120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mOwner->writeInt32(1);
98203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                lastDuration = (*it).timestamp - last;
98303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mOwner->writeInt32(lastDuration);
98420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
98520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                last = (*it).timestamp;
98620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
98720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                ++it;
98820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
98903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
99003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            // We don't really know how long the last frame lasts, since
99103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            // there is no frame time after it, just repeat the previous
99203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            // frame's duration.
99303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            mOwner->writeInt32(1);
99403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            mOwner->writeInt32(lastDuration);
99503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
99620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stts
99720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
998050b28a593350047845a45a14cc5026221ac1620James Dong          if (!is_audio) {
999050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->beginBox("stss");
1000050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->writeInt32(0);  // version=0, flags=0
1001050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->writeInt32(mStssTableEntries.size());  // number of sync frames
1002050b28a593350047845a45a14cc5026221ac1620James Dong              for (List<int32_t>::iterator it = mStssTableEntries.begin();
1003050b28a593350047845a45a14cc5026221ac1620James Dong                   it != mStssTableEntries.end(); ++it) {
1004050b28a593350047845a45a14cc5026221ac1620James Dong                  mOwner->writeInt32(*it);
1005050b28a593350047845a45a14cc5026221ac1620James Dong              }
1006050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->endBox();  // stss
1007050b28a593350047845a45a14cc5026221ac1620James Dong          }
1008050b28a593350047845a45a14cc5026221ac1620James Dong
100920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stsz");
101020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
101120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // default sample size
101220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(mSampleInfos.size());
101320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            for (List<SampleInfo>::iterator it = mSampleInfos.begin();
101420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                 it != mSampleInfos.end(); ++it) {
101520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mOwner->writeInt32((*it).size);
101620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
101720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stsz
101820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
101920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stsc");
102020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
102120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(mSampleInfos.size());
102220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            int32_t n = 1;
102320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            for (List<SampleInfo>::iterator it = mSampleInfos.begin();
102420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                 it != mSampleInfos.end(); ++it, ++n) {
102520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mOwner->writeInt32(n);
102620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mOwner->writeInt32(1);
102720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mOwner->writeInt32(1);
102820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
102920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stsc
103020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
103120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("co64");
103220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
103320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(mSampleInfos.size());
103420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            for (List<SampleInfo>::iterator it = mSampleInfos.begin();
1035050b28a593350047845a45a14cc5026221ac1620James Dong                 it != mSampleInfos.end(); ++it) {
103620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mOwner->writeInt64((*it).offset);
103720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
103820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // co64
103920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
104020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->endBox();  // stbl
104120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->endBox();  // mdia
104220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOwner->endBox();  // trak
104320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
104420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
104520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
1046