MPEG4Writer.cpp revision 3266b2c04867f687e1e1b7b86088d6eb83077fd0
120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber/*
220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Copyright (C) 2009 The Android Open Source Project
320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * you may not use this file except in compliance with the License.
620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * You may obtain a copy of the License at
720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
1020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Unless required by applicable law or agreed to in writing, software
1120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
1220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * See the License for the specific language governing permissions and
1420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * limitations under the License.
1520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber */
1620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
17050b28a593350047845a45a14cc5026221ac1620James Dong//#define LOG_NDEBUG 0
18050b28a593350047845a45a14cc5026221ac1620James Dong#define LOG_TAG "MPEG4Writer"
19050b28a593350047845a45a14cc5026221ac1620James Dong#include <utils/Log.h>
20050b28a593350047845a45a14cc5026221ac1620James Dong
2120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <arpa/inet.h>
2220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <ctype.h>
2420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <pthread.h>
2520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MPEG4Writer.h>
2720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBuffer.h>
2820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h>
290c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber#include <media/stagefright/MediaDebug.h>
3018291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h>
3103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#include <media/stagefright/MediaErrors.h>
3220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaSource.h>
3320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/Utils.h>
34d599cd4573b5a2d5914c5040e0565ef866749b77James Dong#include <media/mediarecorder.h>
35365a963142093a1cd8efdcea76b5f65096a5b115James Dong#include <cutils/properties.h>
3620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber#include "include/ESDS.h"
3819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
3920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android {
4020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypeSeqParamSet = 0x07;
423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypePicParamSet = 0x08;
433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
4420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Writer::Track {
4520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic:
4625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    Track(MPEG4Writer *owner, const sp<MediaSource> &source);
478f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
4820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    ~Track();
4920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t start(MetaData *params);
5120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void stop();
52a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    void pause();
5325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool reachedEOS();
5420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
553b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber    int64_t getDurationUs() const;
56d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t getEstimatedTrackSizeBytes() const;
571acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    void writeTrackHeader(int32_t trackID, bool use32BitOffset = true);
581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void bufferChunk(int64_t timestampUs);
591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isAvc() const { return mIsAvc; }
601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isAudio() const { return mIsAudio; }
611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isMPEG4() const { return mIsMPEG4; }
621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void addChunkOffset(off_t offset) { mChunkOffsets.push_back(offset); }
6320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate:
6520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Writer *mOwner;
6620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MetaData> mMeta;
67693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    sp<MediaSource> mSource;
6820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    volatile bool mDone;
69a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mPaused;
70a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mResumed;
711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAvc;
721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAudio;
731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsMPEG4;
74c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    int64_t mTrackDurationUs;
75d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t mEstimatedTrackSizeBytes;
761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    int64_t mMaxWriteTimeUs;
778f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int32_t mTimeScale;
7820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_t mThread;
8020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
81ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    // mNumSamples is used to track how many samples in mSampleSizes List.
82ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    // This is to reduce the cost associated with mSampleSizes.size() call,
83ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    // since it is O(n). Ideally, the fix should be in List class.
84ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    size_t              mNumSamples;
858644c14618d30d9e57a69df40ed939986ebf02c4James Dong    List<size_t>        mSampleSizes;
86be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    bool                mSamplesHaveSameSize;
87be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
8813aec890216948b0c364f8f92792129d0335f506James Dong    List<MediaBuffer *> mChunkSamples;
8913aec890216948b0c364f8f92792129d0335f506James Dong    List<off_t>         mChunkOffsets;
9013aec890216948b0c364f8f92792129d0335f506James Dong
9113aec890216948b0c364f8f92792129d0335f506James Dong    struct StscTableEntry {
9213aec890216948b0c364f8f92792129d0335f506James Dong
9313aec890216948b0c364f8f92792129d0335f506James Dong        StscTableEntry(uint32_t chunk, uint32_t samples, uint32_t id)
9413aec890216948b0c364f8f92792129d0335f506James Dong            : firstChunk(chunk),
9513aec890216948b0c364f8f92792129d0335f506James Dong              samplesPerChunk(samples),
9613aec890216948b0c364f8f92792129d0335f506James Dong              sampleDescriptionId(id) {}
9713aec890216948b0c364f8f92792129d0335f506James Dong
9813aec890216948b0c364f8f92792129d0335f506James Dong        uint32_t firstChunk;
9913aec890216948b0c364f8f92792129d0335f506James Dong        uint32_t samplesPerChunk;
10013aec890216948b0c364f8f92792129d0335f506James Dong        uint32_t sampleDescriptionId;
10113aec890216948b0c364f8f92792129d0335f506James Dong    };
10213aec890216948b0c364f8f92792129d0335f506James Dong    List<StscTableEntry> mStscTableEntries;
10320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
104050b28a593350047845a45a14cc5026221ac1620James Dong    List<int32_t> mStssTableEntries;
105365a963142093a1cd8efdcea76b5f65096a5b115James Dong    List<int64_t> mChunkDurations;
106050b28a593350047845a45a14cc5026221ac1620James Dong
107be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    struct SttsTableEntry {
108be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
1098f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        SttsTableEntry(uint32_t count, uint32_t durationUs)
1108f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            : sampleCount(count), sampleDurationUs(durationUs) {}
111be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
112be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        uint32_t sampleCount;
1138f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        uint32_t sampleDurationUs;
114be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    };
115be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    List<SttsTableEntry> mSttsTableEntries;
116be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
1173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Sequence parameter set or picture parameter set
1183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    struct AVCParamSet {
1193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        AVCParamSet(uint16_t length, const uint8_t *data)
1203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            : mLength(length), mData(data) {}
1213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
1223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t mLength;
1233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *mData;
1243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    };
1253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    List<AVCParamSet> mSeqParamSets;
1263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    List<AVCParamSet> mPicParamSets;
1273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mProfileIdc;
1283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mProfileCompatible;
1293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mLevelIdc;
1303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *mCodecSpecificData;
13220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t mCodecSpecificDataSize;
133548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    bool mGotAllCodecSpecificData;
13493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    bool mTrackingProgressStatus;
13520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
13625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool mReachedEOS;
1373c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    int64_t mStartTimestampUs;
13893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mPreviousTrackTimeUs;
13993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mTrackEveryTimeDurationUs;
14025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
14120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    static void *ThreadWrapper(void *me);
14220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void threadEntry();
14320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *parseParamSet(
1453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen);
1463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
14703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    status_t makeAVCCodecSpecificData(
14803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            const uint8_t *data, size_t size);
1493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    status_t copyAVCCodecSpecificData(
1503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            const uint8_t *data, size_t size);
1513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    status_t parseAVCCodecSpecificData(
1523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            const uint8_t *data, size_t size);
153215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong
154215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    // Track authoring progress status
155faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    void trackProgressStatus(int64_t timeUs, status_t err = OK);
15693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    void initTrackingProgressStatus(MetaData *params);
15703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
158215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    // Utilities for collecting statistical data
159215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    void logStatisticalData(bool isAudio);
160215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    void findMinAvgMaxSampleDurationMs(
161215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong            int32_t *min, int32_t *avg, int32_t *max);
162215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    void findMinMaxChunkDurations(int64_t *min, int64_t *max);
163215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong
16419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    void getCodecSpecificDataFromInputFormatIfPossible();
16519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
16620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track(const Track &);
16720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track &operator=(const Track &);
16820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
16920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
17003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#define USE_NALLEN_FOUR         1
17103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
17220111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::MPEG4Writer(const char *filename)
17320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mFile(fopen(filename, "wb")),
1741acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong      mUse32BitOffset(true),
175a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
176a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mStarted(false),
17720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOffset(0),
17813aec890216948b0c364f8f92792129d0335f506James Dong      mMdatOffset(0),
1797837c17063a4c50bc856ba59418516fdab731de7James Dong      mEstimatedMoovBoxSize(0),
180f01528f435e6b1f02d118fcd8305a148c27a89f1James Dong      mInterleaveDurationUs(1000000) {
1810c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(mFile != NULL);
18220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
18320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
18430ab66297501757d745b9ae10da61adcd891f497Andreas HuberMPEG4Writer::MPEG4Writer(int fd)
18530ab66297501757d745b9ae10da61adcd891f497Andreas Huber    : mFile(fdopen(fd, "wb")),
1861acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong      mUse32BitOffset(true),
187a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
188a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mStarted(false),
18930ab66297501757d745b9ae10da61adcd891f497Andreas Huber      mOffset(0),
19013aec890216948b0c364f8f92792129d0335f506James Dong      mMdatOffset(0),
1917837c17063a4c50bc856ba59418516fdab731de7James Dong      mEstimatedMoovBoxSize(0),
192f01528f435e6b1f02d118fcd8305a148c27a89f1James Dong      mInterleaveDurationUs(1000000) {
19330ab66297501757d745b9ae10da61adcd891f497Andreas Huber    CHECK(mFile != NULL);
19430ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
19530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
19620111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() {
19720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    stop();
19820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
19920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
20020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber         it != mTracks.end(); ++it) {
20120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        delete *it;
20220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
20320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.clear();
20420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
20520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2062dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huberstatus_t MPEG4Writer::addSource(const sp<MediaSource> &source) {
20725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    Track *track = new Track(this, source);
20820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.push_back(track);
2092dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
2102dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    return OK;
21120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
21220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
21393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::startTracks(MetaData *params) {
214a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
215a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
21693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        status_t err = (*it)->start(params);
217a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
218a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (err != OK) {
219a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            for (List<Track *>::iterator it2 = mTracks.begin();
220a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                 it2 != it; ++it2) {
221a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                (*it2)->stop();
222a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            }
223a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
224a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            return err;
225a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
226a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
227a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    return OK;
228a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
229a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
2302dec2b5be2056c6d9428897dc672185872d30d17James Dongint64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) {
2312dec2b5be2056c6d9428897dc672185872d30d17James Dong    // This implementation is highly experimental/heurisitic.
2322dec2b5be2056c6d9428897dc672185872d30d17James Dong    //
2332dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Statistical analysis shows that metadata usually accounts
2342dec2b5be2056c6d9428897dc672185872d30d17James Dong    // for a small portion of the total file size, usually < 0.6%.
2352dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Currently, lets set to 0.4% for now.
2362dec2b5be2056c6d9428897dc672185872d30d17James Dong
2372dec2b5be2056c6d9428897dc672185872d30d17James Dong    // The default MIN_MOOV_BOX_SIZE is set to 0.4% x 1MB,
2382dec2b5be2056c6d9428897dc672185872d30d17James Dong    // where 1MB is the common file size limit for MMS application.
2392dec2b5be2056c6d9428897dc672185872d30d17James Dong    // The default MAX _MOOV_BOX_SIZE value is based on about 4
2402dec2b5be2056c6d9428897dc672185872d30d17James Dong    // minute video recording with a bit rate about 3 Mbps, because
2412dec2b5be2056c6d9428897dc672185872d30d17James Dong    // statistics also show that most of the video captured are going
2422dec2b5be2056c6d9428897dc672185872d30d17James Dong    // to be less than 3 minutes.
2432dec2b5be2056c6d9428897dc672185872d30d17James Dong
2442dec2b5be2056c6d9428897dc672185872d30d17James Dong    // If the estimation is wrong, we will pay the price of wasting
2452dec2b5be2056c6d9428897dc672185872d30d17James Dong    // some reserved space. This should not happen so often statistically.
2462dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int32_t factor = mUse32BitOffset? 1: 2;
2472dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int64_t MIN_MOOV_BOX_SIZE = 4 * 1024;  // 4 KB
2482dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000);
2492dec2b5be2056c6d9428897dc672185872d30d17James Dong    int64_t size = MIN_MOOV_BOX_SIZE;
2502dec2b5be2056c6d9428897dc672185872d30d17James Dong
2512dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (mMaxFileSizeLimitBytes != 0) {
2522dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = mMaxFileSizeLimitBytes * 4 / 1000;
2532dec2b5be2056c6d9428897dc672185872d30d17James Dong    } else if (mMaxFileDurationLimitUs != 0) {
2542dec2b5be2056c6d9428897dc672185872d30d17James Dong        if (bitRate <= 0) {
2552dec2b5be2056c6d9428897dc672185872d30d17James Dong            // We could not estimate the file size since bitRate is not set.
2562dec2b5be2056c6d9428897dc672185872d30d17James Dong            size = MIN_MOOV_BOX_SIZE;
2572dec2b5be2056c6d9428897dc672185872d30d17James Dong        } else {
2582dec2b5be2056c6d9428897dc672185872d30d17James Dong            size = ((mMaxFileDurationLimitUs * bitRate * 4) / 1000 / 8000000);
2592dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
2602dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
2612dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size < MIN_MOOV_BOX_SIZE) {
2622dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MIN_MOOV_BOX_SIZE;
2632dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
2642dec2b5be2056c6d9428897dc672185872d30d17James Dong
2652dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Any long duration recording will be probably end up with
2662dec2b5be2056c6d9428897dc672185872d30d17James Dong    // non-streamable mp4 file.
2672dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size > MAX_MOOV_BOX_SIZE) {
2682dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MAX_MOOV_BOX_SIZE;
2692dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
2702dec2b5be2056c6d9428897dc672185872d30d17James Dong
2712dec2b5be2056c6d9428897dc672185872d30d17James Dong    LOGI("limits: %lld/%lld bytes/us, bit rate: %d bps and the estimated"
2722dec2b5be2056c6d9428897dc672185872d30d17James Dong         " moov size %lld bytes",
2732dec2b5be2056c6d9428897dc672185872d30d17James Dong         mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size);
2742dec2b5be2056c6d9428897dc672185872d30d17James Dong    return factor * size;
2752dec2b5be2056c6d9428897dc672185872d30d17James Dong}
2762dec2b5be2056c6d9428897dc672185872d30d17James Dong
2772dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t MPEG4Writer::start(MetaData *param) {
27820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mFile == NULL) {
27925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return UNKNOWN_ERROR;
28020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
28120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2822dec2b5be2056c6d9428897dc672185872d30d17James Dong    int32_t use64BitOffset;
2832dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (param &&
2842dec2b5be2056c6d9428897dc672185872d30d17James Dong        param->findInt32(kKey64BitFileOffset, &use64BitOffset) &&
2852dec2b5be2056c6d9428897dc672185872d30d17James Dong        use64BitOffset) {
2862dec2b5be2056c6d9428897dc672185872d30d17James Dong        mUse32BitOffset = false;
2872dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
2882dec2b5be2056c6d9428897dc672185872d30d17James Dong
2892dec2b5be2056c6d9428897dc672185872d30d17James Dong    // System property can overwrite the file offset bits parameter
2902dec2b5be2056c6d9428897dc672185872d30d17James Dong    char value[PROPERTY_VALUE_MAX];
2912dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (property_get("media.stagefright.record-64bits", value, NULL)
2922dec2b5be2056c6d9428897dc672185872d30d17James Dong        && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
2932dec2b5be2056c6d9428897dc672185872d30d17James Dong        mUse32BitOffset = false;
2942dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
2952dec2b5be2056c6d9428897dc672185872d30d17James Dong
296065d1aff96818df54456053f1574aec8a234d0deJames Dong    mStartTimestampUs = -1;
29793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
298a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (mStarted) {
299a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused) {
300a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mPaused = false;
30193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            return startTracks(param);
302a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
303a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
304a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
305a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
3068f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    if (!param ||
3078f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        !param->findInt32(kKeyTimeScale, &mTimeScale)) {
3088f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        mTimeScale = 1000;
3098f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    }
3108f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    CHECK(mTimeScale > 0);
3118f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    LOGV("movie time scale: %d", mTimeScale);
3128f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
3137837c17063a4c50bc856ba59418516fdab731de7James Dong    mStreamableFile = true;
3147837c17063a4c50bc856ba59418516fdab731de7James Dong    mWriteMoovBoxToMemory = false;
3157837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBuffer = NULL;
3167837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
3177837c17063a4c50bc856ba59418516fdab731de7James Dong
31820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    beginBox("ftyp");
31993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong      {
32093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        int32_t fileType;
32193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (param && param->findInt32(kKeyFileType, &fileType) &&
32293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            fileType != OUTPUT_FORMAT_MPEG_4) {
32393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            writeFourcc("3gp4");
32493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        } else {
32593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            writeFourcc("isom");
32693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
32793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong      }
32820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      writeInt32(0);
32920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      writeFourcc("isom");
33093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong      writeFourcc("3gp4");
33120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    endBox();
33220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3337837c17063a4c50bc856ba59418516fdab731de7James Dong    mFreeBoxOffset = mOffset;
33420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3357837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mEstimatedMoovBoxSize == 0) {
3362dec2b5be2056c6d9428897dc672185872d30d17James Dong        int32_t bitRate = -1;
3372dec2b5be2056c6d9428897dc672185872d30d17James Dong        if (param) {
3382dec2b5be2056c6d9428897dc672185872d30d17James Dong            param->findInt32(kKeyBitRate, &bitRate);
3392dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
3402dec2b5be2056c6d9428897dc672185872d30d17James Dong        mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate);
3417837c17063a4c50bc856ba59418516fdab731de7James Dong    }
3427837c17063a4c50bc856ba59418516fdab731de7James Dong    CHECK(mEstimatedMoovBoxSize >= 8);
3437837c17063a4c50bc856ba59418516fdab731de7James Dong    fseeko(mFile, mFreeBoxOffset, SEEK_SET);
3447837c17063a4c50bc856ba59418516fdab731de7James Dong    writeInt32(mEstimatedMoovBoxSize);
3457837c17063a4c50bc856ba59418516fdab731de7James Dong    write("free", 4);
3467837c17063a4c50bc856ba59418516fdab731de7James Dong
3477837c17063a4c50bc856ba59418516fdab731de7James Dong    mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize;
3487837c17063a4c50bc856ba59418516fdab731de7James Dong    mOffset = mMdatOffset;
3497837c17063a4c50bc856ba59418516fdab731de7James Dong    fseeko(mFile, mMdatOffset, SEEK_SET);
3501acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
3511acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("????mdat", 8);
3521acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
3531acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("\x00\x00\x00\x01mdat????????", 16);
3541acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
3551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
3561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    status_t err = startWriterThread();
3571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (err != OK) {
3581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        return err;
3591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
3601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
3611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    err = startTracks(param);
362a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (err != OK) {
363a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return err;
36420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
3651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
366a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mStarted = true;
36725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
36820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
36920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
370a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dongvoid MPEG4Writer::pause() {
371a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (mFile == NULL) {
372a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return;
373a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
374a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
375a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
376a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
377a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        (*it)->pause();
378a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
379a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
380a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
3811c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::stopWriterThread() {
3821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("stopWriterThread");
3831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
3841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    {
3851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        Mutex::Autolock autolock(mLock);
3861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
3871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mDone = true;
3881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkReadyCondition.signal();
3891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
3901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
3911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void *dummy;
3921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_join(mThread, &dummy);
3931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
3941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
39520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::stop() {
39620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mFile == NULL) {
39720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return;
39820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
39920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4008f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t maxDurationUs = 0;
40120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
40220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber         it != mTracks.end(); ++it) {
40320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        (*it)->stop();
40420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4058f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int64_t durationUs = (*it)->getDurationUs();
4068f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        if (durationUs > maxDurationUs) {
4078f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            maxDurationUs = durationUs;
40820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
40920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
41020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    stopWriterThread();
4127837c17063a4c50bc856ba59418516fdab731de7James Dong
41320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // Fix up the size of the 'mdat' chunk.
4141acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
4151acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        fseeko(mFile, mMdatOffset, SEEK_SET);
4161acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        int32_t size = htonl(static_cast<int32_t>(mOffset - mMdatOffset));
4171acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        fwrite(&size, 1, 4, mFile);
4181acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
4191acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        fseeko(mFile, mMdatOffset + 8, SEEK_SET);
4201acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        int64_t size = mOffset - mMdatOffset;
4211acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        size = hton64(size);
4221acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        fwrite(&size, 1, 8, mFile);
4231acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
4247837c17063a4c50bc856ba59418516fdab731de7James Dong    fseeko(mFile, mOffset, SEEK_SET);
42520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
42620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    time_t now = time(NULL);
4277837c17063a4c50bc856ba59418516fdab731de7James Dong    const off_t moovOffset = mOffset;
4287837c17063a4c50bc856ba59418516fdab731de7James Dong    mWriteMoovBoxToMemory = true;
4297837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize);
4307837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
4317837c17063a4c50bc856ba59418516fdab731de7James Dong    CHECK(mMoovBoxBuffer != NULL);
4328f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int32_t duration = (maxDurationUs * mTimeScale) / 1E6;
43320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
43420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    beginBox("moov");
43520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
43620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      beginBox("mvhd");
43720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // version=0, flags=0
43820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(now);           // creation time
43920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(now);           // modification time
4408f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        writeInt32(mTimeScale);    // mvhd timescale
4411acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        writeInt32(duration);
4421acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        writeInt32(0x10000);       // rate: 1.0
44320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt16(0x100);         // volume
44420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt16(0);             // reserved
44520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // reserved
44620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // reserved
44720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0x10000);       // matrix
44820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
44920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
45020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
45120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0x10000);
45220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
45320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
45420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);
45520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0x40000000);
45620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
45720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
45820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
45920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
46020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
46120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(0);             // predefined
46220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        writeInt32(mTracks.size() + 1);  // nextTrackID
46320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      endBox();  // mvhd
46420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
46520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      int32_t id = 1;
46620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      for (List<Track *>::iterator it = mTracks.begin();
46720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber           it != mTracks.end(); ++it, ++id) {
4681acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          (*it)->writeTrackHeader(id, mUse32BitOffset);
46920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      }
47020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    endBox();  // moov
47120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4727837c17063a4c50bc856ba59418516fdab731de7James Dong    mWriteMoovBoxToMemory = false;
4737837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mStreamableFile) {
4747837c17063a4c50bc856ba59418516fdab731de7James Dong        CHECK(mMoovBoxBufferOffset + 8 <= mEstimatedMoovBoxSize);
4757837c17063a4c50bc856ba59418516fdab731de7James Dong
4767837c17063a4c50bc856ba59418516fdab731de7James Dong        // Moov box
4777837c17063a4c50bc856ba59418516fdab731de7James Dong        fseeko(mFile, mFreeBoxOffset, SEEK_SET);
4787837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset = mFreeBoxOffset;
4797837c17063a4c50bc856ba59418516fdab731de7James Dong        write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, mFile);
4807837c17063a4c50bc856ba59418516fdab731de7James Dong
4817837c17063a4c50bc856ba59418516fdab731de7James Dong        // Free box
4822dec2b5be2056c6d9428897dc672185872d30d17James Dong        fseeko(mFile, mOffset, SEEK_SET);
4837837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset);
4847837c17063a4c50bc856ba59418516fdab731de7James Dong        write("free", 4);
4857837c17063a4c50bc856ba59418516fdab731de7James Dong
4867837c17063a4c50bc856ba59418516fdab731de7James Dong        // Free temp memory
4877837c17063a4c50bc856ba59418516fdab731de7James Dong        free(mMoovBoxBuffer);
4887837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBuffer = NULL;
4897837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBufferOffset = 0;
4902dec2b5be2056c6d9428897dc672185872d30d17James Dong    } else {
4912dec2b5be2056c6d9428897dc672185872d30d17James Dong        LOGI("The mp4 file will not be streamable.");
4927837c17063a4c50bc856ba59418516fdab731de7James Dong    }
4937837c17063a4c50bc856ba59418516fdab731de7James Dong
4940c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(mBoxes.empty());
49520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4967837c17063a4c50bc856ba59418516fdab731de7James Dong    fflush(mFile);
49720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fclose(mFile);
49820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mFile = NULL;
499a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mStarted = false;
50020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
50120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
50213aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) {
50313aec890216948b0c364f8f92792129d0335f506James Dong    mInterleaveDurationUs = durationUs;
50413aec890216948b0c364f8f92792129d0335f506James Dong    return OK;
50513aec890216948b0c364f8f92792129d0335f506James Dong}
50613aec890216948b0c364f8f92792129d0335f506James Dong
50713aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() {
50813aec890216948b0c364f8f92792129d0335f506James Dong    mLock.lock();
50913aec890216948b0c364f8f92792129d0335f506James Dong}
51013aec890216948b0c364f8f92792129d0335f506James Dong
51113aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() {
51213aec890216948b0c364f8f92792129d0335f506James Dong    mLock.unlock();
51313aec890216948b0c364f8f92792129d0335f506James Dong}
51420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
51513aec890216948b0c364f8f92792129d0335f506James Dongoff_t MPEG4Writer::addSample_l(MediaBuffer *buffer) {
51620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    off_t old_offset = mOffset;
51720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
51820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    fwrite((const uint8_t *)buffer->data() + buffer->range_offset(),
51920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber           1, buffer->range_length(), mFile);
52020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
52120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += buffer->range_length();
52220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
52320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return old_offset;
52420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
52520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
52603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) {
52703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (buffer->range_length() < 4) {
52803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return;
52903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
53003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
53103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    const uint8_t *ptr =
53203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        (const uint8_t *)buffer->data() + buffer->range_offset();
53303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
53403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) {
53503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        buffer->set_range(
53603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                buffer->range_offset() + 4, buffer->range_length() - 4);
53703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
53803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
53903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
54013aec890216948b0c364f8f92792129d0335f506James Dongoff_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) {
54130ab66297501757d745b9ae10da61adcd891f497Andreas Huber    off_t old_offset = mOffset;
54230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
54330ab66297501757d745b9ae10da61adcd891f497Andreas Huber    size_t length = buffer->range_length();
54403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
54503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR
54603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    uint8_t x = length >> 24;
54703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    fwrite(&x, 1, 1, mFile);
54803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    x = (length >> 16) & 0xff;
54903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    fwrite(&x, 1, 1, mFile);
55003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    x = (length >> 8) & 0xff;
55103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    fwrite(&x, 1, 1, mFile);
55203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    x = length & 0xff;
55303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    fwrite(&x, 1, 1, mFile);
55403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else
55530ab66297501757d745b9ae10da61adcd891f497Andreas Huber    CHECK(length < 65536);
55630ab66297501757d745b9ae10da61adcd891f497Andreas Huber
55730ab66297501757d745b9ae10da61adcd891f497Andreas Huber    uint8_t x = length >> 8;
55830ab66297501757d745b9ae10da61adcd891f497Andreas Huber    fwrite(&x, 1, 1, mFile);
55930ab66297501757d745b9ae10da61adcd891f497Andreas Huber    x = length & 0xff;
56030ab66297501757d745b9ae10da61adcd891f497Andreas Huber    fwrite(&x, 1, 1, mFile);
56103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif
56230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
56330ab66297501757d745b9ae10da61adcd891f497Andreas Huber    fwrite((const uint8_t *)buffer->data() + buffer->range_offset(),
56430ab66297501757d745b9ae10da61adcd891f497Andreas Huber           1, length, mFile);
56530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
56603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR
56703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    mOffset += length + 4;
56803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else
56930ab66297501757d745b9ae10da61adcd891f497Andreas Huber    mOffset += length + 2;
57003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif
57130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
57230ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return old_offset;
57330ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
57430ab66297501757d745b9ae10da61adcd891f497Andreas Huber
5757837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write(
5767837c17063a4c50bc856ba59418516fdab731de7James Dong        const void *ptr, size_t size, size_t nmemb, FILE *stream) {
5777837c17063a4c50bc856ba59418516fdab731de7James Dong
5787837c17063a4c50bc856ba59418516fdab731de7James Dong    const size_t bytes = size * nmemb;
5797837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
5801acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        off_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes;
5811acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        if (moovBoxSize > mEstimatedMoovBoxSize) {
5827837c17063a4c50bc856ba59418516fdab731de7James Dong            for (List<off_t>::iterator it = mBoxes.begin();
5837837c17063a4c50bc856ba59418516fdab731de7James Dong                 it != mBoxes.end(); ++it) {
5847837c17063a4c50bc856ba59418516fdab731de7James Dong                (*it) += mOffset;
5857837c17063a4c50bc856ba59418516fdab731de7James Dong            }
5867837c17063a4c50bc856ba59418516fdab731de7James Dong            fseeko(mFile, mOffset, SEEK_SET);
5877837c17063a4c50bc856ba59418516fdab731de7James Dong            fwrite(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, stream);
5887837c17063a4c50bc856ba59418516fdab731de7James Dong            fwrite(ptr, size, nmemb, stream);
5897837c17063a4c50bc856ba59418516fdab731de7James Dong            mOffset += (bytes + mMoovBoxBufferOffset);
5907837c17063a4c50bc856ba59418516fdab731de7James Dong            free(mMoovBoxBuffer);
5917837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBuffer = NULL;
5927837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset = 0;
5937837c17063a4c50bc856ba59418516fdab731de7James Dong            mWriteMoovBoxToMemory = false;
5947837c17063a4c50bc856ba59418516fdab731de7James Dong            mStreamableFile = false;
5957837c17063a4c50bc856ba59418516fdab731de7James Dong        } else {
5967837c17063a4c50bc856ba59418516fdab731de7James Dong            memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes);
5977837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset += bytes;
5987837c17063a4c50bc856ba59418516fdab731de7James Dong        }
5997837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
6007837c17063a4c50bc856ba59418516fdab731de7James Dong        fwrite(ptr, size, nmemb, stream);
6017837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset += bytes;
6027837c17063a4c50bc856ba59418516fdab731de7James Dong    }
6037837c17063a4c50bc856ba59418516fdab731de7James Dong    return bytes;
6047837c17063a4c50bc856ba59418516fdab731de7James Dong}
6057837c17063a4c50bc856ba59418516fdab731de7James Dong
60620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) {
6070c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(fourcc), 4);
60820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6097837c17063a4c50bc856ba59418516fdab731de7James Dong    mBoxes.push_back(mWriteMoovBoxToMemory?
6107837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset: mOffset);
61120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
61220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeInt32(0);
61320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeFourcc(fourcc);
61420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
61520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
61620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() {
6170c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(!mBoxes.empty());
61820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
61920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    off_t offset = *--mBoxes.end();
62020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mBoxes.erase(--mBoxes.end());
62120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6227837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
6237837c17063a4c50bc856ba59418516fdab731de7James Dong       int32_t x = htonl(mMoovBoxBufferOffset - offset);
6247837c17063a4c50bc856ba59418516fdab731de7James Dong       memcpy(mMoovBoxBuffer + offset, &x, 4);
6257837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
6267837c17063a4c50bc856ba59418516fdab731de7James Dong        fseeko(mFile, offset, SEEK_SET);
6277837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mOffset - offset);
6287837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset -= 4;
6297837c17063a4c50bc856ba59418516fdab731de7James Dong        fseeko(mFile, mOffset, SEEK_SET);
6307837c17063a4c50bc856ba59418516fdab731de7James Dong    }
63120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
63220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
63320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) {
6347837c17063a4c50bc856ba59418516fdab731de7James Dong    write(&x, 1, 1, mFile);
63520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
63620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
63720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) {
63820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htons(x);
6397837c17063a4c50bc856ba59418516fdab731de7James Dong    write(&x, 1, 2, mFile);
64020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
64120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
64220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) {
64320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htonl(x);
6447837c17063a4c50bc856ba59418516fdab731de7James Dong    write(&x, 1, 4, mFile);
64520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
64620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
64720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) {
64820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = hton64(x);
6497837c17063a4c50bc856ba59418516fdab731de7James Dong    write(&x, 1, 8, mFile);
65020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
65120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
65220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) {
65320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t n = strlen(s);
6547837c17063a4c50bc856ba59418516fdab731de7James Dong    write(s, 1, n + 1, mFile);
65520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
65620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
65720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) {
6580c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(s), 4);
6597837c17063a4c50bc856ba59418516fdab731de7James Dong    write(s, 1, 4, mFile);
66020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
66120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
66220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) {
6637837c17063a4c50bc856ba59418516fdab731de7James Dong    write(data, 1, size, mFile);
66420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
66520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
666d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() {
667d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
668d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileSizeLimitBytes == 0) {
669d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
670d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
671d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
672956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize);
673d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
674d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
675d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes();
676d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
677d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return (nTotalBytesEstimate >= mMaxFileSizeLimitBytes);
678d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
679d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
680d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() {
681d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
682d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileDurationLimitUs == 0) {
683d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
684d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
685d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
686d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
687d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
688d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) {
689d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            return true;
690d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
691d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
692d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return false;
693d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
694d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
69525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() {
69625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool allDone = true;
69725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
69825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber         it != mTracks.end(); ++it) {
69925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        if (!(*it)->reachedEOS()) {
70025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            allDone = false;
70125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            break;
70225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        }
70325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
70425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
70525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return allDone;
70625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
70725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
708f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) {
709f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    LOGI("setStartTimestampUs: %lld", timeUs);
710f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    CHECK(timeUs >= 0);
7113c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
712065d1aff96818df54456053f1574aec8a234d0deJames Dong    if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) {
713f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mStartTimestampUs = timeUs;
714f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        LOGI("Earliest track starting time: %lld", mStartTimestampUs);
7153c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    }
7163c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
7173c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
718f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() {
7193c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
7203c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    return mStartTimestampUs;
7213c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
7223c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
72358ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() {
72458ae9c530247668f8af36e30d228c716c226b3d4James Dong    Mutex::Autolock autolock(mLock);
72558ae9c530247668f8af36e30d228c716c226b3d4James Dong    return mTracks.size();
72658ae9c530247668f8af36e30d228c716c226b3d4James Dong}
72758ae9c530247668f8af36e30d228c716c226b3d4James Dong
72820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
72920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
73020111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track(
73125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        MPEG4Writer *owner, const sp<MediaSource> &source)
73220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mOwner(owner),
73325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mMeta(source->getFormat()),
73420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSource(source),
73520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDone(false),
736a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
737a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mResumed(false),
738c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong      mTrackDurationUs(0),
739956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      mEstimatedTrackSizeBytes(0),
740be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong      mSamplesHaveSameSize(true),
74120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCodecSpecificData(NULL),
74225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mCodecSpecificDataSize(0),
743548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber      mGotAllCodecSpecificData(false),
74425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mReachedEOS(false) {
74519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    getCodecSpecificDataFromInputFormatIfPossible();
7468f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
7478f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    if (!mMeta->findInt32(kKeyTimeScale, &mTimeScale)) {
7488f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        mTimeScale = 1000;
7498f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    }
7501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
7511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    const char *mime;
7521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mMeta->findCString(kKeyMIMEType, &mime);
7531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
7541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAudio = !strncasecmp(mime, "audio/", 6);
7551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
7561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong               !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC);
7571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
7588f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    CHECK(mTimeScale > 0);
75919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber}
76019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
76119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Hubervoid MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() {
76219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    const char *mime;
76319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
76419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
76519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
76619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        uint32_t type;
76719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        const void *data;
76819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        size_t size;
76919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        if (mMeta->findData(kKeyAVCC, &type, &data, &size)) {
77019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mCodecSpecificData = malloc(size);
77119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mCodecSpecificDataSize = size;
77219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            memcpy(mCodecSpecificData, data, size);
77319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mGotAllCodecSpecificData = true;
77419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        }
77519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
77619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
77719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        uint32_t type;
77819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        const void *data;
77919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        size_t size;
78019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        if (mMeta->findData(kKeyESDS, &type, &data, &size)) {
78119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            ESDS esds(data, size);
78219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            if (esds.getCodecSpecificInfo(&data, &size) == OK) {
78319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mCodecSpecificData = malloc(size);
78419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mCodecSpecificDataSize = size;
78519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                memcpy(mCodecSpecificData, data, size);
78619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mGotAllCodecSpecificData = true;
78719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            }
78819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        }
78919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
79020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
79120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
79220111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() {
79320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    stop();
79420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
79520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mCodecSpecificData != NULL) {
79620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        free(mCodecSpecificData);
79720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mCodecSpecificData = NULL;
79820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
79920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
80020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
80193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) {
80293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    LOGV("initTrackingProgressStatus");
80393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mPreviousTrackTimeUs = -1;
80493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackingProgressStatus = false;
80593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackEveryTimeDurationUs = 0;
80693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    {
80793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        int64_t timeUs;
80893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) {
80993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            LOGV("Receive request to track progress status for every %lld us", timeUs);
81093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackEveryTimeDurationUs = timeUs;
81193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackingProgressStatus = true;
81293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
81393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
81493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
81593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
8161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong// static
8171c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid *MPEG4Writer::ThreadWrapper(void *me) {
8181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("ThreadWrapper: %p", me);
8191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    MPEG4Writer *writer = static_cast<MPEG4Writer *>(me);
8201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    writer->threadFunc();
8211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return NULL;
8221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
8231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8241c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::bufferChunk(const Chunk& chunk) {
8251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("bufferChunk: %p", chunk.mTrack);
8261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Mutex::Autolock autolock(mLock);
8271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    CHECK_EQ(mDone, false);
8281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
8301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
8311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (chunk.mTrack == it->mTrack) {  // Found owner
8331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            it->mChunks.push_back(chunk);
8341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.signal();
8351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            return;
8361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
8371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
8381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    CHECK("Received a chunk for a unknown track" == 0);
8401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
8411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8421c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::writeFirstChunk(ChunkInfo* info) {
8431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("writeFirstChunk: %p", info->mTrack);
8441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    List<Chunk>::iterator chunkIt = info->mChunks.begin();
8461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<MediaBuffer *>::iterator it = chunkIt->mSamples.begin();
8471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != chunkIt->mSamples.end(); ++it) {
8481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        off_t offset = info->mTrack->isAvc()
8501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                            ? addLengthPrefixedSample_l(*it)
8511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                            : addSample_l(*it);
8521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (it == chunkIt->mSamples.begin()) {
8531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            info->mTrack->addChunkOffset(offset);
8541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
8551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
8561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    // Done with the current chunk.
8581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    // Release all the samples in this chunk.
8591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    while (!chunkIt->mSamples.empty()) {
8601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        List<MediaBuffer *>::iterator it = chunkIt->mSamples.begin();
8611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it)->release();
8621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it) = NULL;
8631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        chunkIt->mSamples.erase(it);
8641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
8651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    chunkIt->mSamples.clear();
8661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    info->mChunks.erase(chunkIt);
8671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
8681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8691c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::writeChunks() {
8701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("writeChunks");
8711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    size_t outstandingChunks = 0;
8721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    while (!mChunkInfos.empty()) {
8731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        List<ChunkInfo>::iterator it = mChunkInfos.begin();
8741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        while (!it->mChunks.empty()) {
8751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            CHECK_EQ(OK, writeOneChunk());
8761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            ++outstandingChunks;
8771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
8781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        it->mTrack = NULL;
8791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkInfos.erase(it);
8801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
8811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mChunkInfos.clear();
8821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGD("%d chunks are written in the last batch", outstandingChunks);
8831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
8841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8851c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::writeOneChunk() {
8861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("writeOneChunk");
8871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    // Find the smallest timestamp, and write that chunk out
8891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    // XXX: What if some track is just too slow?
8901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL;
8911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Track *track = NULL;
8921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
8931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
8941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (!it->mChunks.empty()) {
8951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            List<Chunk>::iterator chunkIt = it->mChunks.begin();
8961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (chunkIt->mTimeStampUs < minTimestampUs) {
8971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                minTimestampUs = chunkIt->mTimeStampUs;
8981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                track = it->mTrack;
8991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            }
9001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
9011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
9021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
9031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (track == NULL) {
9041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        LOGV("Nothing to be written after all");
9051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        return OK;
9061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
9071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
9081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (mIsFirstChunk) {
9091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsFirstChunk = false;
9101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
9111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
9121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
9131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (it->mTrack == track) {
9141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            writeFirstChunk(&(*it));
9151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
9161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
9171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return OK;
9181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
9191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
9201c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::threadFunc() {
9211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("threadFunc");
9221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
9231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    while (!mDone) {
9241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        {
9251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            Mutex::Autolock autolock(mLock);
9261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.wait(mLock);
9271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            CHECK_EQ(writeOneChunk(), OK);
9281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
9291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
9301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
9311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    {
9321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        // Write ALL samples
9331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        Mutex::Autolock autolock(mLock);
9341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        writeChunks();
9351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
9361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
9371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
9381c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::startWriterThread() {
9391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("startWriterThread");
9401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
9411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mDone = false;
9421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsFirstChunk = true;
9431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<Track *>::iterator it = mTracks.begin();
9441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mTracks.end(); ++it) {
9451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        ChunkInfo info;
9461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        info.mTrack = *it;
9471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkInfos.push_back(info);
9481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
9491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
9501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_t attr;
9511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_init(&attr);
9521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
9531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_create(&mThread, &attr, ThreadWrapper, this);
9541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_destroy(&attr);
9551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return OK;
9561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
9571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
95893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) {
959a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (!mDone && mPaused) {
960a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mPaused = false;
961a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mResumed = true;
962a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
963a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
96425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
96593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t startTimeUs;
96619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) {
96719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        startTimeUs = 0;
96819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
96919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
97093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    initTrackingProgressStatus(params);
97193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
972f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    sp<MetaData> meta = new MetaData;
973f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    meta->setInt64(kKeyTime, startTimeUs);
974f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    status_t err = mSource->start(meta.get());
97525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    if (err != OK) {
97625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        mDone = mReachedEOS = true;
97725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return err;
97825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
97920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
98020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_t attr;
98120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_init(&attr);
98220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
98320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
98420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = false;
985c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs = 0;
98625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = false;
987956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    mEstimatedTrackSizeBytes = 0;
98820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
98925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    pthread_create(&mThread, &attr, ThreadWrapper, this);
99020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_destroy(&attr);
99125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
99225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
99320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
99420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
995a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dongvoid MPEG4Writer::Track::pause() {
996a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
997a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
998a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
99920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::Track::stop() {
100020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mDone) {
100120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return;
100220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
100320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
100420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = true;
100520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
100620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *dummy;
100720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_join(mThread, &dummy);
100820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
100920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mSource->stop();
101020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
101120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
101225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() {
101325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return mReachedEOS;
101425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
101525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
101620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static
101720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) {
101820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = static_cast<Track *>(me);
101920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
102020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    track->threadEntry();
102120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
102220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return NULL;
102320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
102420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1025548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber#include <ctype.h>
1026548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huberstatic void hexdump(const void *_data, size_t size) {
1027548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    const uint8_t *data = (const uint8_t *)_data;
1028548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    size_t offset = 0;
1029548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    while (offset < size) {
1030548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        printf("0x%04x  ", offset);
1031548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
1032548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        size_t n = size - offset;
1033548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        if (n > 16) {
1034548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            n = 16;
1035548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        }
1036548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
1037548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        for (size_t i = 0; i < 16; ++i) {
1038548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            if (i == 8) {
1039548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber                printf(" ");
1040548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            }
1041548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
1042548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            if (offset + i < size) {
1043548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber                printf("%02x ", data[offset + i]);
1044548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            } else {
1045548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber                printf("   ");
1046548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            }
1047548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        }
1048548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
1049548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        printf(" ");
1050548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
1051548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        for (size_t i = 0; i < n; ++i) {
1052548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            if (isprint(data[offset + i])) {
1053548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber                printf("%c", data[offset + i]);
1054548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            } else {
1055548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber                printf(".");
1056548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            }
1057548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        }
1058548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
1059548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        printf("\n");
1060548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
1061548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        offset += 16;
1062548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    }
1063548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber}
1064548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
10653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic void getNalUnitType(uint8_t byte, uint8_t* type) {
10663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    LOGV("getNalUnitType: %d", byte);
10673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
10683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // nal_unit_type: 5-bit unsigned integer
10693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *type = (byte & 0x1F);
10703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
10713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
10723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t *findNextStartCode(
10733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length) {
10743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
10753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    LOGV("findNextStartCode: %p %d", data, length);
10763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
10773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t bytesLeft = length;
10783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    while (bytesLeft > 4  &&
10793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            memcmp("\x00\x00\x00\x01", &data[length - bytesLeft], 4)) {
10803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        --bytesLeft;
10813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
10823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (bytesLeft <= 4) {
10833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        bytesLeft = 0; // Last parameter set
10843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
10853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return &data[length - bytesLeft];
10863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
10873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
10883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongconst uint8_t *MPEG4Writer::Track::parseParamSet(
10893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen) {
10903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
10913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    LOGV("parseParamSet");
10923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    CHECK(type == kNalUnitTypeSeqParamSet ||
10933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong          type == kNalUnitTypePicParamSet);
10943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
10953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *nextStartCode = findNextStartCode(data, length);
10963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *paramSetLen = nextStartCode - data;
10973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (*paramSetLen == 0) {
10983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        LOGE("Param set is malformed, since its length is 0");
10993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return NULL;
11003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
11013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
11023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    AVCParamSet paramSet(*paramSetLen, data);
11033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (type == kNalUnitTypeSeqParamSet) {
11043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (*paramSetLen < 4) {
11053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Seq parameter set malformed");
11063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return NULL;
11073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
11083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mSeqParamSets.empty()) {
11093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc = data[1];
11103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileCompatible = data[2];
11113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mLevelIdc = data[3];
11123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
11133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (mProfileIdc != data[1] ||
11143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mProfileCompatible != data[2] ||
11153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mLevelIdc != data[3]) {
11163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                LOGE("Inconsistent profile/level found in seq parameter sets");
11173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return NULL;
11183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
11193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
11203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mSeqParamSets.push_back(paramSet);
11213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    } else {
11223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mPicParamSets.push_back(paramSet);
11233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
11243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return nextStartCode;
11253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
11263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
11273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::copyAVCCodecSpecificData(
11283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
11293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    LOGV("copyAVCCodecSpecificData");
11303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
11313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 2 bytes for each of the parameter set length field
11323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // plus the 7 bytes for the header
11333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (size < 4 + 7) {
11343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        LOGE("Codec specific data length too short: %d", size);
11353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return ERROR_MALFORMED;
11363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
11373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
11383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize = size;
11393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificData = malloc(size);
11403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    memcpy(mCodecSpecificData, data, size);
11413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
11423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
11433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
11443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::parseAVCCodecSpecificData(
11453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
11463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
11473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    LOGV("parseAVCCodecSpecificData");
11483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data starts with a start code.
11493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // SPS and PPS are separated with start codes.
11503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Also, SPS must come before PPS
11513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t type = kNalUnitTypeSeqParamSet;
11523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotSps = false;
11533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotPps = false;
11543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *tmp = data;
11553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *nextStartCode = data;
11563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t bytesLeft = size;
11573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t paramSetLen = 0;
11583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize = 0;
11593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) {
11603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        getNalUnitType(*(tmp + 4), &type);
11613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (type == kNalUnitTypeSeqParamSet) {
11623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (gotPps) {
11633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                LOGE("SPS must come before PPS");
11643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
11653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
11663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
11673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotSps = true;
11683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
11693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
11703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else if (type == kNalUnitTypePicParamSet) {
11713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
11723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                LOGE("SPS must come before PPS");
11733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
11743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
11753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotPps) {
11763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotPps = true;
11773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
11783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
11793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
11803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Only SPS and PPS Nal units are expected");
11813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
11823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
11833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
11843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nextStartCode == NULL) {
11853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
11863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
11873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
11883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Move on to find the next parameter set
11893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        bytesLeft -= nextStartCode - tmp;
11903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        tmp = nextStartCode;
11913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mCodecSpecificDataSize += (2 + paramSetLen);
11923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
11933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
11943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
11953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of seq parameter sets
11963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nSeqParamSets = mSeqParamSets.size();
11973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets == 0) {
11983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Cound not find sequence parameter set");
11993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
12003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
12013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
12023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets > 0x1F) {
12033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Too many seq parameter sets (%d) found", nSeqParamSets);
12043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
12053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
12063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
12073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
12083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
12093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of pic parameter sets
12103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nPicParamSets = mPicParamSets.size();
12113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets == 0) {
12123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Cound not find picture parameter set");
12133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
12143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
12153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets > 0xFF) {
12163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Too many pic parameter sets (%d) found", nPicParamSets);
12173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
12183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
12193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
12203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
12213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
12223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the profiles
12233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // These profiles requires additional parameter set extensions
12243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mProfileIdc == 100 || mProfileIdc == 110 ||
12253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc == 122 || mProfileIdc == 144) {
12263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            LOGE("Sorry, no support for profile_idc: %d!", mProfileIdc);
12273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return BAD_VALUE;
12283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
12293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
12303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
12313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
12323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
1233548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
123403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData(
123503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        const uint8_t *data, size_t size) {
1236548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    // hexdump(data, size);
1237548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
123803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (mCodecSpecificData != NULL) {
1239548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        LOGE("Already have codec specific data");
124003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
124103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
124203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
12433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (size < 4) {
12443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        LOGE("Codec specific data length too short: %d", size);
124503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
124603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
124703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
12483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data is in the form of AVCCodecSpecificData
12493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (memcmp("\x00\x00\x00\x01", data, 4)) {
12503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return copyAVCCodecSpecificData(data, size);
125103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
125203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
12533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (parseAVCCodecSpecificData(data, size) != OK) {
125403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
125503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
125603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
12573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // ISO 14496-15: AVC file format
12583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize += 7;  // 7 more bytes in the header
125903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    mCodecSpecificData = malloc(mCodecSpecificDataSize);
126003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    uint8_t *header = (uint8_t *)mCodecSpecificData;
12613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = 1;                     // version
12623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[1] = mProfileIdc;           // profile indication
12633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[2] = mProfileCompatible;    // profile compatibility
12643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[3] = mLevelIdc;
126503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
12663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne
126703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR
126803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[4] = 0xfc | 3;  // length size == 4 bytes
126903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else
127003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    header[4] = 0xfc | 1;  // length size == 2 bytes
127103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif
127203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
12733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 3-bit '111' followed by 5-bit numSequenceParameterSets
12743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nSequenceParamSets = mSeqParamSets.size();
12753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[5] = 0xe0 | nSequenceParamSets;
12763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 6;
12773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mSeqParamSets.begin();
12783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mSeqParamSets.end(); ++it) {
12793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit sequence parameter set length
12803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t seqParamSetLength = it->mLength;
12813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = seqParamSetLength >> 8;
12823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = seqParamSetLength & 0xff;
12833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
12843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // SPS NAL unit (sequence parameter length bytes)
12853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, seqParamSetLength);
12863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + seqParamSetLength);
12873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
12883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
12893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 8-bit nPictureParameterSets
12903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nPictureParamSets = mPicParamSets.size();
12913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = nPictureParamSets;
12923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 1;
12933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mPicParamSets.begin();
12943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mPicParamSets.end(); ++it) {
12953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit picture parameter set length
12963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t picParamSetLength = it->mLength;
12973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = picParamSetLength >> 8;
12983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = picParamSetLength & 0xff;
12993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
13003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // PPS Nal unit (picture parameter set length bytes)
13013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, picParamSetLength);
13023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + picParamSetLength);
13033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
130403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
130503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    return OK;
130603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
130703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
13088644c14618d30d9e57a69df40ed939986ebf02c4James Dongstatic bool collectStatisticalData() {
13098644c14618d30d9e57a69df40ed939986ebf02c4James Dong    char value[PROPERTY_VALUE_MAX];
13108644c14618d30d9e57a69df40ed939986ebf02c4James Dong    if (property_get("media.stagefright.record-stats", value, NULL)
13118644c14618d30d9e57a69df40ed939986ebf02c4James Dong        && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
13128644c14618d30d9e57a69df40ed939986ebf02c4James Dong        return true;
13138644c14618d30d9e57a69df40ed939986ebf02c4James Dong    }
13148644c14618d30d9e57a69df40ed939986ebf02c4James Dong    return false;
13158644c14618d30d9e57a69df40ed939986ebf02c4James Dong}
13168644c14618d30d9e57a69df40ed939986ebf02c4James Dong
131720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::Track::threadEntry() {
131830ab66297501757d745b9ae10da61adcd891f497Andreas Huber    int32_t count = 0;
131913aec890216948b0c364f8f92792129d0335f506James Dong    const int64_t interleaveDurationUs = mOwner->interleaveDuration();
132013aec890216948b0c364f8f92792129d0335f506James Dong    int64_t chunkTimestampUs = 0;
132113aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nChunks = 0;
132213aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nZeroLengthFrames = 0;
13238f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t lastTimestampUs = 0;  // Previous sample time stamp in ms
13248f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t lastDurationUs = 0;   // Between the previous two samples in ms
13258f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int32_t sampleCount = 1;      // Sample count in the current stts table entry
1326be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    uint32_t previousSampleSize = 0;  // Size of the previous sample
1327a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    int64_t previousPausedDurationUs = 0;
13281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    int64_t timestampUs;
1329d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong    sp<MetaData> meta_data;
13308644c14618d30d9e57a69df40ed939986ebf02c4James Dong    bool collectStats = collectStatisticalData();
133120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1332ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    mNumSamples = 0;
13331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mMaxWriteTimeUs = 0;
133493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t err = OK;
133520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBuffer *buffer;
133693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    while (!mDone && (err = mSource->read(&buffer)) == OK) {
133720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (buffer->range_length() == 0) {
133820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer->release();
133920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer = NULL;
134013aec890216948b0c364f8f92792129d0335f506James Dong            ++nZeroLengthFrames;
134120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            continue;
134220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
134320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1344a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // If the codec specific data has not been received yet, delay pause.
1345a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // After the codec specific data is received, discard what we received
1346a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // when the track is to be paused.
1347a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused && !mResumed) {
1348a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer->release();
1349a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer = NULL;
1350a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            continue;
1351a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
1352a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
135330ab66297501757d745b9ae10da61adcd891f497Andreas Huber        ++count;
135430ab66297501757d745b9ae10da61adcd891f497Andreas Huber
135503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        int32_t isCodecConfig;
135603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig)
135703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                && isCodecConfig) {
1358548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            CHECK(!mGotAllCodecSpecificData);
1359548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
13601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (mIsAvc) {
136103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                status_t err = makeAVCCodecSpecificData(
136203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        (const uint8_t *)buffer->data()
136303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                            + buffer->range_offset(),
136403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        buffer->range_length());
1365be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                CHECK_EQ(OK, err);
13661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            } else if (mIsMPEG4) {
136703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificDataSize = buffer->range_length();
136803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificData = malloc(mCodecSpecificDataSize);
136903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                memcpy(mCodecSpecificData,
137003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        (const uint8_t *)buffer->data()
137103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                            + buffer->range_offset(),
137203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                       buffer->range_length());
137330ab66297501757d745b9ae10da61adcd891f497Andreas Huber            }
137430ab66297501757d745b9ae10da61adcd891f497Andreas Huber
137530ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer->release();
137630ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer = NULL;
137730ab66297501757d745b9ae10da61adcd891f497Andreas Huber
1378548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            mGotAllCodecSpecificData = true;
137930ab66297501757d745b9ae10da61adcd891f497Andreas Huber            continue;
1380548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber        } else if (!mGotAllCodecSpecificData &&
13811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                count == 1 && mIsMPEG4 && mCodecSpecificData == NULL) {
138203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            // The TI mpeg4 encoder does not properly set the
138303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            // codec-specific-data flag.
138430ab66297501757d745b9ae10da61adcd891f497Andreas Huber
138520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            const uint8_t *data =
138620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                (const uint8_t *)buffer->data() + buffer->range_offset();
138720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
138820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            const size_t size = buffer->range_length();
138920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
139020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            size_t offset = 0;
139120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (offset + 3 < size) {
139220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (data[offset] == 0x00 && data[offset + 1] == 0x00
139320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    && data[offset + 2] == 0x01 && data[offset + 3] == 0xb6) {
139420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    break;
139520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
139620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
139720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                ++offset;
139820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
139920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14000c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber            // CHECK(offset + 3 < size);
1401bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber            if (offset + 3 >= size) {
1402bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber                // XXX assume the entire first chunk of data is the codec specific
1403bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber                // data.
1404bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber                offset = size;
1405bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber            }
140620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
140720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mCodecSpecificDataSize = offset;
140820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mCodecSpecificData = malloc(offset);
140920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            memcpy(mCodecSpecificData, data, offset);
141020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
141120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer->set_range(buffer->range_offset() + offset, size - offset);
141203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
141303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            if (size == offset) {
141403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                buffer->release();
141503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                buffer = NULL;
141603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
141703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                continue;
141803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            }
1419548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
1420548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            mGotAllCodecSpecificData = true;
14211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        } else if (!mGotAllCodecSpecificData && mIsAvc && count < 3) {
142203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            // The TI video encoder does not flag codec specific data
142303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            // as such and also splits up SPS and PPS across two buffers.
142403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
142503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            const uint8_t *data =
142603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                (const uint8_t *)buffer->data() + buffer->range_offset();
142703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
142803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            size_t size = buffer->range_length();
142903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
143003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            CHECK(count == 2 || mCodecSpecificData == NULL);
143103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
143203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            size_t offset = mCodecSpecificDataSize;
143303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            mCodecSpecificDataSize += size + 4;
143403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            mCodecSpecificData =
143503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                realloc(mCodecSpecificData, mCodecSpecificDataSize);
143603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
143703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            memcpy((uint8_t *)mCodecSpecificData + offset,
143803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                   "\x00\x00\x00\x01", 4);
143903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
144003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            memcpy((uint8_t *)mCodecSpecificData + offset + 4, data, size);
144103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
144203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            buffer->release();
144303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            buffer = NULL;
144403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
144503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            if (count == 2) {
144603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                void *tmp = mCodecSpecificData;
144703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                size = mCodecSpecificDataSize;
144803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificData = NULL;
144903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificDataSize = 0;
145003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
145103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                status_t err = makeAVCCodecSpecificData(
145203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        (const uint8_t *)tmp, size);
145303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                free(tmp);
145403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                tmp = NULL;
1455be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                CHECK_EQ(OK, err);
1456548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
1457548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber                mGotAllCodecSpecificData = true;
145803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            }
145903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
146003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber            continue;
146120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
146220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1463a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (!mGotAllCodecSpecificData) {
1464a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mGotAllCodecSpecificData = true;
1465a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
1466a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
1467d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // Make a deep copy of the MediaBuffer and Metadata and release
1468d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // the original as soon as we can
1469d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        MediaBuffer *copy = new MediaBuffer(buffer->range_length());
1470d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(),
1471d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong                buffer->range_length());
1472d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        copy->set_range(0, buffer->range_length());
1473d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data = new MetaData(*buffer->meta_data().get());
1474d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer->release();
1475d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer = NULL;
1476d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
14771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (mIsAvc) StripStartcode(copy);
1478e136c3bb38e88315bf8797a464ebf2c788296b22James Dong
14798644c14618d30d9e57a69df40ed939986ebf02c4James Dong        size_t sampleSize;
14801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        sampleSize = mIsAvc
148103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR
1482d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong                ? copy->range_length() + 4
148303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else
1484d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong                ? copy->range_length() + 2
148503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif
1486d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong                : copy->range_length();
1487050b28a593350047845a45a14cc5026221ac1620James Dong
1488d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        // Max file size or duration handling
14898644c14618d30d9e57a69df40ed939986ebf02c4James Dong        mEstimatedTrackSizeBytes += sampleSize;
1490d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileSizeLimit()) {
1491d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
1492d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
1493d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
1494d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileDurationLimit()) {
1495d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
1496d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
1497d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
1498d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1499050b28a593350047845a45a14cc5026221ac1620James Dong
1500d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        int32_t isSync = false;
1501d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data->findInt32(kKeyIsSyncFrame, &isSync);
1502d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
1503d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        CHECK(meta_data->findInt64(kKeyTime, &timestampUs));
1504d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
1505d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong////////////////////////////////////////////////////////////////////////////////
15068644c14618d30d9e57a69df40ed939986ebf02c4James Dong        if (mSampleSizes.empty()) {
1507f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mStartTimestampUs = timestampUs;
1508f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mOwner->setStartTimestampUs(mStartTimestampUs);
15093c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        }
151048c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber
1511a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mResumed) {
1512c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong            previousPausedDurationUs += (timestampUs - mTrackDurationUs - lastDurationUs);
1513a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mResumed = false;
1514a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
1515a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
1516a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        timestampUs -= previousPausedDurationUs;
1517a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        LOGV("time stamp: %lld and previous paused duration %lld",
1518a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                timestampUs, previousPausedDurationUs);
1519c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong        if (timestampUs > mTrackDurationUs) {
1520c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong            mTrackDurationUs = timestampUs;
15213b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber        }
15223b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber
15238644c14618d30d9e57a69df40ed939986ebf02c4James Dong        mSampleSizes.push_back(sampleSize);
1524ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong        ++mNumSamples;
1525ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong        if (mNumSamples > 2) {
15268644c14618d30d9e57a69df40ed939986ebf02c4James Dong            if (lastDurationUs != timestampUs - lastTimestampUs) {
15278f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong                SttsTableEntry sttsEntry(sampleCount, lastDurationUs);
1528be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mSttsTableEntries.push_back(sttsEntry);
1529be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                sampleCount = 1;
1530be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            } else {
1531be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                ++sampleCount;
1532be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
1533be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
1534be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        if (mSamplesHaveSameSize) {
1535ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong            if (mNumSamples >= 2 && previousSampleSize != sampleSize) {
1536be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mSamplesHaveSameSize = false;
1537be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
15388644c14618d30d9e57a69df40ed939986ebf02c4James Dong            previousSampleSize = sampleSize;
1539be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
15408644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastDurationUs = timestampUs - lastTimestampUs;
15418644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastTimestampUs = timestampUs;
154220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1543d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        if (isSync != 0) {
1544ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong            mStssTableEntries.push_back(mNumSamples);
1545d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        }
1546d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
154793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (mTrackingProgressStatus) {
154893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            if (mPreviousTrackTimeUs <= 0) {
154993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong                mPreviousTrackTimeUs = mStartTimestampUs;
155093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            }
1551faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong            trackProgressStatus(timestampUs);
155293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
155358ae9c530247668f8af36e30d228c716c226b3d4James Dong        if (mOwner->numTracks() == 1) {
15541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            off_t offset = mIsAvc? mOwner->addLengthPrefixedSample_l(copy)
155558ae9c530247668f8af36e30d228c716c226b3d4James Dong                                 : mOwner->addSample_l(copy);
155658ae9c530247668f8af36e30d228c716c226b3d4James Dong            if (mChunkOffsets.empty()) {
155758ae9c530247668f8af36e30d228c716c226b3d4James Dong                mChunkOffsets.push_back(offset);
155858ae9c530247668f8af36e30d228c716c226b3d4James Dong            }
155958ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy->release();
156058ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy = NULL;
156158ae9c530247668f8af36e30d228c716c226b3d4James Dong            continue;
156258ae9c530247668f8af36e30d228c716c226b3d4James Dong        }
156313aec890216948b0c364f8f92792129d0335f506James Dong
156413aec890216948b0c364f8f92792129d0335f506James Dong        mChunkSamples.push_back(copy);
156513aec890216948b0c364f8f92792129d0335f506James Dong        if (interleaveDurationUs == 0) {
156613aec890216948b0c364f8f92792129d0335f506James Dong            StscTableEntry stscEntry(++nChunks, 1, 1);
156713aec890216948b0c364f8f92792129d0335f506James Dong            mStscTableEntries.push_back(stscEntry);
15681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            bufferChunk(timestampUs);
156913aec890216948b0c364f8f92792129d0335f506James Dong        } else {
157013aec890216948b0c364f8f92792129d0335f506James Dong            if (chunkTimestampUs == 0) {
157113aec890216948b0c364f8f92792129d0335f506James Dong                chunkTimestampUs = timestampUs;
157213aec890216948b0c364f8f92792129d0335f506James Dong            } else {
157313aec890216948b0c364f8f92792129d0335f506James Dong                if (timestampUs - chunkTimestampUs > interleaveDurationUs) {
157413aec890216948b0c364f8f92792129d0335f506James Dong                    ++nChunks;
15758644c14618d30d9e57a69df40ed939986ebf02c4James Dong                    if (collectStats) {
15768644c14618d30d9e57a69df40ed939986ebf02c4James Dong                        mChunkDurations.push_back(timestampUs - chunkTimestampUs);
15778644c14618d30d9e57a69df40ed939986ebf02c4James Dong                    }
157813aec890216948b0c364f8f92792129d0335f506James Dong                    if (nChunks == 1 ||  // First chunk
157913aec890216948b0c364f8f92792129d0335f506James Dong                        (--(mStscTableEntries.end()))->samplesPerChunk !=
158013aec890216948b0c364f8f92792129d0335f506James Dong                         mChunkSamples.size()) {
158113aec890216948b0c364f8f92792129d0335f506James Dong                        StscTableEntry stscEntry(nChunks,
158213aec890216948b0c364f8f92792129d0335f506James Dong                                mChunkSamples.size(), 1);
158313aec890216948b0c364f8f92792129d0335f506James Dong                        mStscTableEntries.push_back(stscEntry);
158413aec890216948b0c364f8f92792129d0335f506James Dong                    }
15851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                    bufferChunk(timestampUs);
158613aec890216948b0c364f8f92792129d0335f506James Dong                    chunkTimestampUs = timestampUs;
158713aec890216948b0c364f8f92792129d0335f506James Dong                }
158813aec890216948b0c364f8f92792129d0335f506James Dong            }
158913aec890216948b0c364f8f92792129d0335f506James Dong        }
159013aec890216948b0c364f8f92792129d0335f506James Dong
159120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
159225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
15938644c14618d30d9e57a69df40ed939986ebf02c4James Dong    if (mSampleSizes.empty()) {
159493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        err = UNKNOWN_ERROR;
1595f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong    }
1596faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    mOwner->trackProgressStatus(this, -1, err);
1597be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
159813aec890216948b0c364f8f92792129d0335f506James Dong    // Last chunk
159958ae9c530247668f8af36e30d228c716c226b3d4James Dong    if (mOwner->numTracks() == 1) {
1600ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong        StscTableEntry stscEntry(1, mNumSamples, 1);
160158ae9c530247668f8af36e30d228c716c226b3d4James Dong        mStscTableEntries.push_back(stscEntry);
160258ae9c530247668f8af36e30d228c716c226b3d4James Dong    } else if (!mChunkSamples.empty()) {
160313aec890216948b0c364f8f92792129d0335f506James Dong        ++nChunks;
160413aec890216948b0c364f8f92792129d0335f506James Dong        StscTableEntry stscEntry(nChunks, mChunkSamples.size(), 1);
160513aec890216948b0c364f8f92792129d0335f506James Dong        mStscTableEntries.push_back(stscEntry);
16061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        bufferChunk(timestampUs);
160713aec890216948b0c364f8f92792129d0335f506James Dong    }
160813aec890216948b0c364f8f92792129d0335f506James Dong
1609be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // We don't really know how long the last frame lasts, since
1610be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // there is no frame time after it, just repeat the previous
1611be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // frame's duration.
1612ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong    if (mNumSamples == 1) {
16138f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        lastDurationUs = 0;  // A single sample's duration
1614be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    } else {
1615be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        ++sampleCount;  // Count for the last sample
1616be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    }
16178f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    SttsTableEntry sttsEntry(sampleCount, lastDurationUs);
1618be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    mSttsTableEntries.push_back(sttsEntry);
1619c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs += lastDurationUs;
162025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = true;
16211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. Max write time: %lld us - %s",
16221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            count, nZeroLengthFrames, mNumSamples, mMaxWriteTimeUs, mIsAudio? "audio": "video");
1623365a963142093a1cd8efdcea76b5f65096a5b115James Dong
16241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    logStatisticalData(mIsAudio);
1625365a963142093a1cd8efdcea76b5f65096a5b115James Dong}
1626365a963142093a1cd8efdcea76b5f65096a5b115James Dong
1627faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) {
1628faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    LOGV("trackProgressStatus: %lld us", timeUs);
1629215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    if (mTrackEveryTimeDurationUs > 0 &&
1630215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) {
163193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        LOGV("Fire time tracking progress status at %lld us", timeUs);
1632faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        mOwner->trackProgressStatus(this, timeUs - mPreviousTrackTimeUs, err);
163393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        mPreviousTrackTimeUs = timeUs;
163493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
163593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
163693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
1637faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::trackProgressStatus(
1638faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        const MPEG4Writer::Track* track, int64_t timeUs, status_t err) {
1639faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    Mutex::Autolock lock(mLock);
1640faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    int32_t nTracks = mTracks.size();
1641faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    CHECK(nTracks >= 1);
1642faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    CHECK(nTracks < 64);  // Arbitrary number
1643faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
1644faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    int32_t trackNum = 0;
1645faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong#if 0
1646faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // In the worst case, we can put the trackNum
1647faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // along with MEDIA_RECORDER_INFO_COMPLETION_STATUS
1648faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // to report the progress.
1649faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    for (List<Track *>::iterator it = mTracks.begin();
1650faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong         it != mTracks.end(); ++it, ++trackNum) {
1651faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        if (track == (*it)) {
1652faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong            break;
1653faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        }
1654faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
1655faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong#endif
1656faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    CHECK(trackNum < nTracks);
1657faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    trackNum <<= 16;
1658faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
1659faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Error notification
1660faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Do not consider ERROR_END_OF_STREAM an error
1661faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (err != OK && err != ERROR_END_OF_STREAM) {
1662faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        notify(MEDIA_RECORDER_EVENT_ERROR,
1663faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               trackNum | MEDIA_RECORDER_ERROR_UNKNOWN,
1664faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
1665faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        return;
1666faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
1667faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
1668faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (timeUs == -1) {
1669faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send completion notification
1670faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        notify(MEDIA_RECORDER_EVENT_INFO,
1671faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               trackNum | MEDIA_RECORDER_INFO_COMPLETION_STATUS,
1672faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
1673faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        return;
1674faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    } else {
1675faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send progress status
1676faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        notify(MEDIA_RECORDER_EVENT_INFO,
1677faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               trackNum | MEDIA_RECORDER_INFO_PROGRESS_TIME_STATUS,
1678faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               timeUs / 1000);
1679faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
1680faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong}
1681faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
1682215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dongvoid MPEG4Writer::Track::findMinAvgMaxSampleDurationMs(
1683215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        int32_t *min, int32_t *avg, int32_t *max) {
16848644c14618d30d9e57a69df40ed939986ebf02c4James Dong    CHECK(!mSampleSizes.empty());
1685c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    int32_t avgSampleDurationMs = mTrackDurationUs / 1000 / mNumSamples;
1686215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    int32_t minSampleDurationMs = 0x7FFFFFFF;
1687215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    int32_t maxSampleDurationMs = 0;
1688365a963142093a1cd8efdcea76b5f65096a5b115James Dong    for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin();
1689365a963142093a1cd8efdcea76b5f65096a5b115James Dong        it != mSttsTableEntries.end(); ++it) {
16908f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int32_t sampleDurationMs =
16918f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            (static_cast<int32_t>(it->sampleDurationUs) + 500) / 1000;
1692215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        if (sampleDurationMs > maxSampleDurationMs) {
1693215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong            maxSampleDurationMs = sampleDurationMs;
1694215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        } else if (sampleDurationMs < minSampleDurationMs) {
1695215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong            minSampleDurationMs = sampleDurationMs;
1696365a963142093a1cd8efdcea76b5f65096a5b115James Dong        }
1697215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        LOGI("sample duration: %d ms", sampleDurationMs);
1698365a963142093a1cd8efdcea76b5f65096a5b115James Dong    }
1699215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    CHECK(minSampleDurationMs != 0);
1700215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    CHECK(avgSampleDurationMs != 0);
1701215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    CHECK(maxSampleDurationMs != 0);
1702215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    *min = minSampleDurationMs;
1703215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    *avg = avgSampleDurationMs;
1704215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    *max = maxSampleDurationMs;
1705365a963142093a1cd8efdcea76b5f65096a5b115James Dong}
1706365a963142093a1cd8efdcea76b5f65096a5b115James Dong
1707365a963142093a1cd8efdcea76b5f65096a5b115James Dong// Don't count the last duration
1708365a963142093a1cd8efdcea76b5f65096a5b115James Dongvoid MPEG4Writer::Track::findMinMaxChunkDurations(int64_t *min, int64_t *max) {
1709365a963142093a1cd8efdcea76b5f65096a5b115James Dong    int64_t duration = mOwner->interleaveDuration();
1710365a963142093a1cd8efdcea76b5f65096a5b115James Dong    int64_t minChunkDuration = duration;
1711365a963142093a1cd8efdcea76b5f65096a5b115James Dong    int64_t maxChunkDuration = duration;
1712365a963142093a1cd8efdcea76b5f65096a5b115James Dong    if (mChunkDurations.size() > 1) {
1713365a963142093a1cd8efdcea76b5f65096a5b115James Dong        for (List<int64_t>::iterator it = mChunkDurations.begin();
1714365a963142093a1cd8efdcea76b5f65096a5b115James Dong            it != --mChunkDurations.end(); ++it) {
1715365a963142093a1cd8efdcea76b5f65096a5b115James Dong            if (minChunkDuration > (*it)) {
1716365a963142093a1cd8efdcea76b5f65096a5b115James Dong                minChunkDuration = (*it);
1717365a963142093a1cd8efdcea76b5f65096a5b115James Dong            } else if (maxChunkDuration < (*it)) {
1718365a963142093a1cd8efdcea76b5f65096a5b115James Dong                maxChunkDuration = (*it);
1719365a963142093a1cd8efdcea76b5f65096a5b115James Dong            }
1720365a963142093a1cd8efdcea76b5f65096a5b115James Dong        }
1721365a963142093a1cd8efdcea76b5f65096a5b115James Dong    }
1722365a963142093a1cd8efdcea76b5f65096a5b115James Dong    *min = minChunkDuration;
1723365a963142093a1cd8efdcea76b5f65096a5b115James Dong    *max = maxChunkDuration;
1724365a963142093a1cd8efdcea76b5f65096a5b115James Dong}
1725365a963142093a1cd8efdcea76b5f65096a5b115James Dong
1726365a963142093a1cd8efdcea76b5f65096a5b115James Dongvoid MPEG4Writer::Track::logStatisticalData(bool isAudio) {
1727c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    if (mTrackDurationUs <= 0 || mSampleSizes.empty()) {
1728365a963142093a1cd8efdcea76b5f65096a5b115James Dong        LOGI("nothing is recorded");
1729365a963142093a1cd8efdcea76b5f65096a5b115James Dong        return;
1730365a963142093a1cd8efdcea76b5f65096a5b115James Dong    }
1731365a963142093a1cd8efdcea76b5f65096a5b115James Dong
17328644c14618d30d9e57a69df40ed939986ebf02c4James Dong    bool collectStats = collectStatisticalData();
1733365a963142093a1cd8efdcea76b5f65096a5b115James Dong
1734365a963142093a1cd8efdcea76b5f65096a5b115James Dong    if (collectStats) {
1735215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        LOGI("%s track - duration %lld us, total %d frames",
1736c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong                isAudio? "audio": "video", mTrackDurationUs,
1737ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong                mNumSamples);
1738215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        int32_t min, avg, max;
1739215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        findMinAvgMaxSampleDurationMs(&min, &avg, &max);
1740215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        LOGI("min/avg/max sample duration (ms): %d/%d/%d", min, avg, max);
1741215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        if (!isAudio) {
1742215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong            float avgFps = 1000.0 / avg;
1743215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong            float minFps = 1000.0 / max;
1744215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong            float maxFps = 1000.0 / min;
1745365a963142093a1cd8efdcea76b5f65096a5b115James Dong            LOGI("min/avg/max frame rate (fps): %.2f/%.2f/%.2f",
1746215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong                minFps, avgFps, maxFps);
1747365a963142093a1cd8efdcea76b5f65096a5b115James Dong        }
1748365a963142093a1cd8efdcea76b5f65096a5b115James Dong
1749365a963142093a1cd8efdcea76b5f65096a5b115James Dong        int64_t totalBytes = 0;
17508644c14618d30d9e57a69df40ed939986ebf02c4James Dong        for (List<size_t>::iterator it = mSampleSizes.begin();
17518644c14618d30d9e57a69df40ed939986ebf02c4James Dong            it != mSampleSizes.end(); ++it) {
17528644c14618d30d9e57a69df40ed939986ebf02c4James Dong            totalBytes += (*it);
1753365a963142093a1cd8efdcea76b5f65096a5b115James Dong        }
1754c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong        float bitRate = (totalBytes * 8000000.0) / mTrackDurationUs;
1755365a963142093a1cd8efdcea76b5f65096a5b115James Dong        LOGI("avg bit rate (bps): %.2f", bitRate);
1756365a963142093a1cd8efdcea76b5f65096a5b115James Dong
1757365a963142093a1cd8efdcea76b5f65096a5b115James Dong        int64_t duration = mOwner->interleaveDuration();
1758365a963142093a1cd8efdcea76b5f65096a5b115James Dong        if (duration != 0) {  // If interleaving is enabled
1759365a963142093a1cd8efdcea76b5f65096a5b115James Dong            int64_t minChunk, maxChunk;
1760365a963142093a1cd8efdcea76b5f65096a5b115James Dong            findMinMaxChunkDurations(&minChunk, &maxChunk);
1761365a963142093a1cd8efdcea76b5f65096a5b115James Dong            LOGI("min/avg/max chunk duration (ms): %lld/%lld/%lld",
1762365a963142093a1cd8efdcea76b5f65096a5b115James Dong                minChunk, duration, maxChunk);
1763365a963142093a1cd8efdcea76b5f65096a5b115James Dong        }
1764365a963142093a1cd8efdcea76b5f65096a5b115James Dong    }
176513aec890216948b0c364f8f92792129d0335f506James Dong}
176613aec890216948b0c364f8f92792129d0335f506James Dong
17671c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::Track::bufferChunk(int64_t timestampUs) {
17681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    LOGV("bufferChunk");
17691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    int64_t startTimeUs = systemTime() / 1000;
17711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Chunk chunk(this, timestampUs, mChunkSamples);
17721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mOwner->bufferChunk(chunk);
177313aec890216948b0c364f8f92792129d0335f506James Dong    mChunkSamples.clear();
17741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    int64_t endTimeUs = systemTime() / 1000;
17751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (mMaxWriteTimeUs < endTimeUs - startTimeUs) {
17761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mMaxWriteTimeUs = endTimeUs - startTimeUs;
17771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
177820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
177920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
17803b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const {
1781c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    return mTrackDurationUs;
178220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
178320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1784d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const {
1785d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return mEstimatedTrackSizeBytes;
1786d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
1787d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
17881acfe8649f8169caf2ff098c2dc2de880d9a3760James Dongvoid MPEG4Writer::Track::writeTrackHeader(
17891acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        int32_t trackID, bool use32BitOffset) {
179020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const char *mime;
179120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool success = mMeta->findCString(kKeyMIMEType, &mime);
17920c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(success);
179320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
17948f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    LOGV("%s track time scale: %d",
17951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsAudio? "Audio": "Video", mTimeScale);
17968f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
179720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
179820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    time_t now = time(NULL);
17998f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int32_t mvhdTimeScale = mOwner->getTimeScale();
18008f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t trakDurationUs = getDurationUs();
180120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
180220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOwner->beginBox("trak");
180320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
180420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->beginBox("tkhd");
18051acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        // Flags = 7 to indicate that the track is enabled, and
18061acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        // part of the presentation
18071acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        mOwner->writeInt32(0x07);          // version=0, flags=7
180820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(now);           // creation time
180920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(now);           // modification time
181020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(trackID);
181120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);             // reserved
18128f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int32_t tkhdDuration =
18138f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
18148f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        mOwner->writeInt32(tkhdDuration);  // in mvhd timescale
181520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);             // reserved
181620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);             // reserved
181720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt16(0);             // layer
181820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt16(0);             // alternate group
18191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mOwner->writeInt16(mIsAudio ? 0x100 : 0);  // volume
182020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt16(0);             // reserved
182120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
182220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0x10000);       // matrix
182320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
182420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
182520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
182620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0x10000);
182720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
182820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
182920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0);
183020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->writeInt32(0x40000000);
183120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
18321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (mIsAudio) {
183320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);
183420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);
183520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        } else {
183620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            int32_t width, height;
183720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            bool success = mMeta->findInt32(kKeyWidth, &width);
183820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            success = success && mMeta->findInt32(kKeyHeight, &height);
18390c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber            CHECK(success);
184020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1841050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->writeInt32(width << 16);   // 32-bit fixed-point value
1842050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->writeInt32(height << 16);  // 32-bit fixed-point value
184320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
184420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->endBox();  // tkhd
184520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1846f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong      int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
1847f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong      if (mStartTimestampUs != moovStartTimeUs) {
18483c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        mOwner->beginBox("edts");
18493c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong          mOwner->beginBox("elst");
18501acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong            mOwner->writeInt32(0);           // version=0, flags=0: 32-bit time
18511acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong            mOwner->writeInt32(2);           // never ends with an empty list
18528f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
18538f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            // First elst entry: specify the starting time offset
18548f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            int64_t offsetUs = mStartTimestampUs - moovStartTimeUs;
18558f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            int32_t seg = (offsetUs * mvhdTimeScale + 5E5) / 1E6;
18568f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            mOwner->writeInt32(seg);         // in mvhd timecale
18578f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            mOwner->writeInt32(-1);          // starting time offset
18588f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            mOwner->writeInt32(1 << 16);     // rate = 1.0
18598f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
18608f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            // Second elst entry: specify the track duration
18618f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            seg = (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
18628f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            mOwner->writeInt32(seg);         // in mvhd timescale
18631acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong            mOwner->writeInt32(0);
18641acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong            mOwner->writeInt32(1 << 16);
18653c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong          mOwner->endBox();
18663c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        mOwner->endBox();
18673c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong      }
18683c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
186920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->beginBox("mdia");
187020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
187120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("mdhd");
187220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // version=0, flags=0
187320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(now);           // creation time
187420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(now);           // modification time
18758f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong          mOwner->writeInt32(mTimeScale);    // media timescale
18768f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong          int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6;
18778f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong          mOwner->writeInt32(mdhdDuration);  // use media timescale
18781acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // Language follows the three letter standard ISO-639-2/T
18791acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // 'e', 'n', 'g' for "English", for instance.
18801acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // Each character is packed as the difference between its ASCII value and 0x60.
18811acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // For "English", these are 00101, 01110, 00111.
18821acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // XXX: Where is the padding bit located: 0x15C7?
18831acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          mOwner->writeInt16(0);             // language code
188420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt16(0);             // predefined
188520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->endBox();
188620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
188720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("hdlr");
188820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // version=0, flags=0
1889050b28a593350047845a45a14cc5026221ac1620James Dong          mOwner->writeInt32(0);             // component type: should be mhlr
18901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong          mOwner->writeFourcc(mIsAudio ? "soun" : "vide");  // component subtype
189120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // reserved
189220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // reserved
189320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->writeInt32(0);             // reserved
18941acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          // Removing "r" for the name string just makes the string 4 byte aligned
18951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong          mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle");  // name
189620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->endBox();
189720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
189820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("minf");
18991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong          if (mIsAudio) {
190020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->beginBox("smhd");
190120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt32(0);           // version=0, flags=0
190220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // balance
190320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // reserved
190420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->endBox();
190520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          } else {
190620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->beginBox("vmhd");
19071acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong              mOwner->writeInt32(0x01);        // version=0, flags=1
190820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // graphics mode
190920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);           // opcolor
191020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);
191120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->writeInt16(0);
191220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber              mOwner->endBox();
191320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          }
1914050b28a593350047845a45a14cc5026221ac1620James Dong
1915050b28a593350047845a45a14cc5026221ac1620James Dong          mOwner->beginBox("dinf");
1916050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->beginBox("dref");
1917050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->writeInt32(0);  // version=0, flags=0
19181acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong              mOwner->writeInt32(1);  // entry count (either url or urn)
19191acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong              // The table index here refers to the sample description index
19201acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong              // in the sample table entries.
1921050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->beginBox("url ");
19221acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                mOwner->writeInt32(1);  // version=0, flags=1 (self-contained)
1923050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->endBox();  // url
1924050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->endBox();  // dref
1925050b28a593350047845a45a14cc5026221ac1620James Dong          mOwner->endBox();  // dinf
1926050b28a593350047845a45a14cc5026221ac1620James Dong
192720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->beginBox("stbl");
192820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
192920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stsd");
193020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);               // version=0, flags=0
193120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(1);               // entry count
19321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (mIsAudio) {
193325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                const char *fourcc = NULL;
193418291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) {
193525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    fourcc = "samr";
193618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
193725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    fourcc = "sawb";
1938050b28a593350047845a45a14cc5026221ac1620James Dong                } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
1939050b28a593350047845a45a14cc5026221ac1620James Dong                    fourcc = "mp4a";
194025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                } else {
194125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    LOGE("Unknown mime type '%s'.", mime);
194225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    CHECK(!"should not be here, unknown mime type.");
194325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                }
194425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
194525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                mOwner->beginBox(fourcc);          // audio format
194620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
194720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
1948050b28a593350047845a45a14cc5026221ac1620James Dong                  mOwner->writeInt16(0x1);         // data ref index
194920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
195020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
1951050b28a593350047845a45a14cc5026221ac1620James Dong                  int32_t nChannels;
1952050b28a593350047845a45a14cc5026221ac1620James Dong                  CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels));
1953050b28a593350047845a45a14cc5026221ac1620James Dong                  mOwner->writeInt16(nChannels);   // channel count
195420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(16);          // sample size
195520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // predefined
195620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
195720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
195820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  int32_t samplerate;
195920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  bool success = mMeta->findInt32(kKeySampleRate, &samplerate);
19600c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                  CHECK(success);
196120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
196220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(samplerate << 16);
1963050b28a593350047845a45a14cc5026221ac1620James Dong                  if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
1964050b28a593350047845a45a14cc5026221ac1620James Dong                    mOwner->beginBox("esds");
1965050b28a593350047845a45a14cc5026221ac1620James Dong
1966050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt32(0);     // version=0, flags=0
1967050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x03);   // ES_DescrTag
1968050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(23 + mCodecSpecificDataSize);
1969050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt16(0x0000);// ES_ID
1970050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x00);
1971050b28a593350047845a45a14cc5026221ac1620James Dong
1972050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x04);   // DecoderConfigDescrTag
1973050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(15 + mCodecSpecificDataSize);
1974050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x40);   // objectTypeIndication ISO/IEC 14492-2
1975050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x15);   // streamType AudioStream
1976050b28a593350047845a45a14cc5026221ac1620James Dong
1977050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt16(0x03);  // XXX
1978050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x00);   // buffer size 24-bit
1979050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt32(96000); // max bit rate
1980050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt32(96000); // avg bit rate
1981050b28a593350047845a45a14cc5026221ac1620James Dong
1982050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(0x05);   // DecoderSpecificInfoTag
1983050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->writeInt8(mCodecSpecificDataSize);
1984050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
1985050b28a593350047845a45a14cc5026221ac1620James Dong
1986050b28a593350047845a45a14cc5026221ac1620James Dong                        static const uint8_t kData2[] = {
1987050b28a593350047845a45a14cc5026221ac1620James Dong                            0x06,  // SLConfigDescriptorTag
1988050b28a593350047845a45a14cc5026221ac1620James Dong                            0x01,
1989050b28a593350047845a45a14cc5026221ac1620James Dong                            0x02
1990050b28a593350047845a45a14cc5026221ac1620James Dong                        };
1991050b28a593350047845a45a14cc5026221ac1620James Dong                        mOwner->write(kData2, sizeof(kData2));
1992050b28a593350047845a45a14cc5026221ac1620James Dong
1993050b28a593350047845a45a14cc5026221ac1620James Dong                    mOwner->endBox();  // esds
19945aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                  } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) ||
19955aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                             !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
19965aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                    // 3gpp2 Spec AMRSampleEntry fields
19975aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                    mOwner->beginBox("damr");
19985aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                      mOwner->writeCString("   ");  // vendor: 4 bytes
19995aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                      mOwner->writeInt8(0);         // decoder version
20005aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                      mOwner->writeInt16(0x83FF);   // mode set: all enabled
20015aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                      mOwner->writeInt8(0);         // mode change period
20025aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                      mOwner->writeInt8(1);         // frames per sample
20035aff464f67322cd13dc8ed165806971cfff2e4d5James Dong                    mOwner->endBox();
2004050b28a593350047845a45a14cc5026221ac1620James Dong                  }
200520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mOwner->endBox();
200620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
200718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
200820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    mOwner->beginBox("mp4v");
200918291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
201020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    mOwner->beginBox("s263");
201130ab66297501757d745b9ae10da61adcd891f497Andreas Huber                } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
201230ab66297501757d745b9ae10da61adcd891f497Andreas Huber                    mOwner->beginBox("avc1");
201320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                } else {
201425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber                    LOGE("Unknown mime type '%s'.", mime);
20150c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                    CHECK(!"should not be here, unknown mime type.");
201620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
201720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
201820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
201920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
20201acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                  mOwner->writeInt16(1);           // data ref index
202120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // predefined
202220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0);           // reserved
202320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // predefined
202420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // predefined
202520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // predefined
202620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
202720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  int32_t width, height;
202820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  bool success = mMeta->findInt32(kKeyWidth, &width);
202920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  success = success && mMeta->findInt32(kKeyHeight, &height);
20300c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                  CHECK(success);
203120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
203220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(width);
203320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(height);
203420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0x480000);    // horiz resolution
203520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0x480000);    // vert resolution
203620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt32(0);           // reserved
203720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(1);           // frame count
203820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->write("                                ", 32);
203920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(0x18);        // depth
204020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  mOwner->writeInt16(-1);          // predefined
204120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
20420c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber                  CHECK(23 + mCodecSpecificDataSize < 128);
204320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
204418291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                  if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
204520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->beginBox("esds");
204620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
204720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt32(0);           // version=0, flags=0
204820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
204920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x03);  // ES_DescrTag
205020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(23 + mCodecSpecificDataSize);
205120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt16(0x0000);  // ES_ID
205220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x1f);
205320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
205420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x04);  // DecoderConfigDescrTag
205520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(15 + mCodecSpecificDataSize);
205620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x20);  // objectTypeIndication ISO/IEC 14492-2
205720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x11);  // streamType VisualStream
205820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
205920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        static const uint8_t kData[] = {
206020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x01, 0x77, 0x00,
206120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x00, 0x03, 0xe8, 0x00,
206220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x00, 0x03, 0xe8, 0x00
206320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        };
206420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->write(kData, sizeof(kData));
2065050b28a593350047845a45a14cc5026221ac1620James Dong
206620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(0x05);  // DecoderSpecificInfoTag
206720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
206820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->writeInt8(mCodecSpecificDataSize);
206920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
207020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
207120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        static const uint8_t kData2[] = {
207220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x06,  // SLConfigDescriptorTag
207320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x01,
207420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            0x02
207520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        };
207620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        mOwner->write(kData2, sizeof(kData2));
207720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
207820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->endBox();  // esds
207918291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                  } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
208020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->beginBox("d263");
208120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
208220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt32(0);  // vendor
208320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt8(0);   // decoder version
208420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt8(10);  // level: 10
208520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                          mOwner->writeInt8(0);   // profile: 0
208620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
208720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                      mOwner->endBox();  // d263
208830ab66297501757d745b9ae10da61adcd891f497Andreas Huber                  } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
208930ab66297501757d745b9ae10da61adcd891f497Andreas Huber                      mOwner->beginBox("avcC");
209030ab66297501757d745b9ae10da61adcd891f497Andreas Huber                        mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
209130ab66297501757d745b9ae10da61adcd891f497Andreas Huber                      mOwner->endBox();  // avcC
209220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                  }
209330ab66297501757d745b9ae10da61adcd891f497Andreas Huber
20941acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                  mOwner->beginBox("pasp");
20951acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                    // This is useful if the pixel is not square
20961acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                    mOwner->writeInt32(1 << 16);  // hspacing
20971acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                    mOwner->writeInt32(1 << 16);  // vspacing
20981acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                  mOwner->endBox();  // pasp
209930ab66297501757d745b9ae10da61adcd891f497Andreas Huber                mOwner->endBox();  // mp4v, s263 or avc1
210020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
210120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stsd
210220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
210320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stts");
210420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
2105be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            mOwner->writeInt32(mSttsTableEntries.size());
2106be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin();
2107be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                 it != mSttsTableEntries.end(); ++it) {
2108be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mOwner->writeInt32(it->sampleCount);
21098f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong                int32_t dur = (it->sampleDurationUs * mTimeScale + 5E5) / 1E6;
21108f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong                mOwner->writeInt32(dur);
211120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
211220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stts
211320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
21141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong          if (!mIsAudio) {
2115050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->beginBox("stss");
2116050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->writeInt32(0);  // version=0, flags=0
2117050b28a593350047845a45a14cc5026221ac1620James Dong              mOwner->writeInt32(mStssTableEntries.size());  // number of sync frames
2118050b28a593350047845a45a14cc5026221ac1620James Dong              for (List<int32_t>::iterator it = mStssTableEntries.begin();
2119050b28a593350047845a45a14cc5026221ac1620James Dong                   it != mStssTableEntries.end(); ++it) {
2120050b28a593350047845a45a14cc5026221ac1620James Dong                  mOwner->writeInt32(*it);
2121050b28a593350047845a45a14cc5026221ac1620James Dong              }
2122050b28a593350047845a45a14cc5026221ac1620James Dong            mOwner->endBox();  // stss
2123050b28a593350047845a45a14cc5026221ac1620James Dong          }
2124050b28a593350047845a45a14cc5026221ac1620James Dong
212520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stsz");
212620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
2127be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            if (mSamplesHaveSameSize) {
21288644c14618d30d9e57a69df40ed939986ebf02c4James Dong                List<size_t>::iterator it = mSampleSizes.begin();
21298644c14618d30d9e57a69df40ed939986ebf02c4James Dong                mOwner->writeInt32(*it);  // default sample size
2130be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            } else {
2131be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mOwner->writeInt32(0);
2132be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
2133ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong            mOwner->writeInt32(mNumSamples);
2134be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            if (!mSamplesHaveSameSize) {
21358644c14618d30d9e57a69df40ed939986ebf02c4James Dong                for (List<size_t>::iterator it = mSampleSizes.begin();
21368644c14618d30d9e57a69df40ed939986ebf02c4James Dong                     it != mSampleSizes.end(); ++it) {
21378644c14618d30d9e57a69df40ed939986ebf02c4James Dong                    mOwner->writeInt32(*it);
2138be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                }
213920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
214020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stsz
214120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
214220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->beginBox("stsc");
214320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
214413aec890216948b0c364f8f92792129d0335f506James Dong            mOwner->writeInt32(mStscTableEntries.size());
214513aec890216948b0c364f8f92792129d0335f506James Dong            for (List<StscTableEntry>::iterator it = mStscTableEntries.begin();
214613aec890216948b0c364f8f92792129d0335f506James Dong                 it != mStscTableEntries.end(); ++it) {
214713aec890216948b0c364f8f92792129d0335f506James Dong                mOwner->writeInt32(it->firstChunk);
214813aec890216948b0c364f8f92792129d0335f506James Dong                mOwner->writeInt32(it->samplesPerChunk);
214913aec890216948b0c364f8f92792129d0335f506James Dong                mOwner->writeInt32(it->sampleDescriptionId);
215020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
215120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber          mOwner->endBox();  // stsc
21521acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong          mOwner->beginBox(use32BitOffset? "stco": "co64");
215320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mOwner->writeInt32(0);  // version=0, flags=0
215413aec890216948b0c364f8f92792129d0335f506James Dong            mOwner->writeInt32(mChunkOffsets.size());
215513aec890216948b0c364f8f92792129d0335f506James Dong            for (List<off_t>::iterator it = mChunkOffsets.begin();
215613aec890216948b0c364f8f92792129d0335f506James Dong                 it != mChunkOffsets.end(); ++it) {
21571acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                if (use32BitOffset) {
21581acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                    mOwner->writeInt32(static_cast<int32_t>(*it));
21591acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                } else {
21601acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                    mOwner->writeInt64((*it));
21611acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong                }
216220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
21638f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong          mOwner->endBox();  // stco or co64
216420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
216520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mOwner->endBox();  // stbl
21661acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong       mOwner->endBox();  // minf
216720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mOwner->endBox();  // mdia
216820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOwner->endBox();  // trak
216920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
217020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
217120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
2172