MPEG4Writer.cpp revision e76dba7af9589d9ed7b116eec3a74168a8352925
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
2020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <arpa/inet.h>
21a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <fcntl.h>
22a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <inttypes.h>
2320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <pthread.h>
24a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong#include <sys/prctl.h>
25a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <sys/stat.h>
26a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <sys/types.h>
27a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <unistd.h>
28a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn
29a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <utils/Log.h>
3020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong#include <media/stagefright/foundation/ADebug.h>
32e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang#include <media/stagefright/foundation/AMessage.h>
3320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MPEG4Writer.h>
3420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBuffer.h>
3520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h>
3618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h>
3703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#include <media/stagefright/MediaErrors.h>
3820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaSource.h>
3920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/Utils.h>
40d599cd4573b5a2d5914c5040e0565ef866749b77James Dong#include <media/mediarecorder.h>
4107ec01904613a0bac32caaa8444b4690998faed7James Dong#include <cutils/properties.h>
4220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber#include "include/ESDS.h"
4419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
45dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn
46dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn#ifndef __predict_false
47dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn#define __predict_false(exp) __builtin_expect((exp) != 0, 0)
48dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn#endif
49dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn
5011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih#define WARN_UNLESS(condition, message, ...) \
51dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn( (__predict_false(condition)) ? false : ({ \
5211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih    ALOGW("Condition %s failed "  message, #condition, ##__VA_ARGS__); \
5311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih    true; \
5411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih}))
5511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
5620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android {
5720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5877e8ae9967a078770416619e99ddb5b010def312James Dongstatic const int64_t kMinStreamableFileSizeInBytes = 5 * 1024 * 1024;
591f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachadstatic const int64_t kMax32BitFileSize = 0x00ffffffffLL; // 2^32-1 : max FAT32
601f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad                                                         // filesystem file size
611f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad                                                         // used by most SD cards
623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypeSeqParamSet = 0x07;
633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypePicParamSet = 0x08;
6470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongstatic const int64_t kInitialDelayTimeUs     = 700000LL;
655b6a01e65aa4129a9226667536d1bc1dad5980d8James Dong
6620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Writer::Track {
6720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic:
68bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    Track(MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId);
698f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
7020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    ~Track();
7120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t start(MetaData *params);
7337187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t stop();
7437187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t pause();
7525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool reachedEOS();
7620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
773b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber    int64_t getDurationUs() const;
78d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t getEstimatedTrackSizeBytes() const;
79b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeTrackHeader(bool use32BitOffset = true);
801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void bufferChunk(int64_t timestampUs);
811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isAvc() const { return mIsAvc; }
821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isAudio() const { return mIsAudio; }
831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isMPEG4() const { return mIsMPEG4; }
84c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    void addChunkOffset(off64_t offset);
8570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int32_t getTrackId() const { return mTrackId; }
86dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    status_t dump(int fd, const Vector<String16>& args) const;
8720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate:
89000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    enum {
90000e18370baae60ffd9f25b509501dd8c26deabfJames Dong        kMaxCttsOffsetTimeUs = 1000000LL,  // 1 second
918c460498c028888c533ab442be12b6d4b669b965James Dong        kSampleArraySize = 1000,
92000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    };
93000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
94c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    // A helper class to handle faster write box with table entries
95c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    template<class TYPE>
96c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    struct ListTableEntries {
97c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        ListTableEntries(uint32_t elementCapacity, uint32_t entryCapacity)
98c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            : mElementCapacity(elementCapacity),
99c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mEntryCapacity(entryCapacity),
100c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mTotalNumTableEntries(0),
101c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mNumValuesInCurrEntry(0),
102c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mCurrTableEntriesElement(NULL) {
103c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_GT(mElementCapacity, 0);
104c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_GT(mEntryCapacity, 0);
105c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
106c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
107c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Free the allocated memory.
108c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        ~ListTableEntries() {
109c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            while (!mTableEntryList.empty()) {
110c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                typename List<TYPE *>::iterator it = mTableEntryList.begin();
111c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                delete[] (*it);
112c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mTableEntryList.erase(it);
113c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
114c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
115c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
116c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Replace the value at the given position by the given value.
117c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // There must be an existing value at the given position.
118c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg value must be in network byte order
119c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg pos location the value must be in.
120c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        void set(const TYPE& value, uint32_t pos) {
12125f0d7ba1987de61c75f8c68b19de48e0ad9736cJames Dong            CHECK_LT(pos, mTotalNumTableEntries * mEntryCapacity);
122c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
123c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            typename List<TYPE *>::iterator it = mTableEntryList.begin();
124c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t iterations = (pos / (mElementCapacity * mEntryCapacity));
125c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            while (it != mTableEntryList.end() && iterations > 0) {
126c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                ++it;
127c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                --iterations;
128c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
129c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK(it != mTableEntryList.end());
130c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_EQ(iterations, 0);
131c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
132c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            (*it)[(pos % (mElementCapacity * mEntryCapacity))] = value;
133c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
134c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
135c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Get the value at the given position by the given value.
136c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg value the retrieved value at the position in network byte order.
137c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg pos location the value must be in.
138c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @return true if a value is found.
139c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        bool get(TYPE& value, uint32_t pos) const {
14025f0d7ba1987de61c75f8c68b19de48e0ad9736cJames Dong            if (pos >= mTotalNumTableEntries * mEntryCapacity) {
141c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                return false;
142c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
143c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
144c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            typename List<TYPE *>::iterator it = mTableEntryList.begin();
145c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t iterations = (pos / (mElementCapacity * mEntryCapacity));
146c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            while (it != mTableEntryList.end() && iterations > 0) {
147c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                ++it;
148c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                --iterations;
149c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
150c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK(it != mTableEntryList.end());
151c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_EQ(iterations, 0);
152c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
153c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            value = (*it)[(pos % (mElementCapacity * mEntryCapacity))];
154c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            return true;
155c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
156c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
157c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Store a single value.
158c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg value must be in network byte order.
159c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        void add(const TYPE& value) {
160c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_LT(mNumValuesInCurrEntry, mElementCapacity);
161c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t nEntries = mTotalNumTableEntries % mElementCapacity;
162c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t nValues  = mNumValuesInCurrEntry % mEntryCapacity;
163c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (nEntries == 0 && nValues == 0) {
164c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mCurrTableEntriesElement = new TYPE[mEntryCapacity * mElementCapacity];
165c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                CHECK(mCurrTableEntriesElement != NULL);
166c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mTableEntryList.push_back(mCurrTableEntriesElement);
167c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
168c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
169c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t pos = nEntries * mEntryCapacity + nValues;
170c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mCurrTableEntriesElement[pos] = value;
171c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
172c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            ++mNumValuesInCurrEntry;
173c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if ((mNumValuesInCurrEntry % mEntryCapacity) == 0) {
174c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                ++mTotalNumTableEntries;
175c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mNumValuesInCurrEntry = 0;
176c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
177c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
178c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
179c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Write out the table entries:
180c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // 1. the number of entries goes first
181c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // 2. followed by the values in the table enties in order
182c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg writer the writer to actual write to the storage
183c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        void write(MPEG4Writer *writer) const {
184c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_EQ(mNumValuesInCurrEntry % mEntryCapacity, 0);
185c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t nEntries = mTotalNumTableEntries;
186c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            writer->writeInt32(nEntries);
187c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            for (typename List<TYPE *>::iterator it = mTableEntryList.begin();
188c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                it != mTableEntryList.end(); ++it) {
189c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                CHECK_GT(nEntries, 0);
190c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                if (nEntries >= mElementCapacity) {
191c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    writer->write(*it, sizeof(TYPE) * mEntryCapacity, mElementCapacity);
192c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    nEntries -= mElementCapacity;
193c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                } else {
194c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    writer->write(*it, sizeof(TYPE) * mEntryCapacity, nEntries);
195c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    break;
196c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                }
197c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
198c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
199c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
200c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Return the number of entries in the table.
201c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t count() const { return mTotalNumTableEntries; }
202c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
203c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    private:
204c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t         mElementCapacity;  // # entries in an element
205c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t         mEntryCapacity;    // # of values in each entry
206c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t         mTotalNumTableEntries;
207c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t         mNumValuesInCurrEntry;  // up to mEntryCapacity
208c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        TYPE             *mCurrTableEntriesElement;
209c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mutable List<TYPE *>     mTableEntryList;
210c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
211c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        DISALLOW_EVIL_CONSTRUCTORS(ListTableEntries);
212c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    };
213c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
214c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
215c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
21620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Writer *mOwner;
21720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MetaData> mMeta;
218693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    sp<MediaSource> mSource;
21920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    volatile bool mDone;
220a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mPaused;
221a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mResumed;
222eaae38445a340c4857c1c5569475879a728e63b7James Dong    volatile bool mStarted;
2231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAvc;
2241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAudio;
2251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsMPEG4;
226bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    int32_t mTrackId;
227c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    int64_t mTrackDurationUs;
22843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    int64_t mMaxChunkDurationUs;
229e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
230d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t mEstimatedTrackSizeBytes;
2311f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    int64_t mMdatSizeBytes;
2328f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int32_t mTimeScale;
23320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
23420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_t mThread;
23520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
236be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
23713aec890216948b0c364f8f92792129d0335f506James Dong    List<MediaBuffer *> mChunkSamples;
2381f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
239c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    bool                mSamplesHaveSameSize;
240c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mStszTableEntries;
241be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
242c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mStcoTableEntries;
243c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<off64_t> *mCo64TableEntries;
244c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mStscTableEntries;
245c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mStssTableEntries;
246c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mSttsTableEntries;
247c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mCttsTableEntries;
248965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
249000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t mMinCttsOffsetTimeUs;
250000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t mMaxCttsOffsetTimeUs;
251965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Sequence parameter set or picture parameter set
2533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    struct AVCParamSet {
2543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        AVCParamSet(uint16_t length, const uint8_t *data)
2553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            : mLength(length), mData(data) {}
2563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
2573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t mLength;
2583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *mData;
2593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    };
2603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    List<AVCParamSet> mSeqParamSets;
2613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    List<AVCParamSet> mPicParamSets;
2623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mProfileIdc;
2633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mProfileCompatible;
2643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mLevelIdc;
2653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
26620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *mCodecSpecificData;
26720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t mCodecSpecificDataSize;
268548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    bool mGotAllCodecSpecificData;
26993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    bool mTrackingProgressStatus;
27020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
27125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool mReachedEOS;
2723c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    int64_t mStartTimestampUs;
27370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int64_t mStartTimeRealUs;
27470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int64_t mFirstSampleTimeRealUs;
27593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mPreviousTrackTimeUs;
27693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mTrackEveryTimeDurationUs;
27725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
278872a481558350634a3fd5cb67939de288af00ecbJames Dong    // Update the audio track's drift information.
279872a481558350634a3fd5cb67939de288af00ecbJames Dong    void updateDriftTime(const sp<MetaData>& meta);
280872a481558350634a3fd5cb67939de288af00ecbJames Dong
281000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int32_t getStartTimeOffsetScaledTime() const;
282000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
28320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    static void *ThreadWrapper(void *me);
28437187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t threadEntry();
28520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *parseParamSet(
2873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen);
2883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
289b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t makeAVCCodecSpecificData(const uint8_t *data, size_t size);
290b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t copyAVCCodecSpecificData(const uint8_t *data, size_t size);
291b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t parseAVCCodecSpecificData(const uint8_t *data, size_t size);
292215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong
293215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    // Track authoring progress status
294faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    void trackProgressStatus(int64_t timeUs, status_t err = OK);
29593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    void initTrackingProgressStatus(MetaData *params);
29603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
29719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    void getCodecSpecificDataFromInputFormatIfPossible();
29819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
299c059860c73678a202bfa33062723e8f82fb779d9James Dong    // Determine the track time scale
300c059860c73678a202bfa33062723e8f82fb779d9James Dong    // If it is an audio track, try to use the sampling rate as
301c059860c73678a202bfa33062723e8f82fb779d9James Dong    // the time scale; however, if user chooses the overwrite
302c059860c73678a202bfa33062723e8f82fb779d9James Dong    // value, the user-supplied time scale will be used.
303c059860c73678a202bfa33062723e8f82fb779d9James Dong    void setTimeScale();
304c059860c73678a202bfa33062723e8f82fb779d9James Dong
305690f546b0ee548dbfe997df36418e5302ec2d786James Dong    // Simple validation on the codec specific data
306690f546b0ee548dbfe997df36418e5302ec2d786James Dong    status_t checkCodecSpecificData() const;
30713f6284305e4b27395a23db7882d670bdb1bcae1James Dong    int32_t mRotation;
308690f546b0ee548dbfe997df36418e5302ec2d786James Dong
3091f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void updateTrackSizeEstimate();
3101f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void addOneStscTableEntry(size_t chunkId, size_t sampleId);
3111f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void addOneStssTableEntry(size_t sampleId);
31279761ab096f57c3027fad9556c2bc436672d614eJames Dong
31379761ab096f57c3027fad9556c2bc436672d614eJames Dong    // Duration is time scale based
31479761ab096f57c3027fad9556c2bc436672d614eJames Dong    void addOneSttsTableEntry(size_t sampleCount, int32_t timescaledDur);
315965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    void addOneCttsTableEntry(size_t sampleCount, int32_t timescaledDur);
31645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
31745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    bool isTrackMalFormed() const;
31843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    void sendTrackSummary(bool hasMultipleTracks);
3191f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
320b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Write the boxes
321b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStcoBox(bool use32BitOffset);
322b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStscBox();
323b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStszBox();
324b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStssBox();
325b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeSttsBox();
326965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    void writeCttsBox();
327b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeD263Box();
328b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writePaspBox();
329b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeAvccBox();
330b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeUrlBox();
331b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDrefBox();
332b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDinfBox();
333b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDamrBox();
334efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    void writeMdhdBox(uint32_t now);
335b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeSmhdBox();
336b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeVmhdBox();
337b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeHdlrBox();
338efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    void writeTkhdBox(uint32_t now);
339b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeMp4aEsdsBox();
340b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeMp4vEsdsBox();
341b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeAudioFourCCBox();
342b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeVideoFourCCBox();
343b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStblBox(bool use32BitOffset);
344b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
34520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track(const Track &);
34620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track &operator=(const Track &);
34720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
34820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
34930ab66297501757d745b9ae10da61adcd891f497Andreas HuberMPEG4Writer::MPEG4Writer(int fd)
350674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    : mFd(dup(fd)),
351674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong      mInitCheck(mFd < 0? NO_INIT: OK),
352de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui      mIsRealTimeRecording(true),
353b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong      mUse4ByteNalLength(true),
3541acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong      mUse32BitOffset(true),
355a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong      mIsFileSizeLimitExplicitlyRequested(false),
356a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
357a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mStarted(false),
358411ba422e3635d534928ffd81abf54f4f291c739James Dong      mWriterThreadStarted(false),
35930ab66297501757d745b9ae10da61adcd891f497Andreas Huber      mOffset(0),
36013aec890216948b0c364f8f92792129d0335f506James Dong      mMdatOffset(0),
3617837c17063a4c50bc856ba59418516fdab731de7James Dong      mEstimatedMoovBoxSize(0),
36207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mInterleaveDurationUs(1000000),
36307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mLatitudex10000(0),
36407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mLongitudex10000(0),
36586b7f47aa7482424cf8fd248f1315311919be3b0James Dong      mAreGeoTagsAvailable(false),
366e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang      mMetaKeys(new AMessage()),
36786b7f47aa7482424cf8fd248f1315311919be3b0James Dong      mStartTimeOffsetMs(-1) {
36830ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
36930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
37020111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() {
3718bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dong    reset();
37220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3731f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    while (!mTracks.empty()) {
3741f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        List<Track *>::iterator it = mTracks.begin();
37520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        delete *it;
3761f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        (*it) = NULL;
3771f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mTracks.erase(it);
37820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
37920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.clear();
38020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
38120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
382dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::dump(
383dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        int fd, const Vector<String16>& args) {
384dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    const size_t SIZE = 256;
385dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    char buffer[SIZE];
386dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    String8 result;
387dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "   MPEG4Writer %p\n", this);
388dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
389dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "     mStarted: %s\n", mStarted? "true": "false");
390dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
391dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    ::write(fd, result.string(), result.size());
392dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    for (List<Track *>::iterator it = mTracks.begin();
393dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong         it != mTracks.end(); ++it) {
394dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        (*it)->dump(fd, args);
395dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    }
396dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    return OK;
397dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong}
398dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong
399dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::Track::dump(
40084333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        int fd, const Vector<String16>& /* args */) const {
401dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    const size_t SIZE = 256;
402dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    char buffer[SIZE];
403dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    String8 result;
404dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "     %s track\n", mIsAudio? "Audio": "Video");
405dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
406dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "       reached EOS: %s\n",
407dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong            mReachedEOS? "true": "false");
408dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
409c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    snprintf(buffer, SIZE, "       frames encoded : %d\n", mStszTableEntries->count());
41013210f3346462a86ce9fe3af72a0c200dba84e27James Dong    result.append(buffer);
411377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    snprintf(buffer, SIZE, "       duration encoded : %" PRId64 " us\n", mTrackDurationUs);
41213210f3346462a86ce9fe3af72a0c200dba84e27James Dong    result.append(buffer);
413dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    ::write(fd, result.string(), result.size());
414dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    return OK;
415dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong}
416dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong
4172dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huberstatus_t MPEG4Writer::addSource(const sp<MediaSource> &source) {
418bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    Mutex::Autolock l(mLock);
419bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    if (mStarted) {
42029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Attempt to add source AFTER recording is started");
421bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        return UNKNOWN_ERROR;
422bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    }
423acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
424acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // At most 2 tracks can be supported.
425acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    if (mTracks.size() >= 2) {
426a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGE("Too many tracks (%zu) to add", mTracks.size());
427acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        return ERROR_UNSUPPORTED;
428acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    }
429acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
430acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    CHECK(source.get() != NULL);
431acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
432acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // A track of type other than video or audio is not supported.
433acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    const char *mime;
434acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    source->getFormat()->findCString(kKeyMIMEType, &mime);
435acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    bool isAudio = !strncasecmp(mime, "audio/", 6);
436acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    bool isVideo = !strncasecmp(mime, "video/", 6);
437acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    if (!isAudio && !isVideo) {
438acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        ALOGE("Track (%s) other than video or audio is not supported",
439acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong            mime);
440acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        return ERROR_UNSUPPORTED;
441acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    }
442acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
443acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // At this point, we know the track to be added is either
444acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // video or audio. Thus, we only need to check whether it
445acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // is an audio track or not (if it is not, then it must be
446acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // a video track).
447acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
448acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // No more than one video or one audio track is supported.
449acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    for (List<Track*>::iterator it = mTracks.begin();
450acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong         it != mTracks.end(); ++it) {
451acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        if ((*it)->isAudio() == isAudio) {
452acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong            ALOGE("%s track already exists", isAudio? "Audio": "Video");
453acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong            return ERROR_UNSUPPORTED;
454acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        }
455acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    }
456acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
457acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // This is the first track of either audio or video.
458acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // Go ahead to add the track.
459219f195159f93d627af2b243732e3f9020511a46James Dong    Track *track = new Track(this, source, 1 + mTracks.size());
46020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.push_back(track);
4612dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
4622dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    return OK;
46320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
46420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
46593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::startTracks(MetaData *params) {
466acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    if (mTracks.empty()) {
467acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        ALOGE("No source added");
468acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        return INVALID_OPERATION;
469acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    }
470acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
471a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
472a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
47393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        status_t err = (*it)->start(params);
474a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
475a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (err != OK) {
476a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            for (List<Track *>::iterator it2 = mTracks.begin();
477a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                 it2 != it; ++it2) {
478a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                (*it2)->stop();
479a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            }
480a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
481a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            return err;
482a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
483a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
484a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    return OK;
485a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
486a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
4872dec2b5be2056c6d9428897dc672185872d30d17James Dongint64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) {
4882dec2b5be2056c6d9428897dc672185872d30d17James Dong    // This implementation is highly experimental/heurisitic.
4892dec2b5be2056c6d9428897dc672185872d30d17James Dong    //
4902dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Statistical analysis shows that metadata usually accounts
4912dec2b5be2056c6d9428897dc672185872d30d17James Dong    // for a small portion of the total file size, usually < 0.6%.
4922dec2b5be2056c6d9428897dc672185872d30d17James Dong
49378a1a286f736888ae7af8860b2c424af0d978848James Dong    // The default MIN_MOOV_BOX_SIZE is set to 0.6% x 1MB / 2,
4942dec2b5be2056c6d9428897dc672185872d30d17James Dong    // where 1MB is the common file size limit for MMS application.
49578a1a286f736888ae7af8860b2c424af0d978848James Dong    // The default MAX _MOOV_BOX_SIZE value is based on about 3
4962dec2b5be2056c6d9428897dc672185872d30d17James Dong    // minute video recording with a bit rate about 3 Mbps, because
4972dec2b5be2056c6d9428897dc672185872d30d17James Dong    // statistics also show that most of the video captured are going
4982dec2b5be2056c6d9428897dc672185872d30d17James Dong    // to be less than 3 minutes.
4992dec2b5be2056c6d9428897dc672185872d30d17James Dong
5002dec2b5be2056c6d9428897dc672185872d30d17James Dong    // If the estimation is wrong, we will pay the price of wasting
5012dec2b5be2056c6d9428897dc672185872d30d17James Dong    // some reserved space. This should not happen so often statistically.
5022dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int32_t factor = mUse32BitOffset? 1: 2;
50378a1a286f736888ae7af8860b2c424af0d978848James Dong    static const int64_t MIN_MOOV_BOX_SIZE = 3 * 1024;  // 3 KB
5042dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000);
5052dec2b5be2056c6d9428897dc672185872d30d17James Dong    int64_t size = MIN_MOOV_BOX_SIZE;
5062dec2b5be2056c6d9428897dc672185872d30d17James Dong
50778a1a286f736888ae7af8860b2c424af0d978848James Dong    // Max file size limit is set
508a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
50978a1a286f736888ae7af8860b2c424af0d978848James Dong        size = mMaxFileSizeLimitBytes * 6 / 1000;
51078a1a286f736888ae7af8860b2c424af0d978848James Dong    }
51178a1a286f736888ae7af8860b2c424af0d978848James Dong
51278a1a286f736888ae7af8860b2c424af0d978848James Dong    // Max file duration limit is set
51378a1a286f736888ae7af8860b2c424af0d978848James Dong    if (mMaxFileDurationLimitUs != 0) {
51478a1a286f736888ae7af8860b2c424af0d978848James Dong        if (bitRate > 0) {
51578a1a286f736888ae7af8860b2c424af0d978848James Dong            int64_t size2 =
51678a1a286f736888ae7af8860b2c424af0d978848James Dong                ((mMaxFileDurationLimitUs * bitRate * 6) / 1000 / 8000000);
51778a1a286f736888ae7af8860b2c424af0d978848James Dong            if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
51878a1a286f736888ae7af8860b2c424af0d978848James Dong                // When both file size and duration limits are set,
51978a1a286f736888ae7af8860b2c424af0d978848James Dong                // we use the smaller limit of the two.
52078a1a286f736888ae7af8860b2c424af0d978848James Dong                if (size > size2) {
52178a1a286f736888ae7af8860b2c424af0d978848James Dong                    size = size2;
52278a1a286f736888ae7af8860b2c424af0d978848James Dong                }
52378a1a286f736888ae7af8860b2c424af0d978848James Dong            } else {
52478a1a286f736888ae7af8860b2c424af0d978848James Dong                // Only max file duration limit is set
52578a1a286f736888ae7af8860b2c424af0d978848James Dong                size = size2;
52678a1a286f736888ae7af8860b2c424af0d978848James Dong            }
5272dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
5282dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
52978a1a286f736888ae7af8860b2c424af0d978848James Dong
5302dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size < MIN_MOOV_BOX_SIZE) {
5312dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MIN_MOOV_BOX_SIZE;
5322dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
5332dec2b5be2056c6d9428897dc672185872d30d17James Dong
5342dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Any long duration recording will be probably end up with
5352dec2b5be2056c6d9428897dc672185872d30d17James Dong    // non-streamable mp4 file.
5362dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size > MAX_MOOV_BOX_SIZE) {
5372dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MAX_MOOV_BOX_SIZE;
5382dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
5392dec2b5be2056c6d9428897dc672185872d30d17James Dong
540a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGI("limits: %" PRId64 "/%" PRId64 " bytes/us, bit rate: %d bps and the"
541a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn         " estimated moov size %" PRId64 " bytes",
5422dec2b5be2056c6d9428897dc672185872d30d17James Dong         mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size);
5432dec2b5be2056c6d9428897dc672185872d30d17James Dong    return factor * size;
5442dec2b5be2056c6d9428897dc672185872d30d17James Dong}
5452dec2b5be2056c6d9428897dc672185872d30d17James Dong
5462dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t MPEG4Writer::start(MetaData *param) {
547674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
54825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return UNKNOWN_ERROR;
54920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
55020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
551a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    /*
552a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * Check mMaxFileSizeLimitBytes at the beginning
553a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * since mMaxFileSizeLimitBytes may be implicitly
554a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * changed later for 32-bit file offset even if
555a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * user does not ask to set it explicitly.
556a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     */
557a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    if (mMaxFileSizeLimitBytes != 0) {
558a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong        mIsFileSizeLimitExplicitlyRequested = true;
559a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    }
560a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong
5612dec2b5be2056c6d9428897dc672185872d30d17James Dong    int32_t use64BitOffset;
5622dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (param &&
5632dec2b5be2056c6d9428897dc672185872d30d17James Dong        param->findInt32(kKey64BitFileOffset, &use64BitOffset) &&
5642dec2b5be2056c6d9428897dc672185872d30d17James Dong        use64BitOffset) {
5652dec2b5be2056c6d9428897dc672185872d30d17James Dong        mUse32BitOffset = false;
5662dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
5672dec2b5be2056c6d9428897dc672185872d30d17James Dong
5681f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    if (mUse32BitOffset) {
5691f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // Implicit 32 bit file size limit
5701f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        if (mMaxFileSizeLimitBytes == 0) {
5711f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            mMaxFileSizeLimitBytes = kMax32BitFileSize;
5721f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        }
5731f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
5741f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // If file size is set to be larger than the 32 bit file
5751f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // size limit, treat it as an error.
5761f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        if (mMaxFileSizeLimitBytes > kMax32BitFileSize) {
577a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGW("32-bit file size limit (%" PRId64 " bytes) too big. "
578a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn                 "It is changed to %" PRId64 " bytes",
579d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong                mMaxFileSizeLimitBytes, kMax32BitFileSize);
580d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong            mMaxFileSizeLimitBytes = kMax32BitFileSize;
5811f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        }
5821f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    }
5831f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
584b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    int32_t use2ByteNalLength;
585b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (param &&
586b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        param->findInt32(kKey2ByteNalLength, &use2ByteNalLength) &&
587b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        use2ByteNalLength) {
588b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mUse4ByteNalLength = false;
5892dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
5902dec2b5be2056c6d9428897dc672185872d30d17James Dong
591de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    int32_t isRealTimeRecording;
592de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    if (param && param->findInt32(kKeyRealTimeRecording, &isRealTimeRecording)) {
593de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        mIsRealTimeRecording = isRealTimeRecording;
594de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    }
595de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui
596065d1aff96818df54456053f1574aec8a234d0deJames Dong    mStartTimestampUs = -1;
59793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
598a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (mStarted) {
599a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused) {
600a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mPaused = false;
60193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            return startTracks(param);
602a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
603a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
604a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
605a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
6068f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    if (!param ||
6078f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        !param->findInt32(kKeyTimeScale, &mTimeScale)) {
6088f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        mTimeScale = 1000;
6098f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    }
61043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mTimeScale, 0);
6113856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("movie time scale: %d", mTimeScale);
6128f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
61377e8ae9967a078770416619e99ddb5b010def312James Dong    /*
61477e8ae9967a078770416619e99ddb5b010def312James Dong     * When the requested file size limit is small, the priority
61577e8ae9967a078770416619e99ddb5b010def312James Dong     * is to meet the file size limit requirement, rather than
6167b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * to make the file streamable. mStreamableFile does not tell
6177b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * whether the actual recorded file is streamable or not.
61877e8ae9967a078770416619e99ddb5b010def312James Dong     */
61977e8ae9967a078770416619e99ddb5b010def312James Dong    mStreamableFile =
62077e8ae9967a078770416619e99ddb5b010def312James Dong        (mMaxFileSizeLimitBytes != 0 &&
62177e8ae9967a078770416619e99ddb5b010def312James Dong         mMaxFileSizeLimitBytes >= kMinStreamableFileSizeInBytes);
62277e8ae9967a078770416619e99ddb5b010def312James Dong
6237b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    /*
6247b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * mWriteMoovBoxToMemory is true if the amount of data in moov box is
6257b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * smaller than the reserved free space at the beginning of a file, AND
6267b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * when the content of moov box is constructed. Note that video/audio
6277b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * frame data is always written to the file but not in the memory.
6287b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
6297b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * Before stop()/reset() is called, mWriteMoovBoxToMemory is always
6307b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * false. When reset() is called at the end of a recording session,
6317b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * Moov box needs to be constructed.
6327b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
6337b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * 1) Right before a moov box is constructed, mWriteMoovBoxToMemory
6347b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * to set to mStreamableFile so that if
6357b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * the file is intended to be streamable, it is set to true;
6367b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * otherwise, it is set to false. When the value is set to false,
6377b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * all the content of the moov box is written immediately to
6387b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * the end of the file. When the value is set to true, all the
6397b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * content of the moov box is written to an in-memory cache,
6407b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * mMoovBoxBuffer, util the following condition happens. Note
6417b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * that the size of the in-memory cache is the same as the
6427b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * reserved free space at the beginning of the file.
6437b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
6447b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * 2) While the data of the moov box is written to an in-memory
6457b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * cache, the data size is checked against the reserved space.
6467b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * If the data size surpasses the reserved space, subsequent moov
6477b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * data could no longer be hold in the in-memory cache. This also
6487b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * indicates that the reserved space was too small. At this point,
6497b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * _all_ moov data must be written to the end of the file.
6507b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * mWriteMoovBoxToMemory must be set to false to direct the write
6517b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * to the file.
6527b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
6537b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * 3) If the data size in moov box is smaller than the reserved
6547b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * space after moov box is completely constructed, the in-memory
6557b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * cache copy of the moov box is written to the reserved free
6567b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * space. Thus, immediately after the moov is completedly
6577b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * constructed, mWriteMoovBoxToMemory is always set to false.
6587b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     */
6597b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    mWriteMoovBoxToMemory = false;
6607837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBuffer = NULL;
6617837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
6627837c17063a4c50bc856ba59418516fdab731de7James Dong
663b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeFtypBox(param);
66420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6657837c17063a4c50bc856ba59418516fdab731de7James Dong    mFreeBoxOffset = mOffset;
66620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6677837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mEstimatedMoovBoxSize == 0) {
6682dec2b5be2056c6d9428897dc672185872d30d17James Dong        int32_t bitRate = -1;
6692dec2b5be2056c6d9428897dc672185872d30d17James Dong        if (param) {
6702dec2b5be2056c6d9428897dc672185872d30d17James Dong            param->findInt32(kKeyBitRate, &bitRate);
6712dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
6722dec2b5be2056c6d9428897dc672185872d30d17James Dong        mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate);
6737837c17063a4c50bc856ba59418516fdab731de7James Dong    }
67443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GE(mEstimatedMoovBoxSize, 8);
67577e8ae9967a078770416619e99ddb5b010def312James Dong    if (mStreamableFile) {
67677e8ae9967a078770416619e99ddb5b010def312James Dong        // Reserve a 'free' box only for streamable file
67777e8ae9967a078770416619e99ddb5b010def312James Dong        lseek64(mFd, mFreeBoxOffset, SEEK_SET);
67877e8ae9967a078770416619e99ddb5b010def312James Dong        writeInt32(mEstimatedMoovBoxSize);
67977e8ae9967a078770416619e99ddb5b010def312James Dong        write("free", 4);
68077e8ae9967a078770416619e99ddb5b010def312James Dong        mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize;
68177e8ae9967a078770416619e99ddb5b010def312James Dong    } else {
68277e8ae9967a078770416619e99ddb5b010def312James Dong        mMdatOffset = mOffset;
68377e8ae9967a078770416619e99ddb5b010def312James Dong    }
6847837c17063a4c50bc856ba59418516fdab731de7James Dong
6857837c17063a4c50bc856ba59418516fdab731de7James Dong    mOffset = mMdatOffset;
686c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    lseek64(mFd, mMdatOffset, SEEK_SET);
6871acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
6881acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("????mdat", 8);
6891acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
6901acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("\x00\x00\x00\x01mdat????????", 16);
6911acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
6921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
6931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    status_t err = startWriterThread();
6941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (err != OK) {
6951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        return err;
6961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
6971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
6981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    err = startTracks(param);
699a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (err != OK) {
700a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return err;
70120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
7021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
703a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mStarted = true;
70425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
70520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
70620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7071f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongbool MPEG4Writer::use32BitFileOffset() const {
7081f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    return mUse32BitOffset;
7091f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
7101f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
71137187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::pause() {
712674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
71337187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
714a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
715a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
71637187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = OK;
717a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
718a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
71937187916a486504acaf83bea30147eb5fbf46ae5James Dong        status_t status = (*it)->pause();
72037187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (status != OK) {
72137187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
72237187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
723a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
72437187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
725a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
726a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
7271c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::stopWriterThread() {
728b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("Stopping writer thread");
729411ba422e3635d534928ffd81abf54f4f291c739James Dong    if (!mWriterThreadStarted) {
730411ba422e3635d534928ffd81abf54f4f291c739James Dong        return;
731411ba422e3635d534928ffd81abf54f4f291c739James Dong    }
7321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
7331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    {
7341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        Mutex::Autolock autolock(mLock);
7351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
7361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mDone = true;
7371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkReadyCondition.signal();
7381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
7391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
7401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void *dummy;
7411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_join(mThread, &dummy);
742411ba422e3635d534928ffd81abf54f4f291c739James Dong    mWriterThreadStarted = false;
743b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("Writer thread stopped");
7441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
7451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
74613f6284305e4b27395a23db7882d670bdb1bcae1James Dong/*
74713f6284305e4b27395a23db7882d670bdb1bcae1James Dong * MP4 file standard defines a composition matrix:
74813f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | a  b  u |
74913f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | c  d  v |
75013f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | x  y  w |
75113f6284305e4b27395a23db7882d670bdb1bcae1James Dong *
75213f6284305e4b27395a23db7882d670bdb1bcae1James Dong * the element in the matrix is stored in the following
75313f6284305e4b27395a23db7882d670bdb1bcae1James Dong * order: {a, b, u, c, d, v, x, y, w},
75413f6284305e4b27395a23db7882d670bdb1bcae1James Dong * where a, b, c, d, x, and y is in 16.16 format, while
75513f6284305e4b27395a23db7882d670bdb1bcae1James Dong * u, v and w is in 2.30 format.
75613f6284305e4b27395a23db7882d670bdb1bcae1James Dong */
75713f6284305e4b27395a23db7882d670bdb1bcae1James Dongvoid MPEG4Writer::writeCompositionMatrix(int degrees) {
7583856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("writeCompositionMatrix");
75913f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t a = 0x00010000;
76013f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t b = 0;
76113f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t c = 0;
76213f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t d = 0x00010000;
76313f6284305e4b27395a23db7882d670bdb1bcae1James Dong    switch (degrees) {
76413f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 0:
76513f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
76613f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 90:
76713f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0;
76813f6284305e4b27395a23db7882d670bdb1bcae1James Dong            b = 0x00010000;
76913f6284305e4b27395a23db7882d670bdb1bcae1James Dong            c = 0xFFFF0000;
77013f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0;
77113f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
77213f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 180:
77313f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0xFFFF0000;
77413f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0xFFFF0000;
77513f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
77613f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 270:
77713f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0;
77813f6284305e4b27395a23db7882d670bdb1bcae1James Dong            b = 0xFFFF0000;
77913f6284305e4b27395a23db7882d670bdb1bcae1James Dong            c = 0x00010000;
78013f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0;
78113f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
78213f6284305e4b27395a23db7882d670bdb1bcae1James Dong        default:
78313f6284305e4b27395a23db7882d670bdb1bcae1James Dong            CHECK(!"Should never reach this unknown rotation");
78413f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
78513f6284305e4b27395a23db7882d670bdb1bcae1James Dong    }
78613f6284305e4b27395a23db7882d670bdb1bcae1James Dong
78713f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(a);           // a
78813f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(b);           // b
78913f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // u
79013f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(c);           // c
79113f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(d);           // d
79213f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // v
79313f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // x
79413f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // y
79513f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0x40000000);  // w
79613f6284305e4b27395a23db7882d670bdb1bcae1James Dong}
79713f6284305e4b27395a23db7882d670bdb1bcae1James Dong
798411ba422e3635d534928ffd81abf54f4f291c739James Dongvoid MPEG4Writer::release() {
799411ba422e3635d534928ffd81abf54f4f291c739James Dong    close(mFd);
800411ba422e3635d534928ffd81abf54f4f291c739James Dong    mFd = -1;
801411ba422e3635d534928ffd81abf54f4f291c739James Dong    mInitCheck = NO_INIT;
802411ba422e3635d534928ffd81abf54f4f291c739James Dong    mStarted = false;
803411ba422e3635d534928ffd81abf54f4f291c739James Dong}
80413f6284305e4b27395a23db7882d670bdb1bcae1James Dong
8058bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dongstatus_t MPEG4Writer::reset() {
806674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
80737187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
808411ba422e3635d534928ffd81abf54f4f291c739James Dong    } else {
809411ba422e3635d534928ffd81abf54f4f291c739James Dong        if (!mWriterThreadStarted ||
810411ba422e3635d534928ffd81abf54f4f291c739James Dong            !mStarted) {
811411ba422e3635d534928ffd81abf54f4f291c739James Dong            if (mWriterThreadStarted) {
812411ba422e3635d534928ffd81abf54f4f291c739James Dong                stopWriterThread();
813411ba422e3635d534928ffd81abf54f4f291c739James Dong            }
814411ba422e3635d534928ffd81abf54f4f291c739James Dong            release();
815411ba422e3635d534928ffd81abf54f4f291c739James Dong            return OK;
816411ba422e3635d534928ffd81abf54f4f291c739James Dong        }
81720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
81820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
81937187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = OK;
8208f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t maxDurationUs = 0;
82165b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    int64_t minDurationUs = 0x7fffffffffffffffLL;
82220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
82320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber         it != mTracks.end(); ++it) {
82437187916a486504acaf83bea30147eb5fbf46ae5James Dong        status_t status = (*it)->stop();
82537187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (err == OK && status != OK) {
82637187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
82737187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
82820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8298f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int64_t durationUs = (*it)->getDurationUs();
8308f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        if (durationUs > maxDurationUs) {
8318f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            maxDurationUs = durationUs;
83220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
83365b3d76025c71d755b0fb3b6ead90255f25417edJames Dong        if (durationUs < minDurationUs) {
83465b3d76025c71d755b0fb3b6ead90255f25417edJames Dong            minDurationUs = durationUs;
83565b3d76025c71d755b0fb3b6ead90255f25417edJames Dong        }
83665b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    }
83765b3d76025c71d755b0fb3b6ead90255f25417edJames Dong
83865b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    if (mTracks.size() > 1) {
839a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGD("Duration from tracks range is [%" PRId64 ", %" PRId64 "] us",
84065b3d76025c71d755b0fb3b6ead90255f25417edJames Dong            minDurationUs, maxDurationUs);
84120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
84220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    stopWriterThread();
8447837c17063a4c50bc856ba59418516fdab731de7James Dong
84537187916a486504acaf83bea30147eb5fbf46ae5James Dong    // Do not write out movie header on error.
84637187916a486504acaf83bea30147eb5fbf46ae5James Dong    if (err != OK) {
847411ba422e3635d534928ffd81abf54f4f291c739James Dong        release();
84837187916a486504acaf83bea30147eb5fbf46ae5James Dong        return err;
84937187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
85037187916a486504acaf83bea30147eb5fbf46ae5James Dong
85120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // Fix up the size of the 'mdat' chunk.
8521acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
853c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mMdatOffset, SEEK_SET);
8541f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad        uint32_t size = htonl(static_cast<uint32_t>(mOffset - mMdatOffset));
855c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &size, 4);
8561acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
857c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mMdatOffset + 8, SEEK_SET);
8581f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad        uint64_t size = mOffset - mMdatOffset;
8591acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        size = hton64(size);
860c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &size, 8);
8611acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
862c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    lseek64(mFd, mOffset, SEEK_SET);
86320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8647b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // Construct moov box now
8657837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
8667b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    mWriteMoovBoxToMemory = mStreamableFile;
8677b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    if (mWriteMoovBoxToMemory) {
8687b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // There is no need to allocate in-memory cache
8697b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // for moov box if the file is not streamable.
8707b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
8717b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize);
8727b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        CHECK(mMoovBoxBuffer != NULL);
8737b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    }
874b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeMoovBox(maxDurationUs);
87520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8767b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // mWriteMoovBoxToMemory could be set to false in
8777b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // MPEG4Writer::write() method
8787b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    if (mWriteMoovBoxToMemory) {
8797b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        mWriteMoovBoxToMemory = false;
8807b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // Content of the moov box is saved in the cache, and the in-memory
8817b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // moov box needs to be written to the file in a single shot.
8827b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
88343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_LE(mMoovBoxBufferOffset + 8, mEstimatedMoovBoxSize);
8847837c17063a4c50bc856ba59418516fdab731de7James Dong
8857837c17063a4c50bc856ba59418516fdab731de7James Dong        // Moov box
886c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mFreeBoxOffset, SEEK_SET);
8877837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset = mFreeBoxOffset;
888674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset);
8897837c17063a4c50bc856ba59418516fdab731de7James Dong
8907837c17063a4c50bc856ba59418516fdab731de7James Dong        // Free box
891c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mOffset, SEEK_SET);
8927837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset);
8937837c17063a4c50bc856ba59418516fdab731de7James Dong        write("free", 4);
8947b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    } else {
8957b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        ALOGI("The mp4 file will not be streamable.");
8967b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    }
8977837c17063a4c50bc856ba59418516fdab731de7James Dong
8987b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // Free in-memory cache for moov box
8997b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    if (mMoovBoxBuffer != NULL) {
9007837c17063a4c50bc856ba59418516fdab731de7James Dong        free(mMoovBoxBuffer);
9017837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBuffer = NULL;
9027837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBufferOffset = 0;
9037837c17063a4c50bc856ba59418516fdab731de7James Dong    }
9047837c17063a4c50bc856ba59418516fdab731de7James Dong
9050c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(mBoxes.empty());
90620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
907411ba422e3635d534928ffd81abf54f4f291c739James Dong    release();
90837187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
90920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
91020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
911efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonuint32_t MPEG4Writer::getMpeg4Time() {
912b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    time_t now = time(NULL);
913efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    // MP4 file uses time counting seconds since midnight, Jan. 1, 1904
914efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    // while time function returns Unix epoch values which starts
915efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    // at 1970-01-01. Lets add the number of seconds between them
916efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    uint32_t mpeg4Time = now + (66 * 365 + 17) * (24 * 60 * 60);
917efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    return mpeg4Time;
918efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson}
919efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson
920efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::writeMvhdBox(int64_t durationUs) {
921efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    uint32_t now = getMpeg4Time();
922b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("mvhd");
923b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // version=0, flags=0
924b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(now);           // creation time
925b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(now);           // modification time
926b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(mTimeScale);    // mvhd timescale
927b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t duration = (durationUs * mTimeScale + 5E5) / 1E6;
928b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(duration);
929b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0x10000);       // rate: 1.0
930b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt16(0x100);         // volume
931b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt16(0);             // reserved
932b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // reserved
933b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // reserved
934b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeCompositionMatrix(0); // matrix
935b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
936b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
937b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
938b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
939b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
940b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
941b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(mTracks.size() + 1);  // nextTrackID
942b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();  // mvhd
943b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
944b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
945b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::writeMoovBox(int64_t durationUs) {
946b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("moov");
947b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeMvhdBox(durationUs);
94807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (mAreGeoTagsAvailable) {
94907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        writeUdtaBox();
95007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
951e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeMetaBox();
952b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t id = 1;
953b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    for (List<Track *>::iterator it = mTracks.begin();
954b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        it != mTracks.end(); ++it, ++id) {
955b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        (*it)->writeTrackHeader(mUse32BitOffset);
956b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
957b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();  // moov
958b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
959b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
9602cf9c5073ca3342ee52673ad68763fadd2c2be79James Dongvoid MPEG4Writer::writeFtypBox(MetaData *param) {
961b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("ftyp");
962b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
963b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t fileType;
964b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (param && param->findInt32(kKeyFileType, &fileType) &&
965b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        fileType != OUTPUT_FORMAT_MPEG_4) {
966b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeFourcc("3gp4");
9678284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeInt32(0);
9688284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("isom");
9698284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("3gp4");
970b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
9718284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("mp42");
9728284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeInt32(0);
973b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeFourcc("isom");
9748284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("mp42");
975b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
976b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
977b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();
978b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
979b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
98007ec01904613a0bac32caaa8444b4690998faed7James Dongstatic bool isTestModeEnabled() {
98107ec01904613a0bac32caaa8444b4690998faed7James Dong#if (PROPERTY_VALUE_MAX < 5)
98207ec01904613a0bac32caaa8444b4690998faed7James Dong#error "PROPERTY_VALUE_MAX must be at least 5"
98307ec01904613a0bac32caaa8444b4690998faed7James Dong#endif
98407ec01904613a0bac32caaa8444b4690998faed7James Dong
98507ec01904613a0bac32caaa8444b4690998faed7James Dong    // Test mode is enabled only if rw.media.record.test system
98607ec01904613a0bac32caaa8444b4690998faed7James Dong    // property is enabled.
98707ec01904613a0bac32caaa8444b4690998faed7James Dong    char value[PROPERTY_VALUE_MAX];
98807ec01904613a0bac32caaa8444b4690998faed7James Dong    if (property_get("rw.media.record.test", value, NULL) &&
98907ec01904613a0bac32caaa8444b4690998faed7James Dong        (!strcasecmp(value, "true") || !strcasecmp(value, "1"))) {
99007ec01904613a0bac32caaa8444b4690998faed7James Dong        return true;
99107ec01904613a0bac32caaa8444b4690998faed7James Dong    }
99207ec01904613a0bac32caaa8444b4690998faed7James Dong    return false;
99307ec01904613a0bac32caaa8444b4690998faed7James Dong}
99407ec01904613a0bac32caaa8444b4690998faed7James Dong
99570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongvoid MPEG4Writer::sendSessionSummary() {
99607ec01904613a0bac32caaa8444b4690998faed7James Dong    // Send session summary only if test mode is enabled
99707ec01904613a0bac32caaa8444b4690998faed7James Dong    if (!isTestModeEnabled()) {
99807ec01904613a0bac32caaa8444b4690998faed7James Dong        return;
99907ec01904613a0bac32caaa8444b4690998faed7James Dong    }
100007ec01904613a0bac32caaa8444b4690998faed7James Dong
100170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
100270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong         it != mChunkInfos.end(); ++it) {
100370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        int trackNum = it->mTrack->getTrackId() << 28;
100470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
100570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                trackNum | MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS,
100670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                it->mMaxInterChunkDurUs);
100770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    }
100870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong}
100970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
101013aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) {
101113aec890216948b0c364f8f92792129d0335f506James Dong    mInterleaveDurationUs = durationUs;
101213aec890216948b0c364f8f92792129d0335f506James Dong    return OK;
101313aec890216948b0c364f8f92792129d0335f506James Dong}
101413aec890216948b0c364f8f92792129d0335f506James Dong
101513aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() {
101613aec890216948b0c364f8f92792129d0335f506James Dong    mLock.lock();
101713aec890216948b0c364f8f92792129d0335f506James Dong}
101813aec890216948b0c364f8f92792129d0335f506James Dong
101913aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() {
102013aec890216948b0c364f8f92792129d0335f506James Dong    mLock.unlock();
102113aec890216948b0c364f8f92792129d0335f506James Dong}
102220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1023c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addSample_l(MediaBuffer *buffer) {
1024c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t old_offset = mOffset;
102520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1026c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    ::write(mFd,
1027c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong          (const uint8_t *)buffer->data() + buffer->range_offset(),
1028c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong          buffer->range_length());
102920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
103020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += buffer->range_length();
103120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
103220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return old_offset;
103320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
103420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
103503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) {
103603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (buffer->range_length() < 4) {
103703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return;
103803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
103903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
104003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    const uint8_t *ptr =
104103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        (const uint8_t *)buffer->data() + buffer->range_offset();
104203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
104303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) {
104403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        buffer->set_range(
104503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                buffer->range_offset() + 4, buffer->range_length() - 4);
104603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
104703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
104803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
1049c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) {
1050c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t old_offset = mOffset;
105130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
105230ab66297501757d745b9ae10da61adcd891f497Andreas Huber    size_t length = buffer->range_length();
105303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
1054b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (mUse4ByteNalLength) {
1055b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        uint8_t x = length >> 24;
1056c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1057b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = (length >> 16) & 0xff;
1058c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1059b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = (length >> 8) & 0xff;
1060c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1061b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = length & 0xff;
1062c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1063c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong
1064c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd,
1065c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong              (const uint8_t *)buffer->data() + buffer->range_offset(),
1066c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong              length);
1067b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong
1068b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mOffset += length + 4;
1069b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    } else {
107043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_LT(length, 65536);
107130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
1072b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        uint8_t x = length >> 8;
1073c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1074b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = length & 0xff;
1075c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1076c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, (const uint8_t *)buffer->data() + buffer->range_offset(), length);
1077b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mOffset += length + 2;
1078b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    }
107930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
108030ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return old_offset;
108130ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
108230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
10837837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write(
1084674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        const void *ptr, size_t size, size_t nmemb) {
10857837c17063a4c50bc856ba59418516fdab731de7James Dong
10867837c17063a4c50bc856ba59418516fdab731de7James Dong    const size_t bytes = size * nmemb;
10877837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
10887b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
1089c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes;
10901acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        if (moovBoxSize > mEstimatedMoovBoxSize) {
10917b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // The reserved moov box at the beginning of the file
10927b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // is not big enough. Moov box should be written to
10937b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // the end of the file from now on, but not to the
10947b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // in-memory cache.
10957b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
10967b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // We write partial moov box that is in the memory to
10977b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // the file first.
1098c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            for (List<off64_t>::iterator it = mBoxes.begin();
10997837c17063a4c50bc856ba59418516fdab731de7James Dong                 it != mBoxes.end(); ++it) {
11007837c17063a4c50bc856ba59418516fdab731de7James Dong                (*it) += mOffset;
11017837c17063a4c50bc856ba59418516fdab731de7James Dong            }
1102674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong            lseek64(mFd, mOffset, SEEK_SET);
1103674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong            ::write(mFd, mMoovBoxBuffer, mMoovBoxBufferOffset);
11047b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            ::write(mFd, ptr, bytes);
11057837c17063a4c50bc856ba59418516fdab731de7James Dong            mOffset += (bytes + mMoovBoxBufferOffset);
11067b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
11077b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // All subsequent moov box content will be written
11087b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // to the end of the file.
11097837c17063a4c50bc856ba59418516fdab731de7James Dong            mWriteMoovBoxToMemory = false;
11107837c17063a4c50bc856ba59418516fdab731de7James Dong        } else {
11117837c17063a4c50bc856ba59418516fdab731de7James Dong            memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes);
11127837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset += bytes;
11137837c17063a4c50bc856ba59418516fdab731de7James Dong        }
11147837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
1115674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        ::write(mFd, ptr, size * nmemb);
11167837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset += bytes;
11177837c17063a4c50bc856ba59418516fdab731de7James Dong    }
11187837c17063a4c50bc856ba59418516fdab731de7James Dong    return bytes;
11197837c17063a4c50bc856ba59418516fdab731de7James Dong}
11207837c17063a4c50bc856ba59418516fdab731de7James Dong
1121e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::beginBox(uint32_t id) {
1122e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    mBoxes.push_back(mWriteMoovBoxToMemory?
1123e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            mMoovBoxBufferOffset: mOffset);
1124e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
1125e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0);
1126e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(id);
1127e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
1128e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
112920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) {
11300c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(fourcc), 4);
113120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
11327837c17063a4c50bc856ba59418516fdab731de7James Dong    mBoxes.push_back(mWriteMoovBoxToMemory?
11337837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset: mOffset);
113420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
113520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeInt32(0);
113620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeFourcc(fourcc);
113720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
113820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
113920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() {
11400c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(!mBoxes.empty());
114120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1142c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t offset = *--mBoxes.end();
114320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mBoxes.erase(--mBoxes.end());
114420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
11457837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
11467837c17063a4c50bc856ba59418516fdab731de7James Dong       int32_t x = htonl(mMoovBoxBufferOffset - offset);
11477837c17063a4c50bc856ba59418516fdab731de7James Dong       memcpy(mMoovBoxBuffer + offset, &x, 4);
11487837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
1149c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, offset, SEEK_SET);
11507837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mOffset - offset);
11517837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset -= 4;
1152c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mOffset, SEEK_SET);
11537837c17063a4c50bc856ba59418516fdab731de7James Dong    }
115420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
115520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
115620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) {
1157674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 1);
115820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
115920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
116020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) {
116120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htons(x);
1162674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 2);
116320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
116420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
116520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) {
116620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htonl(x);
1167674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 4);
116820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
116920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
117020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) {
117120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = hton64(x);
1172674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 8);
117320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
117420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
117520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) {
117620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t n = strlen(s);
1177674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(s, 1, n + 1);
117820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
117920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
118020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) {
11810c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(s), 4);
1182674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(s, 1, 4);
118320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
118420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
118507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
118607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/-DD.DDDD format
118707b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLatitude(int degreex10000) {
118807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    bool isNegative = (degreex10000 < 0);
118907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char sign = isNegative? '-': '+';
119007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
119107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the whole part
119207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char str[9];
119307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int wholePart = degreex10000 / 10000;
119407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (wholePart == 0) {
119507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 5, "%c%.2d.", sign, wholePart);
119607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    } else {
119707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 5, "%+.2d.", wholePart);
119807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
119907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
120007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the fractional part
120107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int fractionalPart = degreex10000 - (wholePart * 10000);
120207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (fractionalPart < 0) {
120307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        fractionalPart = -fractionalPart;
120407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
120507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    snprintf(&str[4], 5, "%.4d", fractionalPart);
120607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
120707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Do not write the null terminator
120807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    write(str, 1, 8);
120907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
121007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
121107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/- DDD.DDDD format
121207b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLongitude(int degreex10000) {
121307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    bool isNegative = (degreex10000 < 0);
121407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char sign = isNegative? '-': '+';
121507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
121607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the whole part
121707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char str[10];
121807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int wholePart = degreex10000 / 10000;
121907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (wholePart == 0) {
122007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 6, "%c%.3d.", sign, wholePart);
122107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    } else {
122207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 6, "%+.3d.", wholePart);
122307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
122407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
122507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the fractional part
122607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int fractionalPart = degreex10000 - (wholePart * 10000);
122707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (fractionalPart < 0) {
122807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        fractionalPart = -fractionalPart;
122907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
123007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    snprintf(&str[5], 5, "%.4d", fractionalPart);
123107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
123207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Do not write the null terminator
123307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    write(str, 1, 9);
123407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
123507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
123607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/*
123707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard.
123807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * latitudex10000 is latitude in degrees times 10000, and
123907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * longitudex10000 is longitude in degrees times 10000.
124007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the latitude is in [-90, +90], and
124107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the longitude is in [-180, +180]
124207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */
124307b1bb529a1ae76c46a71b01338c166f9490629dJames Dongstatus_t MPEG4Writer::setGeoData(int latitudex10000, int longitudex10000) {
124407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Is latitude or longitude out of range?
124507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (latitudex10000 < -900000 || latitudex10000 > 900000 ||
124607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        longitudex10000 < -1800000 || longitudex10000 > 1800000) {
124707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        return BAD_VALUE;
124807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
124907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
125007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mLatitudex10000 = latitudex10000;
125107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mLongitudex10000 = longitudex10000;
125207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mAreGeoTagsAvailable = true;
125307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    return OK;
125407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
125507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
1256e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangstatus_t MPEG4Writer::setCaptureRate(float captureFps) {
1257e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    if (captureFps <= 0.0f) {
1258e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        return BAD_VALUE;
1259e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
1260e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
1261e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    mMetaKeys->setFloat("com.android.capture.fps", captureFps);
1262e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    return OK;
1263e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
1264e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
126520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) {
1266674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(data, 1, size);
126720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
126820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
126978a1a286f736888ae7af8860b2c424af0d978848James Dongbool MPEG4Writer::isFileStreamable() const {
127078a1a286f736888ae7af8860b2c424af0d978848James Dong    return mStreamableFile;
127178a1a286f736888ae7af8860b2c424af0d978848James Dong}
127278a1a286f736888ae7af8860b2c424af0d978848James Dong
1273d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() {
1274d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
1275d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileSizeLimitBytes == 0) {
1276d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
1277d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1278d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1279956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize);
1280d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
1281d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
1282d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes();
1283d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
12841f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
128577e8ae9967a078770416619e99ddb5b010def312James Dong    if (!mStreamableFile) {
128677e8ae9967a078770416619e99ddb5b010def312James Dong        // Add 1024 bytes as error tolerance
128777e8ae9967a078770416619e99ddb5b010def312James Dong        return nTotalBytesEstimate + 1024 >= mMaxFileSizeLimitBytes;
128877e8ae9967a078770416619e99ddb5b010def312James Dong    }
1289acd234bba9f048971d66890009eeff9a8db94be3James Dong    // Be conservative in the estimate: do not exceed 95% of
1290acd234bba9f048971d66890009eeff9a8db94be3James Dong    // the target file limit. For small target file size limit, though,
1291acd234bba9f048971d66890009eeff9a8db94be3James Dong    // this will not help.
1292acd234bba9f048971d66890009eeff9a8db94be3James Dong    return (nTotalBytesEstimate >= (95 * mMaxFileSizeLimitBytes) / 100);
1293d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
1294d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1295d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() {
1296d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
1297d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileDurationLimitUs == 0) {
1298d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
1299d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1300d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1301d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
1302d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
1303d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) {
1304d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            return true;
1305d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
1306d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1307d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return false;
1308d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
1309d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
131025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() {
131125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool allDone = true;
131225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
131325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber         it != mTracks.end(); ++it) {
131425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        if (!(*it)->reachedEOS()) {
131525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            allDone = false;
131625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            break;
131725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        }
131825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
131925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
132025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return allDone;
132125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
132225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
1323f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) {
1324a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGI("setStartTimestampUs: %" PRId64, timeUs);
132543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GE(timeUs, 0ll);
13263c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
1327065d1aff96818df54456053f1574aec8a234d0deJames Dong    if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) {
1328f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mStartTimestampUs = timeUs;
1329a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGI("Earliest track starting time: %" PRId64, mStartTimestampUs);
13303c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    }
13313c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
13323c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
1333f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() {
13343c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
13353c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    return mStartTimestampUs;
13363c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
13373c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
133858ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() {
133958ae9c530247668f8af36e30d228c716c226b3d4James Dong    Mutex::Autolock autolock(mLock);
134058ae9c530247668f8af36e30d228c716c226b3d4James Dong    return mTracks.size();
134158ae9c530247668f8af36e30d228c716c226b3d4James Dong}
134258ae9c530247668f8af36e30d228c716c226b3d4James Dong
134320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
134420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
134520111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track(
1346bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId)
134720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mOwner(owner),
134825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mMeta(source->getFormat()),
134920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSource(source),
135020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDone(false),
1351a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
1352a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mResumed(false),
1353eaae38445a340c4857c1c5569475879a728e63b7James Dong      mStarted(false),
1354bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong      mTrackId(trackId),
1355c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong      mTrackDurationUs(0),
1356956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      mEstimatedTrackSizeBytes(0),
1357be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong      mSamplesHaveSameSize(true),
1358c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mStszTableEntries(new ListTableEntries<uint32_t>(1000, 1)),
1359c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mStcoTableEntries(new ListTableEntries<uint32_t>(1000, 1)),
1360c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mCo64TableEntries(new ListTableEntries<off64_t>(1000, 1)),
1361c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mStscTableEntries(new ListTableEntries<uint32_t>(1000, 3)),
1362c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mStssTableEntries(new ListTableEntries<uint32_t>(1000, 1)),
1363c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mSttsTableEntries(new ListTableEntries<uint32_t>(1000, 2)),
1364c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mCttsTableEntries(new ListTableEntries<uint32_t>(1000, 2)),
136520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCodecSpecificData(NULL),
136625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mCodecSpecificDataSize(0),
1367548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber      mGotAllCodecSpecificData(false),
136813f6284305e4b27395a23db7882d670bdb1bcae1James Dong      mReachedEOS(false),
136913f6284305e4b27395a23db7882d670bdb1bcae1James Dong      mRotation(0) {
137019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    getCodecSpecificDataFromInputFormatIfPossible();
13718f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
13721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    const char *mime;
13731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mMeta->findCString(kKeyMIMEType, &mime);
13741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
13751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAudio = !strncasecmp(mime, "audio/", 6);
13761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
13771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong               !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC);
13781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1379c059860c73678a202bfa33062723e8f82fb779d9James Dong    setTimeScale();
1380c059860c73678a202bfa33062723e8f82fb779d9James Dong}
1381c059860c73678a202bfa33062723e8f82fb779d9James Dong
13821f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::updateTrackSizeEstimate() {
13831f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1384c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t stcoBoxCount = (mOwner->use32BitFileOffset()
1385c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                            ? mStcoTableEntries->count()
1386c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                            : mCo64TableEntries->count());
1387c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    int64_t stcoBoxSizeBytes = stcoBoxCount * 4;
1388c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mStszTableEntries->count() * 4);
13891f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
139078a1a286f736888ae7af8860b2c424af0d978848James Dong    mEstimatedTrackSizeBytes = mMdatSizeBytes;  // media data size
139178a1a286f736888ae7af8860b2c424af0d978848James Dong    if (!mOwner->isFileStreamable()) {
139278a1a286f736888ae7af8860b2c424af0d978848James Dong        // Reserved free space is not large enough to hold
139378a1a286f736888ae7af8860b2c424af0d978848James Dong        // all meta data and thus wasted.
1394c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mEstimatedTrackSizeBytes += mStscTableEntries->count() * 12 +  // stsc box size
1395c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mStssTableEntries->count() * 4 +   // stss box size
1396c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mSttsTableEntries->count() * 8 +   // stts box size
1397c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mCttsTableEntries->count() * 8 +   // ctts box size
139878a1a286f736888ae7af8860b2c424af0d978848James Dong                                    stcoBoxSizeBytes +           // stco box size
139978a1a286f736888ae7af8860b2c424af0d978848James Dong                                    stszBoxSizeBytes;            // stsz box size
140078a1a286f736888ae7af8860b2c424af0d978848James Dong    }
14011f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
14021f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
14031f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStscTableEntry(
14041f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        size_t chunkId, size_t sampleId) {
14051f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1406c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStscTableEntries->add(htonl(chunkId));
1407c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStscTableEntries->add(htonl(sampleId));
1408c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStscTableEntries->add(htonl(1));
14091f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
14101f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
14111f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) {
1412c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries->add(htonl(sampleId));
14131f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
14141f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
14151f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneSttsTableEntry(
141679761ab096f57c3027fad9556c2bc436672d614eJames Dong        size_t sampleCount, int32_t duration) {
14171f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
14185a217fba010e801c255503602bda4b86ac5a6ac9James Dong    if (duration == 0) {
1419377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        ALOGW("0-duration samples found: %zu", sampleCount);
14205a217fba010e801c255503602bda4b86ac5a6ac9James Dong    }
1421c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->add(htonl(sampleCount));
1422c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->add(htonl(duration));
14231f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
14241f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1425965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::addOneCttsTableEntry(
1426965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        size_t sampleCount, int32_t duration) {
1427965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
1428965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    if (mIsAudio) {
1429965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
1430965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
1431c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->add(htonl(sampleCount));
1432c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->add(htonl(duration));
1433965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong}
1434965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
1435c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongvoid MPEG4Writer::Track::addChunkOffset(off64_t offset) {
1436c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mOwner->use32BitFileOffset()) {
1437c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t value = offset;
1438c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStcoTableEntries->add(htonl(value));
1439c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    } else {
1440c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mCo64TableEntries->add(hton64(offset));
1441c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    }
14421f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
14431f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1444c059860c73678a202bfa33062723e8f82fb779d9James Dongvoid MPEG4Writer::Track::setTimeScale() {
14453856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setTimeScale");
1446c059860c73678a202bfa33062723e8f82fb779d9James Dong    // Default time scale
1447c059860c73678a202bfa33062723e8f82fb779d9James Dong    mTimeScale = 90000;
1448c059860c73678a202bfa33062723e8f82fb779d9James Dong
1449c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mIsAudio) {
1450c059860c73678a202bfa33062723e8f82fb779d9James Dong        // Use the sampling rate as the default time scale for audio track.
1451c059860c73678a202bfa33062723e8f82fb779d9James Dong        int32_t sampleRate;
1452c059860c73678a202bfa33062723e8f82fb779d9James Dong        bool success = mMeta->findInt32(kKeySampleRate, &sampleRate);
1453c059860c73678a202bfa33062723e8f82fb779d9James Dong        CHECK(success);
1454c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = sampleRate;
1455c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
1456c059860c73678a202bfa33062723e8f82fb779d9James Dong
1457c059860c73678a202bfa33062723e8f82fb779d9James Dong    // If someone would like to overwrite the timescale, use user-supplied value.
1458c059860c73678a202bfa33062723e8f82fb779d9James Dong    int32_t timeScale;
1459c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mMeta->findInt32(kKeyTimeScale, &timeScale)) {
1460c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = timeScale;
1461c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
1462c059860c73678a202bfa33062723e8f82fb779d9James Dong
146343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mTimeScale, 0);
146419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber}
146519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
146619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Hubervoid MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() {
146719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    const char *mime;
146819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
146919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
147019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
147119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        uint32_t type;
147219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        const void *data;
147319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        size_t size;
147419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        if (mMeta->findData(kKeyAVCC, &type, &data, &size)) {
147519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mCodecSpecificData = malloc(size);
147619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mCodecSpecificDataSize = size;
147719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            memcpy(mCodecSpecificData, data, size);
147819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mGotAllCodecSpecificData = true;
147919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        }
148019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
148119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
148219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        uint32_t type;
148319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        const void *data;
148419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        size_t size;
148519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        if (mMeta->findData(kKeyESDS, &type, &data, &size)) {
148619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            ESDS esds(data, size);
148719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            if (esds.getCodecSpecificInfo(&data, &size) == OK) {
148819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mCodecSpecificData = malloc(size);
148919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mCodecSpecificDataSize = size;
149019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                memcpy(mCodecSpecificData, data, size);
149119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mGotAllCodecSpecificData = true;
149219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            }
149319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        }
149419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
149520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
149620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
149720111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() {
149820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    stop();
149920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1500c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStszTableEntries;
1501c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStcoTableEntries;
1502c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mCo64TableEntries;
1503c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStscTableEntries;
1504c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mSttsTableEntries;
1505c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStssTableEntries;
1506c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mCttsTableEntries;
1507c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
1508c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStszTableEntries = NULL;
1509c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStcoTableEntries = NULL;
1510c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCo64TableEntries = NULL;
1511c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStscTableEntries = NULL;
1512c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries = NULL;
1513c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries = NULL;
1514c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries = NULL;
1515c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
151620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mCodecSpecificData != NULL) {
151720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        free(mCodecSpecificData);
151820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mCodecSpecificData = NULL;
151920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
152020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
152120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
152293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) {
15233856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("initTrackingProgressStatus");
152493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mPreviousTrackTimeUs = -1;
152593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackingProgressStatus = false;
152693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackEveryTimeDurationUs = 0;
152793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    {
152893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        int64_t timeUs;
152993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) {
1530a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGV("Receive request to track progress status for every %" PRId64 " us", timeUs);
153193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackEveryTimeDurationUs = timeUs;
153293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackingProgressStatus = true;
153393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
153493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
153593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
153693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
15371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong// static
15381c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid *MPEG4Writer::ThreadWrapper(void *me) {
15393856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("ThreadWrapper: %p", me);
15401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    MPEG4Writer *writer = static_cast<MPEG4Writer *>(me);
15411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    writer->threadFunc();
15421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return NULL;
15431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
15441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
15451c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::bufferChunk(const Chunk& chunk) {
15463856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("bufferChunk: %p", chunk.mTrack);
15471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Mutex::Autolock autolock(mLock);
15481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    CHECK_EQ(mDone, false);
15491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
15501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
15511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
15521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
15531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (chunk.mTrack == it->mTrack) {  // Found owner
15541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            it->mChunks.push_back(chunk);
15551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.signal();
15561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            return;
15571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
15581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
15591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
156043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK(!"Received a chunk for a unknown track");
15611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
15621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1563fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeChunkToFile(Chunk* chunk) {
1564a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("writeChunkToFile: %" PRId64 " from %s track",
15655410afcbb0af5d29d9f710a1c2978c500f9792dcPannag Sanketi        chunk->mTimeStampUs, chunk->mTrack->isAudio()? "audio": "video");
1566fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1567fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    int32_t isFirstSample = true;
1568fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    while (!chunk->mSamples.empty()) {
1569fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        List<MediaBuffer *>::iterator it = chunk->mSamples.begin();
1570fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1571fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        off64_t offset = chunk->mTrack->isAvc()
1572fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong                                ? addLengthPrefixedSample_l(*it)
1573fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong                                : addSample_l(*it);
1574fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1575fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        if (isFirstSample) {
1576fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            chunk->mTrack->addChunkOffset(offset);
1577fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            isFirstSample = false;
15781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
15791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
15801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it)->release();
15811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it) = NULL;
1582fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        chunk->mSamples.erase(it);
15831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1584fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    chunk->mSamples.clear();
15851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
15861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1587fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeAllChunks() {
15883856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("writeAllChunks");
15891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    size_t outstandingChunks = 0;
159070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    Chunk chunk;
159170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    while (findChunkToWrite(&chunk)) {
1592e9f6d0579603372fd2547e6c5ba6e114c6f8cba7James Dong        writeChunkToFile(&chunk);
159370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        ++outstandingChunks;
15941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
159570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
159670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    sendSessionSummary();
159770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
15981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mChunkInfos.clear();
1599377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    ALOGD("%zu chunks are written in the last batch", outstandingChunks);
16001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
16011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1602fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongbool MPEG4Writer::findChunkToWrite(Chunk *chunk) {
16033856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("findChunkToWrite");
16041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
16051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL;
16061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Track *track = NULL;
16071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
16081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
16091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (!it->mChunks.empty()) {
16101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            List<Chunk>::iterator chunkIt = it->mChunks.begin();
16111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (chunkIt->mTimeStampUs < minTimestampUs) {
16121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                minTimestampUs = chunkIt->mTimeStampUs;
16131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                track = it->mTrack;
16141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            }
16151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
16161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
16171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
16181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (track == NULL) {
16193856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("Nothing to be written after all");
1620fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        return false;
16211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
16221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
16231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (mIsFirstChunk) {
16241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsFirstChunk = false;
16251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1626fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
16271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
16281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
16291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (it->mTrack == track) {
1630fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            *chunk = *(it->mChunks.begin());
1631fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            it->mChunks.erase(it->mChunks.begin());
1632fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            CHECK_EQ(chunk->mTrack, track);
163370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
163470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            int64_t interChunkTimeUs =
163570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                chunk->mTimeStampUs - it->mPrevChunkTimestampUs;
163670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            if (interChunkTimeUs > it->mPrevChunkTimestampUs) {
163770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                it->mMaxInterChunkDurUs = interChunkTimeUs;
163870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            }
163970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
1640fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            return true;
16411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
16421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1643fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1644fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    return false;
16451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
16461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
16471c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::threadFunc() {
16483856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("threadFunc");
16491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1650a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    prctl(PR_SET_NAME, (unsigned long)"MPEG4Writer", 0, 0, 0);
1651fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1652fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    Mutex::Autolock autoLock(mLock);
16531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    while (!mDone) {
1654fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        Chunk chunk;
1655fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        bool chunkFound = false;
1656fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1657fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        while (!mDone && !(chunkFound = findChunkToWrite(&chunk))) {
16581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.wait(mLock);
16591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
16601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1661de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // In real time recording mode, write without holding the lock in order
1662de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // to reduce the blocking time for media track threads.
1663de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // Otherwise, hold the lock until the existing chunks get written to the
1664de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // file.
1665fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        if (chunkFound) {
1666de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            if (mIsRealTimeRecording) {
1667de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui                mLock.unlock();
1668de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            }
1669fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            writeChunkToFile(&chunk);
1670de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            if (mIsRealTimeRecording) {
1671de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui                mLock.lock();
1672de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            }
1673fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        }
16741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1675fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1676fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    writeAllChunks();
16771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
16781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
16791c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::startWriterThread() {
16803856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("startWriterThread");
16811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
16821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mDone = false;
16831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsFirstChunk = true;
1684e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    mDriftTimeUs = 0;
16851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<Track *>::iterator it = mTracks.begin();
16861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mTracks.end(); ++it) {
16871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        ChunkInfo info;
16881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        info.mTrack = *it;
168970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        info.mPrevChunkTimestampUs = 0;
169070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        info.mMaxInterChunkDurUs = 0;
16911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkInfos.push_back(info);
16921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
16931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
16941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_t attr;
16951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_init(&attr);
16961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
16971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_create(&mThread, &attr, ThreadWrapper, this);
16981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_destroy(&attr);
1699411ba422e3635d534928ffd81abf54f4f291c739James Dong    mWriterThreadStarted = true;
17001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return OK;
17011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
17021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17031f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
170493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) {
1705a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (!mDone && mPaused) {
1706a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mPaused = false;
1707a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mResumed = true;
1708a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
1709a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
171025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
171193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t startTimeUs;
171219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) {
171319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        startTimeUs = 0;
171419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
171570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    mStartTimeRealUs = startTimeUs;
171619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
171713f6284305e4b27395a23db7882d670bdb1bcae1James Dong    int32_t rotationDegrees;
171813f6284305e4b27395a23db7882d670bdb1bcae1James Dong    if (!mIsAudio && params && params->findInt32(kKeyRotation, &rotationDegrees)) {
171913f6284305e4b27395a23db7882d670bdb1bcae1James Dong        mRotation = rotationDegrees;
172013f6284305e4b27395a23db7882d670bdb1bcae1James Dong    }
172113f6284305e4b27395a23db7882d670bdb1bcae1James Dong
172293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    initTrackingProgressStatus(params);
172393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
1724f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    sp<MetaData> meta = new MetaData;
1725de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    if (mOwner->isRealTimeRecording() && mOwner->numTracks() > 1) {
1726a472613aec322e25891abf5c77bf3f7e3c244920James Dong        /*
1727a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * This extra delay of accepting incoming audio/video signals
1728a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * helps to align a/v start time at the beginning of a recording
1729a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * session, and it also helps eliminate the "recording" sound for
1730a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * camcorder applications.
1731a472613aec322e25891abf5c77bf3f7e3c244920James Dong         *
173286b7f47aa7482424cf8fd248f1315311919be3b0James Dong         * If client does not set the start time offset, we fall back to
173386b7f47aa7482424cf8fd248f1315311919be3b0James Dong         * use the default initial delay value.
1734a472613aec322e25891abf5c77bf3f7e3c244920James Dong         */
173586b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL;
173686b7f47aa7482424cf8fd248f1315311919be3b0James Dong        if (startTimeOffsetUs < 0) {  // Start time offset was not set
173786b7f47aa7482424cf8fd248f1315311919be3b0James Dong            startTimeOffsetUs = kInitialDelayTimeUs;
173886b7f47aa7482424cf8fd248f1315311919be3b0James Dong        }
173986b7f47aa7482424cf8fd248f1315311919be3b0James Dong        startTimeUs += startTimeOffsetUs;
1740a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGI("Start time offset: %" PRId64 " us", startTimeOffsetUs);
1741a472613aec322e25891abf5c77bf3f7e3c244920James Dong    }
1742a472613aec322e25891abf5c77bf3f7e3c244920James Dong
1743f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    meta->setInt64(kKeyTime, startTimeUs);
1744a472613aec322e25891abf5c77bf3f7e3c244920James Dong
1745f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    status_t err = mSource->start(meta.get());
174625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    if (err != OK) {
174725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        mDone = mReachedEOS = true;
174825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return err;
174925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
175020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
175120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_t attr;
175220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_init(&attr);
175320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
175420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
175520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = false;
1756eaae38445a340c4857c1c5569475879a728e63b7James Dong    mStarted = true;
1757c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs = 0;
175825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = false;
1759956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    mEstimatedTrackSizeBytes = 0;
17601f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mMdatSizeBytes = 0;
176143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mMaxChunkDurationUs = 0;
176220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
176325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    pthread_create(&mThread, &attr, ThreadWrapper, this);
176420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_destroy(&attr);
176525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
176625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
176720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
176820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
176937187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::pause() {
1770a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
177137187916a486504acaf83bea30147eb5fbf46ae5James Dong    return OK;
1772a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
1773a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
177437187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::stop() {
177572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGD("%s track stopping", mIsAudio? "Audio": "Video");
1776eaae38445a340c4857c1c5569475879a728e63b7James Dong    if (!mStarted) {
177729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Stop() called but track is not started");
1778eaae38445a340c4857c1c5569475879a728e63b7James Dong        return ERROR_END_OF_STREAM;
1779eaae38445a340c4857c1c5569475879a728e63b7James Dong    }
1780eaae38445a340c4857c1c5569475879a728e63b7James Dong
178120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mDone) {
178237187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
178320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
178420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = true;
178520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
178672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGD("%s track source stopping", mIsAudio? "Audio": "Video");
178772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mSource->stop();
178872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGD("%s track source stopped", mIsAudio? "Audio": "Video");
178972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
179020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *dummy;
179120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_join(mThread, &dummy);
1792377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    status_t err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy));
179337187916a486504acaf83bea30147eb5fbf46ae5James Dong
1794b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("%s track stopped", mIsAudio? "Audio": "Video");
179537187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
179620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
179720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
179825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() {
179925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return mReachedEOS;
180025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
180125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
180220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static
180320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) {
180420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = static_cast<Track *>(me);
180520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
180637187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = track->threadEntry();
1807377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    return (void *)(uintptr_t)err;
180820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
180920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
18103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic void getNalUnitType(uint8_t byte, uint8_t* type) {
18113856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("getNalUnitType: %d", byte);
18123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
18133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // nal_unit_type: 5-bit unsigned integer
18143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *type = (byte & 0x1F);
18153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
18163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
18173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t *findNextStartCode(
18183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length) {
18193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
1820a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("findNextStartCode: %p %zu", data, length);
18213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
18223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t bytesLeft = length;
18233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    while (bytesLeft > 4  &&
18243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            memcmp("\x00\x00\x00\x01", &data[length - bytesLeft], 4)) {
18253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        --bytesLeft;
18263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
18273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (bytesLeft <= 4) {
18283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        bytesLeft = 0; // Last parameter set
18293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
18303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return &data[length - bytesLeft];
18313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
18323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
18333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongconst uint8_t *MPEG4Writer::Track::parseParamSet(
18343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen) {
18353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
18363856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("parseParamSet");
18373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    CHECK(type == kNalUnitTypeSeqParamSet ||
18383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong          type == kNalUnitTypePicParamSet);
18393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
18403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *nextStartCode = findNextStartCode(data, length);
18413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *paramSetLen = nextStartCode - data;
18423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (*paramSetLen == 0) {
184329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Param set is malformed, since its length is 0");
18443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return NULL;
18453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
18463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
18473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    AVCParamSet paramSet(*paramSetLen, data);
18483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (type == kNalUnitTypeSeqParamSet) {
18493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (*paramSetLen < 4) {
185029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Seq parameter set malformed");
18513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return NULL;
18523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
18533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mSeqParamSets.empty()) {
18543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc = data[1];
18553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileCompatible = data[2];
18563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mLevelIdc = data[3];
18573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
18583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (mProfileIdc != data[1] ||
18593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mProfileCompatible != data[2] ||
18603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mLevelIdc != data[3]) {
186129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("Inconsistent profile/level found in seq parameter sets");
18623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return NULL;
18633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
18643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
18653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mSeqParamSets.push_back(paramSet);
18663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    } else {
18673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mPicParamSets.push_back(paramSet);
18683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
18693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return nextStartCode;
18703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
18713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
18723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::copyAVCCodecSpecificData(
18733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
18743856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("copyAVCCodecSpecificData");
18753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
18763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 2 bytes for each of the parameter set length field
18773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // plus the 7 bytes for the header
18783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (size < 4 + 7) {
1879377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        ALOGE("Codec specific data length too short: %zu", size);
18803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return ERROR_MALFORMED;
18813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
18823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
18833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize = size;
18843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificData = malloc(size);
18853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    memcpy(mCodecSpecificData, data, size);
18863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
18873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
18883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
18893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::parseAVCCodecSpecificData(
18903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
18913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
18923856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("parseAVCCodecSpecificData");
18933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data starts with a start code.
18943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // SPS and PPS are separated with start codes.
18953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Also, SPS must come before PPS
18963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t type = kNalUnitTypeSeqParamSet;
18973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotSps = false;
18983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotPps = false;
18993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *tmp = data;
19003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *nextStartCode = data;
19013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t bytesLeft = size;
19023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t paramSetLen = 0;
19033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize = 0;
19043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) {
19053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        getNalUnitType(*(tmp + 4), &type);
19063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (type == kNalUnitTypeSeqParamSet) {
19073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (gotPps) {
190829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("SPS must come before PPS");
19093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
19103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
19113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
19123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotSps = true;
19133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
19143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
19153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else if (type == kNalUnitTypePicParamSet) {
19163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
191729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("SPS must come before PPS");
19183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
19193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
19203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotPps) {
19213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotPps = true;
19223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
19233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
19243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
192529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Only SPS and PPS Nal units are expected");
19263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
19273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
19283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nextStartCode == NULL) {
19303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
19313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
19323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Move on to find the next parameter set
19343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        bytesLeft -= nextStartCode - tmp;
19353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        tmp = nextStartCode;
19363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mCodecSpecificDataSize += (2 + paramSetLen);
19373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
19383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
19403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of seq parameter sets
19413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nSeqParamSets = mSeqParamSets.size();
19423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets == 0) {
194329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Cound not find sequence parameter set");
19443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
19453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
19463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets > 0x1F) {
1948377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT            ALOGE("Too many seq parameter sets (%zu) found", nSeqParamSets);
19493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
19503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
19513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
19523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
19543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of pic parameter sets
19553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nPicParamSets = mPicParamSets.size();
19563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets == 0) {
195729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Cound not find picture parameter set");
19583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
19593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
19603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets > 0xFF) {
1961377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT            ALOGE("Too many pic parameter sets (%zd) found", nPicParamSets);
19623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
19633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
19643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
19651374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// FIXME:
19661374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// Add chromat_format_idc, bit depth values, etc for AVC/h264 high profile and above
19671374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// and remove #if 0
19681374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#if 0
19693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
19703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the profiles
19713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // These profiles requires additional parameter set extensions
19723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mProfileIdc == 100 || mProfileIdc == 110 ||
19733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc == 122 || mProfileIdc == 144) {
197429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Sorry, no support for profile_idc: %d!", mProfileIdc);
19753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return BAD_VALUE;
19763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
19773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
19781374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#endif
19793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
19803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
1981548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
198203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData(
198303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        const uint8_t *data, size_t size) {
1984548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
198503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (mCodecSpecificData != NULL) {
198629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Already have codec specific data");
198703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
198803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
198903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
19903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (size < 4) {
1991377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        ALOGE("Codec specific data length too short: %zu", size);
199203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
199303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
199403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
19953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data is in the form of AVCCodecSpecificData
19963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (memcmp("\x00\x00\x00\x01", data, 4)) {
19973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return copyAVCCodecSpecificData(data, size);
199803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
199903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
20003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (parseAVCCodecSpecificData(data, size) != OK) {
200103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
200203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
200303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
20043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // ISO 14496-15: AVC file format
20053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize += 7;  // 7 more bytes in the header
200603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    mCodecSpecificData = malloc(mCodecSpecificDataSize);
200703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    uint8_t *header = (uint8_t *)mCodecSpecificData;
20083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = 1;                     // version
20093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[1] = mProfileIdc;           // profile indication
20103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[2] = mProfileCompatible;    // profile compatibility
20113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[3] = mLevelIdc;
201203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
20133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne
2014b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (mOwner->useNalLengthFour()) {
2015b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        header[4] = 0xfc | 3;  // length size == 4 bytes
2016b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    } else {
2017b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        header[4] = 0xfc | 1;  // length size == 2 bytes
2018b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    }
201903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
20203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 3-bit '111' followed by 5-bit numSequenceParameterSets
20213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nSequenceParamSets = mSeqParamSets.size();
20223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[5] = 0xe0 | nSequenceParamSets;
20233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 6;
20243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mSeqParamSets.begin();
20253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mSeqParamSets.end(); ++it) {
20263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit sequence parameter set length
20273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t seqParamSetLength = it->mLength;
20283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = seqParamSetLength >> 8;
20293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = seqParamSetLength & 0xff;
20303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // SPS NAL unit (sequence parameter length bytes)
20323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, seqParamSetLength);
20333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + seqParamSetLength);
20343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
20353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 8-bit nPictureParameterSets
20373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nPictureParamSets = mPicParamSets.size();
20383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = nPictureParamSets;
20393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 1;
20403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mPicParamSets.begin();
20413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mPicParamSets.end(); ++it) {
20423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit picture parameter set length
20433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t picParamSetLength = it->mLength;
20443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = picParamSetLength >> 8;
20453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = picParamSetLength & 0xff;
20463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // PPS Nal unit (picture parameter set length bytes)
20483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, picParamSetLength);
20493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + picParamSetLength);
20503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
205103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
205203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    return OK;
205303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
205403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
2055872a481558350634a3fd5cb67939de288af00ecbJames Dong/*
2056872a481558350634a3fd5cb67939de288af00ecbJames Dong * Updates the drift time from the audio track so that
2057872a481558350634a3fd5cb67939de288af00ecbJames Dong * the video track can get the updated drift time information
2058872a481558350634a3fd5cb67939de288af00ecbJames Dong * from the file writer. The fluctuation of the drift time of the audio
2059872a481558350634a3fd5cb67939de288af00ecbJames Dong * encoding path is smoothed out with a simple filter by giving a larger
2060872a481558350634a3fd5cb67939de288af00ecbJames Dong * weight to more recently drift time. The filter coefficients, 0.5 and 0.5,
2061872a481558350634a3fd5cb67939de288af00ecbJames Dong * are heuristically determined.
2062872a481558350634a3fd5cb67939de288af00ecbJames Dong */
2063872a481558350634a3fd5cb67939de288af00ecbJames Dongvoid MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) {
2064872a481558350634a3fd5cb67939de288af00ecbJames Dong    int64_t driftTimeUs = 0;
2065872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) {
2066872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t prevDriftTimeUs = mOwner->getDriftTimeUs();
2067872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1;
2068872a481558350634a3fd5cb67939de288af00ecbJames Dong        mOwner->setDriftTimeUs(timeUs);
2069872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
2070872a481558350634a3fd5cb67939de288af00ecbJames Dong}
2071872a481558350634a3fd5cb67939de288af00ecbJames Dong
207237187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::threadEntry() {
207330ab66297501757d745b9ae10da61adcd891f497Andreas Huber    int32_t count = 0;
207413aec890216948b0c364f8f92792129d0335f506James Dong    const int64_t interleaveDurationUs = mOwner->interleaveDuration();
207543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    const bool hasMultipleTracks = (mOwner->numTracks() > 1);
207613aec890216948b0c364f8f92792129d0335f506James Dong    int64_t chunkTimestampUs = 0;
207713aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nChunks = 0;
207813aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nZeroLengthFrames = 0;
2079965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastTimestampUs = 0;      // Previous sample time stamp
2080965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastDurationUs = 0;       // Between the previous two samples
2081965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t currDurationTicks = 0;    // Timescale based ticks
2082965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastDurationTicks = 0;    // Timescale based ticks
2083965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int32_t sampleCount = 1;          // Sample count in the current stts table entry
2084000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    uint32_t previousSampleSize = 0;  // Size of the previous sample
2085a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    int64_t previousPausedDurationUs = 0;
2086965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t timestampUs = 0;
2087000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t cttsOffsetTimeUs = 0;
2088000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t currCttsOffsetTimeTicks = 0;   // Timescale based ticks
2089000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t lastCttsOffsetTimeTicks = -1;  // Timescale based ticks
209043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    int32_t cttsSampleCount = 0;           // Sample count in the current ctts table entry
2091c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t lastSamplesPerChunk = 0;
2092e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
2093a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    if (mIsAudio) {
2094a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong        prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0);
2095a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    } else {
2096a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong        prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0);
2097a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    }
2098de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui
2099de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    if (mOwner->isRealTimeRecording()) {
2100de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
2101de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    }
2102985f838934510983d8a887461e98dca60a6e858fJames Dong
2103d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong    sp<MetaData> meta_data;
210420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
210593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t err = OK;
210620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBuffer *buffer;
210711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih    const char *trackName = mIsAudio ? "Audio" : "Video";
210893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    while (!mDone && (err = mSource->read(&buffer)) == OK) {
210920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (buffer->range_length() == 0) {
211020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer->release();
211120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer = NULL;
211213aec890216948b0c364f8f92792129d0335f506James Dong            ++nZeroLengthFrames;
211320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            continue;
211420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
211520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2116a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // If the codec specific data has not been received yet, delay pause.
2117a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // After the codec specific data is received, discard what we received
2118a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // when the track is to be paused.
2119a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused && !mResumed) {
2120a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer->release();
2121a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer = NULL;
2122a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            continue;
2123a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
2124a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
212530ab66297501757d745b9ae10da61adcd891f497Andreas Huber        ++count;
212630ab66297501757d745b9ae10da61adcd891f497Andreas Huber
212703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        int32_t isCodecConfig;
212803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig)
212903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                && isCodecConfig) {
2130548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            CHECK(!mGotAllCodecSpecificData);
2131548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
21321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (mIsAvc) {
213303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                status_t err = makeAVCCodecSpecificData(
213403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        (const uint8_t *)buffer->data()
213503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                            + buffer->range_offset(),
213603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        buffer->range_length());
213743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                CHECK_EQ((status_t)OK, err);
21381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            } else if (mIsMPEG4) {
213903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificDataSize = buffer->range_length();
214003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificData = malloc(mCodecSpecificDataSize);
214103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                memcpy(mCodecSpecificData,
214203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        (const uint8_t *)buffer->data()
214303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                            + buffer->range_offset(),
214403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                       buffer->range_length());
214530ab66297501757d745b9ae10da61adcd891f497Andreas Huber            }
214630ab66297501757d745b9ae10da61adcd891f497Andreas Huber
214730ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer->release();
214830ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer = NULL;
214930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
2150548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            mGotAllCodecSpecificData = true;
215130ab66297501757d745b9ae10da61adcd891f497Andreas Huber            continue;
2152a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
2153a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
2154d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // Make a deep copy of the MediaBuffer and Metadata and release
2155d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // the original as soon as we can
2156d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        MediaBuffer *copy = new MediaBuffer(buffer->range_length());
2157d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(),
2158d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong                buffer->range_length());
2159d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        copy->set_range(0, buffer->range_length());
2160d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data = new MetaData(*buffer->meta_data().get());
2161d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer->release();
2162d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer = NULL;
2163d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
21641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (mIsAvc) StripStartcode(copy);
2165e136c3bb38e88315bf8797a464ebf2c788296b22James Dong
2166b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        size_t sampleSize = copy->range_length();
2167b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        if (mIsAvc) {
2168b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            if (mOwner->useNalLengthFour()) {
2169b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                sampleSize += 4;
2170b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            } else {
2171b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                sampleSize += 2;
2172b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            }
2173b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        }
2174050b28a593350047845a45a14cc5026221ac1620James Dong
2175d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        // Max file size or duration handling
21761f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mMdatSizeBytes += sampleSize;
21771f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        updateTrackSizeEstimate();
21781f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
2179d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileSizeLimit()) {
2180d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
2181d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
2182d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
2183d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileDurationLimit()) {
2184d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
2185d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
2186d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
2187d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
2188050b28a593350047845a45a14cc5026221ac1620James Dong
2189d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        int32_t isSync = false;
2190d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data->findInt32(kKeyIsSyncFrame, &isSync);
2191d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        CHECK(meta_data->findInt64(kKeyTime, &timestampUs));
2192d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
2193d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong////////////////////////////////////////////////////////////////////////////////
2194c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        if (mStszTableEntries->count() == 0) {
219570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            mFirstSampleTimeRealUs = systemTime() / 1000;
2196f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mStartTimestampUs = timestampUs;
2197f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mOwner->setStartTimestampUs(mStartTimestampUs);
21988428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            previousPausedDurationUs = mStartTimestampUs;
21993c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        }
220048c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber
2201a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mResumed) {
22028428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs;
220311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(durExcludingEarlierPausesUs >= 0ll, "for %s track", trackName)) {
220411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
220511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                return ERROR_MALFORMED;
220611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
220711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
22088428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs;
220911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(pausedDurationUs >= lastDurationUs, "for %s track", trackName)) {
221011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
221111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                return ERROR_MALFORMED;
221211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
221311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
22148428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            previousPausedDurationUs += pausedDurationUs - lastDurationUs;
2215a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mResumed = false;
2216a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
2217a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
2218a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        timestampUs -= previousPausedDurationUs;
221911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) {
222011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            copy->release();
222111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            return ERROR_MALFORMED;
222211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        }
222311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
2224000e18370baae60ffd9f25b509501dd8c26deabfJames Dong        if (!mIsAudio) {
2225965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            /*
2226965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             * Composition time: timestampUs
2227965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             * Decoding time: decodingTimeUs
2228000e18370baae60ffd9f25b509501dd8c26deabfJames Dong             * Composition time offset = composition time - decoding time
2229965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             */
2230965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            int64_t decodingTimeUs;
2231965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs));
2232965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            decodingTimeUs -= previousPausedDurationUs;
2233000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            cttsOffsetTimeUs =
2234000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs;
223511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(cttsOffsetTimeUs >= 0ll, "for %s track", trackName)) {
223611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
223711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                return ERROR_MALFORMED;
223811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
223911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
2240965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            timestampUs = decodingTimeUs;
2241a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGV("decoding time: %" PRId64 " and ctts offset time: %" PRId64,
2242000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                timestampUs, cttsOffsetTimeUs);
2243000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2244000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            // Update ctts box table if necessary
2245000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            currCttsOffsetTimeTicks =
2246000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    (cttsOffsetTimeUs * mTimeScale + 500000LL) / 1000000LL;
224711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(currCttsOffsetTimeTicks <= 0x0FFFFFFFFLL, "for %s track", trackName)) {
224811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
224911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                return ERROR_MALFORMED;
225011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
225111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
2252c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() == 0) {
225343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // Force the first ctts table entry to have one single entry
225443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // so that we can do adjustment for the initial track start
225543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // time offset easily in writeCttsBox().
225643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks;
225743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                addOneCttsTableEntry(1, currCttsOffsetTimeTicks);
225843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                cttsSampleCount = 0;      // No sample in ctts box is pending
225943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            } else {
226043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                if (currCttsOffsetTimeTicks != lastCttsOffsetTimeTicks) {
226143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
226243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks;
226343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    cttsSampleCount = 1;  // One sample in ctts box is pending
226443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                } else {
226543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    ++cttsSampleCount;
226643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                }
226743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            }
2268000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2269000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            // Update ctts time offset range
2270c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() == 0) {
2271000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2272000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2273000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            } else {
2274000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                if (currCttsOffsetTimeTicks > mMaxCttsOffsetTimeUs) {
2275000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2276000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                } else if (currCttsOffsetTimeTicks < mMinCttsOffsetTimeUs) {
2277000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2278000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                }
2279000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            }
2280000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2281965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        }
2282872a481558350634a3fd5cb67939de288af00ecbJames Dong
2283de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        if (mOwner->isRealTimeRecording()) {
2284872a481558350634a3fd5cb67939de288af00ecbJames Dong            if (mIsAudio) {
2285872a481558350634a3fd5cb67939de288af00ecbJames Dong                updateDriftTime(meta_data);
2286e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            }
2287e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        }
2288872a481558350634a3fd5cb67939de288af00ecbJames Dong
228911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) {
229011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            copy->release();
229111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            return ERROR_MALFORMED;
229211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        }
229311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
2294a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("%s media time stamp: %" PRId64 " and previous paused duration %" PRId64,
229511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                trackName, timestampUs, previousPausedDurationUs);
2296c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong        if (timestampUs > mTrackDurationUs) {
2297c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong            mTrackDurationUs = timestampUs;
22983b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber        }
22993b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber
23005a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // We need to use the time scale based ticks, rather than the
23015a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // timestamp itself to determine whether we have to use a new
23025a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // stts entry, since we may have rounding errors.
23035a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // The calculation is intended to reduce the accumulated
23045a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // rounding errors.
23055a217fba010e801c255503602bda4b86ac5a6ac9James Dong        currDurationTicks =
23065a217fba010e801c255503602bda4b86ac5a6ac9James Dong            ((timestampUs * mTimeScale + 500000LL) / 1000000LL -
23075a217fba010e801c255503602bda4b86ac5a6ac9James Dong                (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL);
2308c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        if (currDurationTicks < 0ll) {
2309a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGE("timestampUs %" PRId64 " < lastTimestampUs %" PRId64 " for %s track",
231011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                timestampUs, lastTimestampUs, trackName);
231111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            copy->release();
2312c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            return UNKNOWN_ERROR;
23138c460498c028888c533ab442be12b6d4b669b965James Dong        }
23148c460498c028888c533ab442be12b6d4b669b965James Dong
231585fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // if the duration is different for this sample, see if it is close enough to the previous
231685fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // duration that we can fudge it and use the same value, to avoid filling the stts table
231785fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // with lots of near-identical entries.
231885fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // "close enough" here means that the current duration needs to be adjusted by less
231985fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // than 0.1 milliseconds
232085fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        if (lastDurationTicks && (currDurationTicks != lastDurationTicks)) {
232185fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen            int64_t deltaUs = ((lastDurationTicks - currDurationTicks) * 1000000LL
232285fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                    + (mTimeScale / 2)) / mTimeScale;
232385fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen            if (deltaUs > -100 && deltaUs < 100) {
232485fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                // use previous ticks, and adjust timestamp as if it was actually that number
232585fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                // of ticks
232685fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                currDurationTicks = lastDurationTicks;
232785fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                timestampUs += deltaUs;
232885fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen            }
232985fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        }
233085fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen
2331c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStszTableEntries->add(htonl(sampleSize));
2332c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        if (mStszTableEntries->count() > 2) {
2333c059860c73678a202bfa33062723e8f82fb779d9James Dong
2334a472613aec322e25891abf5c77bf3f7e3c244920James Dong            // Force the first sample to have its own stts entry so that
2335a472613aec322e25891abf5c77bf3f7e3c244920James Dong            // we can adjust its value later to maintain the A/V sync.
2336c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() == 3 || currDurationTicks != lastDurationTicks) {
233779761ab096f57c3027fad9556c2bc436672d614eJames Dong                addOneSttsTableEntry(sampleCount, lastDurationTicks);
2338be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                sampleCount = 1;
2339be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            } else {
2340be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                ++sampleCount;
2341be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
2342965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2343be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
2344be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        if (mSamplesHaveSameSize) {
2345c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() >= 2 && previousSampleSize != sampleSize) {
2346be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mSamplesHaveSameSize = false;
2347be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
23488644c14618d30d9e57a69df40ed939986ebf02c4James Dong            previousSampleSize = sampleSize;
2349be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
2350a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("%s timestampUs/lastTimestampUs: %" PRId64 "/%" PRId64,
235111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                trackName, timestampUs, lastTimestampUs);
23528644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastDurationUs = timestampUs - lastTimestampUs;
2353c059860c73678a202bfa33062723e8f82fb779d9James Dong        lastDurationTicks = currDurationTicks;
23548644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastTimestampUs = timestampUs;
235520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2356d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        if (isSync != 0) {
2357c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            addOneStssTableEntry(mStszTableEntries->count());
2358d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        }
2359d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
236093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (mTrackingProgressStatus) {
236193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            if (mPreviousTrackTimeUs <= 0) {
236293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong                mPreviousTrackTimeUs = mStartTimestampUs;
236393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            }
2364faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong            trackProgressStatus(timestampUs);
236593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
236643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong        if (!hasMultipleTracks) {
2367c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t offset = mIsAvc? mOwner->addLengthPrefixedSample_l(copy)
236858ae9c530247668f8af36e30d228c716c226b3d4James Dong                                 : mOwner->addSample_l(copy);
2369c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
2370c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t count = (mOwner->use32BitFileOffset()
2371c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        ? mStcoTableEntries->count()
2372c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        : mCo64TableEntries->count());
2373c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
2374c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (count == 0) {
23751f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                addChunkOffset(offset);
237658ae9c530247668f8af36e30d228c716c226b3d4James Dong            }
237758ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy->release();
237858ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy = NULL;
237958ae9c530247668f8af36e30d228c716c226b3d4James Dong            continue;
238058ae9c530247668f8af36e30d228c716c226b3d4James Dong        }
238113aec890216948b0c364f8f92792129d0335f506James Dong
238213aec890216948b0c364f8f92792129d0335f506James Dong        mChunkSamples.push_back(copy);
238313aec890216948b0c364f8f92792129d0335f506James Dong        if (interleaveDurationUs == 0) {
23841f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            addOneStscTableEntry(++nChunks, 1);
23851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            bufferChunk(timestampUs);
238613aec890216948b0c364f8f92792129d0335f506James Dong        } else {
238713aec890216948b0c364f8f92792129d0335f506James Dong            if (chunkTimestampUs == 0) {
238813aec890216948b0c364f8f92792129d0335f506James Dong                chunkTimestampUs = timestampUs;
238913aec890216948b0c364f8f92792129d0335f506James Dong            } else {
239043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                int64_t chunkDurationUs = timestampUs - chunkTimestampUs;
239143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                if (chunkDurationUs > interleaveDurationUs) {
239243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    if (chunkDurationUs > mMaxChunkDurationUs) {
239343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                        mMaxChunkDurationUs = chunkDurationUs;
239443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    }
239513aec890216948b0c364f8f92792129d0335f506James Dong                    ++nChunks;
239613aec890216948b0c364f8f92792129d0335f506James Dong                    if (nChunks == 1 ||  // First chunk
2397c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        lastSamplesPerChunk != mChunkSamples.size()) {
2398c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        lastSamplesPerChunk = mChunkSamples.size();
2399c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        addOneStscTableEntry(nChunks, lastSamplesPerChunk);
240013aec890216948b0c364f8f92792129d0335f506James Dong                    }
24011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                    bufferChunk(timestampUs);
240213aec890216948b0c364f8f92792129d0335f506James Dong                    chunkTimestampUs = timestampUs;
240313aec890216948b0c364f8f92792129d0335f506James Dong                }
240413aec890216948b0c364f8f92792129d0335f506James Dong            }
240513aec890216948b0c364f8f92792129d0335f506James Dong        }
240613aec890216948b0c364f8f92792129d0335f506James Dong
240720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
240825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
240945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    if (isTrackMalFormed()) {
2410690f546b0ee548dbfe997df36418e5302ec2d786James Dong        err = ERROR_MALFORMED;
2411f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong    }
241245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
2413bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    mOwner->trackProgressStatus(mTrackId, -1, err);
2414be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
241513aec890216948b0c364f8f92792129d0335f506James Dong    // Last chunk
241643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    if (!hasMultipleTracks) {
2417c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        addOneStscTableEntry(1, mStszTableEntries->count());
241858ae9c530247668f8af36e30d228c716c226b3d4James Dong    } else if (!mChunkSamples.empty()) {
24191f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        addOneStscTableEntry(++nChunks, mChunkSamples.size());
24201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        bufferChunk(timestampUs);
242113aec890216948b0c364f8f92792129d0335f506James Dong    }
242213aec890216948b0c364f8f92792129d0335f506James Dong
2423be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // We don't really know how long the last frame lasts, since
2424be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // there is no frame time after it, just repeat the previous
2425be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // frame's duration.
2426c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mStszTableEntries->count() == 1) {
24278f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        lastDurationUs = 0;  // A single sample's duration
242879761ab096f57c3027fad9556c2bc436672d614eJames Dong        lastDurationTicks = 0;
2429be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    } else {
2430be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        ++sampleCount;  // Count for the last sample
2431be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    }
2432a472613aec322e25891abf5c77bf3f7e3c244920James Dong
2433c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mStszTableEntries->count() <= 2) {
243479761ab096f57c3027fad9556c2bc436672d614eJames Dong        addOneSttsTableEntry(1, lastDurationTicks);
2435a472613aec322e25891abf5c77bf3f7e3c244920James Dong        if (sampleCount - 1 > 0) {
243679761ab096f57c3027fad9556c2bc436672d614eJames Dong            addOneSttsTableEntry(sampleCount - 1, lastDurationTicks);
2437a472613aec322e25891abf5c77bf3f7e3c244920James Dong        }
2438a472613aec322e25891abf5c77bf3f7e3c244920James Dong    } else {
243979761ab096f57c3027fad9556c2bc436672d614eJames Dong        addOneSttsTableEntry(sampleCount, lastDurationTicks);
2440a472613aec322e25891abf5c77bf3f7e3c244920James Dong    }
2441a472613aec322e25891abf5c77bf3f7e3c244920James Dong
244243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    // The last ctts box may not have been written yet, and this
244343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    // is to make sure that we write out the last ctts box.
244443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    if (currCttsOffsetTimeTicks == lastCttsOffsetTimeTicks) {
244543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        if (cttsSampleCount > 0) {
244643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
244743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        }
244843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    }
244943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong
2450c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs += lastDurationUs;
245125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = true;
245243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
245343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    sendTrackSummary(hasMultipleTracks);
245443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
2455df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s",
245611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            count, nZeroLengthFrames, mStszTableEntries->count(), trackName);
2457872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (mIsAudio) {
2458a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGI("Audio track drift time: %" PRId64 " us", mOwner->getDriftTimeUs());
2459872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
2460365a963142093a1cd8efdcea76b5f65096a5b115James Dong
246137187916a486504acaf83bea30147eb5fbf46ae5James Dong    if (err == ERROR_END_OF_STREAM) {
246237187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
246337187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
246437187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
2465365a963142093a1cd8efdcea76b5f65096a5b115James Dong}
2466365a963142093a1cd8efdcea76b5f65096a5b115James Dong
246745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dongbool MPEG4Writer::Track::isTrackMalFormed() const {
2468c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mStszTableEntries->count() == 0) {                      // no samples written
246929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("The number of recorded samples is 0");
247045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
247145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
247245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
2473c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (!mIsAudio && mStssTableEntries->count() == 0) {  // no sync frames for video
247429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("There are no sync frames for video track");
247545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
247645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
247745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
247845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    if (OK != checkCodecSpecificData()) {         // no codec specific data
247945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
248045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
248145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
248245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    return false;
248345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong}
248445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
248543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dongvoid MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) {
248607ec01904613a0bac32caaa8444b4690998faed7James Dong
248707ec01904613a0bac32caaa8444b4690998faed7James Dong    // Send track summary only if test mode is enabled.
248807ec01904613a0bac32caaa8444b4690998faed7James Dong    if (!isTestModeEnabled()) {
248907ec01904613a0bac32caaa8444b4690998faed7James Dong        return;
249007ec01904613a0bac32caaa8444b4690998faed7James Dong    }
249107ec01904613a0bac32caaa8444b4690998faed7James Dong
249243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    int trackNum = (mTrackId << 28);
249343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
249443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
249543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_TYPE,
249643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mIsAudio? 0: 1);
249743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
249843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
249943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_DURATION_MS,
250043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mTrackDurationUs / 1000);
250143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
250243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
250343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES,
2504c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    mStszTableEntries->count());
250543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
250686b7f47aa7482424cf8fd248f1315311919be3b0James Dong    {
250786b7f47aa7482424cf8fd248f1315311919be3b0James Dong        // The system delay time excluding the requested initial delay that
250886b7f47aa7482424cf8fd248f1315311919be3b0James Dong        // is used to eliminate the recording sound.
250986b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL;
251086b7f47aa7482424cf8fd248f1315311919be3b0James Dong        if (startTimeOffsetUs < 0) {  // Start time offset was not set
251186b7f47aa7482424cf8fd248f1315311919be3b0James Dong            startTimeOffsetUs = kInitialDelayTimeUs;
251286b7f47aa7482424cf8fd248f1315311919be3b0James Dong        }
251386b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t initialDelayUs =
251486b7f47aa7482424cf8fd248f1315311919be3b0James Dong            mFirstSampleTimeRealUs - mStartTimeRealUs - startTimeOffsetUs;
251586b7f47aa7482424cf8fd248f1315311919be3b0James Dong
251686b7f47aa7482424cf8fd248f1315311919be3b0James Dong        mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
251770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS,
251870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    (initialDelayUs) / 1000);
251986b7f47aa7482424cf8fd248f1315311919be3b0James Dong    }
252070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
252107ec01904613a0bac32caaa8444b4690998faed7James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
252207ec01904613a0bac32caaa8444b4690998faed7James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES,
252307ec01904613a0bac32caaa8444b4690998faed7James Dong                    mMdatSizeBytes / 1024);
252407ec01904613a0bac32caaa8444b4690998faed7James Dong
252543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    if (hasMultipleTracks) {
252643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong        mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
252743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS,
252843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mMaxChunkDurationUs / 1000);
252970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
253070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
253170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        if (mStartTimestampUs != moovStartTimeUs) {
253270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            int64_t startTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
253370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
253470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS,
253570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    startTimeOffsetUs / 1000);
253670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        }
253743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    }
253843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong}
253943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
2540faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) {
2541a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("trackProgressStatus: %" PRId64 " us", timeUs);
2542c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
2543215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    if (mTrackEveryTimeDurationUs > 0 &&
2544215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) {
2545a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("Fire time tracking progress status at %" PRId64 " us", timeUs);
2546bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err);
254793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        mPreviousTrackTimeUs = timeUs;
254893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
254993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
255093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
2551faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::trackProgressStatus(
2552bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        size_t trackId, int64_t timeUs, status_t err) {
2553faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    Mutex::Autolock lock(mLock);
2554bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    int32_t trackNum = (trackId << 28);
2555faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
2556faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Error notification
2557faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Do not consider ERROR_END_OF_STREAM an error
2558faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (err != OK && err != ERROR_END_OF_STREAM) {
2559bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_ERROR,
2560bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL,
2561faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
2562faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        return;
2563faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
2564faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
2565faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (timeUs == -1) {
2566faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send completion notification
2567bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
2568bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS,
2569faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
2570faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    } else {
2571faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send progress status
2572bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
2573bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME,
2574faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               timeUs / 1000);
2575faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
2576faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong}
2577faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
2578d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dongvoid MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) {
2579a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("setDriftTimeUs: %" PRId64 " us", driftTimeUs);
2580e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
2581d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong    mDriftTimeUs = driftTimeUs;
2582e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
2583e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
2584e259531ce59ab1f31de5a23124b22536f6a5a767James Dongint64_t MPEG4Writer::getDriftTimeUs() {
2585a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("getDriftTimeUs: %" PRId64 " us", mDriftTimeUs);
2586e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
2587e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    return mDriftTimeUs;
2588e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
2589e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
2590de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghuibool MPEG4Writer::isRealTimeRecording() const {
2591de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    return mIsRealTimeRecording;
2592de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui}
2593de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui
2594b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dongbool MPEG4Writer::useNalLengthFour() {
2595b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    return mUse4ByteNalLength;
2596b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong}
2597b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong
25981c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::Track::bufferChunk(int64_t timestampUs) {
25993856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("bufferChunk");
26001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
26011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Chunk chunk(this, timestampUs, mChunkSamples);
26021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mOwner->bufferChunk(chunk);
260313aec890216948b0c364f8f92792129d0335f506James Dong    mChunkSamples.clear();
260420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
260520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
26063b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const {
2607c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    return mTrackDurationUs;
260820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
260920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2610d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const {
2611d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return mEstimatedTrackSizeBytes;
2612d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
2613d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
2614690f546b0ee548dbfe997df36418e5302ec2d786James Dongstatus_t MPEG4Writer::Track::checkCodecSpecificData() const {
2615690f546b0ee548dbfe997df36418e5302ec2d786James Dong    const char *mime;
2616690f546b0ee548dbfe997df36418e5302ec2d786James Dong    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
2617690f546b0ee548dbfe997df36418e5302ec2d786James Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) ||
2618690f546b0ee548dbfe997df36418e5302ec2d786James Dong        !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) ||
2619690f546b0ee548dbfe997df36418e5302ec2d786James Dong        !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
2620690f546b0ee548dbfe997df36418e5302ec2d786James Dong        if (!mCodecSpecificData ||
2621690f546b0ee548dbfe997df36418e5302ec2d786James Dong            mCodecSpecificDataSize <= 0) {
262229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Missing codec specific data");
2623690f546b0ee548dbfe997df36418e5302ec2d786James Dong            return ERROR_MALFORMED;
2624690f546b0ee548dbfe997df36418e5302ec2d786James Dong        }
2625690f546b0ee548dbfe997df36418e5302ec2d786James Dong    } else {
2626690f546b0ee548dbfe997df36418e5302ec2d786James Dong        if (mCodecSpecificData ||
2627690f546b0ee548dbfe997df36418e5302ec2d786James Dong            mCodecSpecificDataSize > 0) {
262829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Unexepected codec specific data found");
2629690f546b0ee548dbfe997df36418e5302ec2d786James Dong            return ERROR_MALFORMED;
2630690f546b0ee548dbfe997df36418e5302ec2d786James Dong        }
2631690f546b0ee548dbfe997df36418e5302ec2d786James Dong    }
2632690f546b0ee548dbfe997df36418e5302ec2d786James Dong    return OK;
2633690f546b0ee548dbfe997df36418e5302ec2d786James Dong}
2634690f546b0ee548dbfe997df36418e5302ec2d786James Dong
2635b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeTrackHeader(bool use32BitOffset) {
263620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
26373856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("%s track time scale: %d",
26381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsAudio? "Audio": "Video", mTimeScale);
26398f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
2640efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    uint32_t now = getMpeg4Time();
2641b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("trak");
2642b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeTkhdBox(now);
2643b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->beginBox("mdia");
2644b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            writeMdhdBox(now);
2645b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            writeHdlrBox();
2646b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            mOwner->beginBox("minf");
2647b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                if (mIsAudio) {
2648b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                    writeSmhdBox();
2649b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                } else {
2650b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                    writeVmhdBox();
2651b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                }
2652b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                writeDinfBox();
2653b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                writeStblBox(use32BitOffset);
2654b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            mOwner->endBox();  // minf
2655b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->endBox();  // mdia
2656b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // trak
2657b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2658b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2659b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStblBox(bool use32BitOffset) {
2660b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stbl");
2661b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsd");
2662b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);               // version=0, flags=0
2663b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);               // entry count
2664b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mIsAudio) {
2665b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeAudioFourCCBox();
2666b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
2667b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeVideoFourCCBox();
2668b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2669b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsd
2670b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeSttsBox();
2671965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    writeCttsBox();
2672b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!mIsAudio) {
2673b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeStssBox();
2674b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2675b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStszBox();
2676b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStscBox();
2677b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStcoBox(use32BitOffset);
2678b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stbl
2679b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2680b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2681b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVideoFourCCBox() {
2682b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    const char *mime;
2683b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    bool success = mMeta->findCString(kKeyMIMEType, &mime);
2684b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
2685b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
2686b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->beginBox("mp4v");
2687b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
2688b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->beginBox("s263");
2689b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
2690b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->beginBox("avc1");
2691b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
269229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Unknown mime type '%s'.", mime);
2693b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        CHECK(!"should not be here, unknown mime type.");
2694b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2695b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2696b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2697b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2698b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(1);           // data ref index
2699b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // predefined
2700b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2701b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
2702b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
2703b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
2704b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2705b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t width, height;
2706b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = mMeta->findInt32(kKeyWidth, &width);
2707b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = success && mMeta->findInt32(kKeyHeight, &height);
2708b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
2709b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2710b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(width);
2711b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(height);
2712b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x480000);    // horiz resolution
2713b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x480000);    // vert resolution
2714b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2715b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(1);           // frame count
2716c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo    mOwner->writeInt8(0);            // compressor string length
2717c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo    mOwner->write("                               ", 31);
2718b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x18);        // depth
2719b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(-1);          // predefined
2720b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
272143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_LT(23 + mCodecSpecificDataSize, 128);
2722b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2723b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
2724b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeMp4vEsdsBox();
2725b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
2726b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeD263Box();
2727b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
2728b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeAvccBox();
2729b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2730b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2731b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writePaspBox();
2732b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // mp4v, s263 or avc1
2733b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2734b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2735b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAudioFourCCBox() {
2736b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    const char *mime;
2737b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    bool success = mMeta->findCString(kKeyMIMEType, &mime);
2738b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
2739b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    const char *fourcc = NULL;
2740b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) {
2741b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        fourcc = "samr";
2742b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
2743b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        fourcc = "sawb";
2744b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
2745b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        fourcc = "mp4a";
2746b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
274729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Unknown mime type '%s'.", mime);
2748b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        CHECK(!"should not be here, unknown mime type.");
2749b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2750b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2751b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox(fourcc);        // audio format
2752b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2753b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2754b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x1);         // data ref index
2755b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2756b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2757b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t nChannels;
2758b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels));
2759b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(nChannels);   // channel count
2760b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(16);          // sample size
2761b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // predefined
2762b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2763b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2764b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t samplerate;
2765b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = mMeta->findInt32(kKeySampleRate, &samplerate);
2766b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
2767b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(samplerate << 16);
2768b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
2769b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeMp4aEsdsBox();
2770b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) ||
2771b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong               !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
2772b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeDamrBox();
2773b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2774b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2775b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2776b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2777b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4aEsdsBox() {
2778b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("esds");
2779b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
278043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mCodecSpecificDataSize, 0);
2781b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2782b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Make sure all sizes encode to a single byte.
278343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_LT(mCodecSpecificDataSize + 23, 128);
2784b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2785b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);     // version=0, flags=0
2786b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x03);   // ES_DescrTag
2787b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(23 + mCodecSpecificDataSize);
2788b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x0000);// ES_ID
2789b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x00);
2790b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2791b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x04);   // DecoderConfigDescrTag
2792b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(15 + mCodecSpecificDataSize);
2793b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x40);   // objectTypeIndication ISO/IEC 14492-2
2794b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x15);   // streamType AudioStream
2795b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2796b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x03);  // XXX
2797b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x00);   // buffer size 24-bit
2798b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(96000); // max bit rate
2799b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(96000); // avg bit rate
2800b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2801b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x05);   // DecoderSpecificInfoTag
2802b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(mCodecSpecificDataSize);
2803b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
2804b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2805b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData2[] = {
2806b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x06,  // SLConfigDescriptorTag
2807b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x01,
2808b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x02
2809b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
2810b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData2, sizeof(kData2));
2811b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2812b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // esds
2813b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2814b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2815b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4vEsdsBox() {
2816b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
281743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mCodecSpecificDataSize, 0);
2818b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("esds");
2819b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2820b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);    // version=0, flags=0
2821b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2822b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x03);  // ES_DescrTag
2823b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(23 + mCodecSpecificDataSize);
2824b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x0000);  // ES_ID
2825b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x1f);
2826b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2827b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x04);  // DecoderConfigDescrTag
2828b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(15 + mCodecSpecificDataSize);
2829b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x20);  // objectTypeIndication ISO/IEC 14492-2
2830b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x11);  // streamType VisualStream
2831b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2832b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData[] = {
2833b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x01, 0x77, 0x00,
2834b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x00, 0x03, 0xe8, 0x00,
2835b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x00, 0x03, 0xe8, 0x00
2836b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
2837b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData, sizeof(kData));
2838b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2839b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x05);  // DecoderSpecificInfoTag
2840b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2841b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(mCodecSpecificDataSize);
2842b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
2843b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2844b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData2[] = {
2845b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x06,  // SLConfigDescriptorTag
2846b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x01,
2847b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x02
2848b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
2849b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData2, sizeof(kData2));
2850b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2851b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // esds
2852b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2853b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2854efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeTkhdBox(uint32_t now) {
2855b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("tkhd");
2856b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Flags = 7 to indicate that the track is enabled, and
2857b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // part of the presentation
2858b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x07);          // version=0, flags=7
2859b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // creation time
2860b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // modification time
2861219f195159f93d627af2b243732e3f9020511a46James Dong    mOwner->writeInt32(mTrackId);      // track id starts with 1
2862b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
28638f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t trakDurationUs = getDurationUs();
2864b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t mvhdTimeScale = mOwner->getTimeScale();
2865b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t tkhdDuration =
2866b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
2867b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(tkhdDuration);  // in mvhd timescale
2868b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
2869b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
2870b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // layer
2871b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // alternate group
2872b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(mIsAudio ? 0x100 : 0);  // volume
2873b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // reserved
2874b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2875b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCompositionMatrix(mRotation);       // matrix
287620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2877b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mIsAudio) {
2878b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(0);
2879b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(0);
2880b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
2881b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        int32_t width, height;
2882b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        bool success = mMeta->findInt32(kKeyWidth, &width);
2883b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        success = success && mMeta->findInt32(kKeyHeight, &height);
2884b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        CHECK(success);
2885b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2886b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(width << 16);   // 32-bit fixed-point value
2887b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(height << 16);  // 32-bit fixed-point value
2888b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2889b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // tkhd
2890b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2891b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2892b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVmhdBox() {
2893b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("vmhd");
2894b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x01);        // version=0, flags=1
2895b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // graphics mode
2896b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // opcolor
2897b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);
2898b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);
2899b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2900b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2901b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2902b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeSmhdBox() {
2903b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("smhd");
2904b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // version=0, flags=0
2905b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // balance
2906b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2907b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2908b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2909b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2910b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeHdlrBox() {
2911b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("hdlr");
2912b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // version=0, flags=0
2913b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // component type: should be mhlr
2914b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeFourcc(mIsAudio ? "soun" : "vide");  // component subtype
2915b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
2916b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
2917b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
2918b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Removing "r" for the name string just makes the string 4 byte aligned
2919b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle");  // name
2920b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2921b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2922b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2923efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeMdhdBox(uint32_t now) {
2924b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int64_t trakDurationUs = getDurationUs();
2925b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("mdhd");
2926b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // version=0, flags=0
2927b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // creation time
2928b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // modification time
2929b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(mTimeScale);    // media timescale
2930b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6;
2931b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(mdhdDuration);  // use media timescale
2932b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Language follows the three letter standard ISO-639-2/T
2933b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // 'e', 'n', 'g' for "English", for instance.
2934b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Each character is packed as the difference between its ASCII value and 0x60.
2935b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // For "English", these are 00101, 01110, 00111.
2936b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // XXX: Where is the padding bit located: 0x15C7?
2937b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // language code
2938b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // predefined
2939b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2940b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2941b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2942b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDamrBox() {
2943b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // 3gpp2 Spec AMRSampleEntry fields
2944b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("damr");
2945b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCString("   ");  // vendor: 4 bytes
2946b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);         // decoder version
2947b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x83FF);   // mode set: all enabled
2948b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);         // mode change period
2949b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(1);         // frames per sample
2950b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2951b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2952b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2953b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeUrlBox() {
2954b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // The table index here refers to the sample description index
2955b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // in the sample table entries.
2956b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("url ");
2957b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);  // version=0, flags=1 (self-contained)
2958b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // url
2959b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2960b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2961b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDrefBox() {
2962b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("dref");
2963b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
2964b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);  // entry count (either url or urn)
2965b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeUrlBox();
2966b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // dref
2967b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2968b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2969b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDinfBox() {
2970b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("dinf");
2971b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeDrefBox();
2972b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // dinf
2973b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2974b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2975b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAvccBox() {
2976b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
297743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GE(mCodecSpecificDataSize, 5);
2978b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2979b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Patch avcc's lengthSize field to match the number
2980b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // of bytes we use to indicate the size of a nal unit.
2981b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    uint8_t *ptr = (uint8_t *)mCodecSpecificData;
2982b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    ptr[4] = (ptr[4] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1);
2983b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("avcC");
2984b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
2985b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // avcC
2986b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2987b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2988b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeD263Box() {
2989b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("d263");
2990b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // vendor
2991b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);   // decoder version
2992b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(10);  // level: 10
2993b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);   // profile: 0
2994b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // d263
2995b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2996b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2997b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong// This is useful if the pixel is not square
2998b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writePaspBox() {
2999b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("pasp");
3000b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1 << 16);  // hspacing
3001b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1 << 16);  // vspacing
3002b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // pasp
3003b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3004b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3005000e18370baae60ffd9f25b509501dd8c26deabfJames Dongint32_t MPEG4Writer::Track::getStartTimeOffsetScaledTime() const {
3006a472613aec322e25891abf5c77bf3f7e3c244920James Dong    int64_t trackStartTimeOffsetUs = 0;
3007b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
3008b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mStartTimestampUs != moovStartTimeUs) {
300943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_GT(mStartTimestampUs, moovStartTimeUs);
3010b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        trackStartTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
3011b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3012000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    return (trackStartTimeOffsetUs *  mTimeScale + 500000LL) / 1000000LL;
3013000e18370baae60ffd9f25b509501dd8c26deabfJames Dong}
3014000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
3015000e18370baae60ffd9f25b509501dd8c26deabfJames Dongvoid MPEG4Writer::Track::writeSttsBox() {
3016000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->beginBox("stts");
3017000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3018c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t duration;
3019c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    CHECK(mSttsTableEntries->get(duration, 1));
3020c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    duration = htonl(duration);  // Back to host byte order
3021c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime()), 1);
3022c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->write(mOwner);
3023b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stts
3024b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
302520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3026965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::writeCttsBox() {
3027965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    if (mIsAudio) {  // ctts is not for audio
3028965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
3029965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
3030965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
3031000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    // There is no B frame at all
3032000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    if (mMinCttsOffsetTimeUs == mMaxCttsOffsetTimeUs) {
3033000e18370baae60ffd9f25b509501dd8c26deabfJames Dong        return;
3034000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    }
3035000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
3036965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    // Do not write ctts box when there is no need to have it.
3037c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mCttsTableEntries->count() == 0) {
3038965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
3039965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
3040965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
3041a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("ctts box has %d entries with range [%" PRId64 ", %" PRId64 "]",
3042c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mCttsTableEntries->count(), mMinCttsOffsetTimeUs, mMaxCttsOffsetTimeUs);
3043965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
3044965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mOwner->beginBox("ctts");
3045000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3046c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t duration;
3047c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    CHECK(mCttsTableEntries->get(duration, 1));
3048c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    duration = htonl(duration);  // Back host byte order
3049c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime() - mMinCttsOffsetTimeUs), 1);
3050c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->write(mOwner);
3051965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mOwner->endBox();  // ctts
3052965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong}
3053965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
3054b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStssBox() {
3055b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stss");
3056b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3057c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries->write(mOwner);
3058b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stss
3059b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
306025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
3061b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStszBox() {
3062b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsz");
3063b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3064c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mOwner->writeInt32(0);
3065c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStszTableEntries->write(mOwner);
3066b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsz
3067b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
306820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3069b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStscBox() {
3070b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsc");
3071b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3072c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStscTableEntries->write(mOwner);
3073b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsc
3074b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
307520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3076b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) {
3077b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox(use32BitOffset? "stco": "co64");
3078b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3079c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (use32BitOffset) {
3080c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStcoTableEntries->write(mOwner);
3081c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    } else {
3082c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mCo64TableEntries->write(mOwner);
3083b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3084b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stco or co64
308520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
308620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
308707b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeUdtaBox() {
308807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    beginBox("udta");
308907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeGeoDataBox();
309007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    endBox();
309107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
309207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
3093e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeHdlr() {
3094e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("hdlr");
3095e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Version, Flags
3096e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Predefined
3097e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeFourcc("mdta");
3098e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Reserved[0]
3099e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Reserved[1]
3100e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Reserved[2]
3101e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt8(0);  // Name (empty)
3102e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox();
3103e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3104e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3105e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeKeys() {
3106e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    size_t count = mMetaKeys->countEntries();
3107e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3108e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("keys");
3109e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0);     // Version, Flags
3110e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(count); // Entry_count
3111e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    for (size_t i = 0; i < count; i++) {
3112e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        AMessage::Type type;
3113e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        const char *key = mMetaKeys->getEntryNameAt(i, &type);
3114e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        size_t n = strlen(key);
3115e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        writeInt32(n + 8);
3116e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        writeFourcc("mdta");
3117e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        write(key, n); // write without the \0
3118e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
3119e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox();
3120e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3121e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3122e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeIlst() {
3123e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    size_t count = mMetaKeys->countEntries();
3124e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3125e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    // meta data key types
3126e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    static const int32_t kKeyType_BE32Float = 23;
3127e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    static const int32_t kKeyType_BE32SignedInteger = 67;
3128e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    static const int32_t kKeyType_BE32UnsignedInteger = 77;
3129e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3130e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("ilst");
3131e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    for (size_t i = 0; i < count; i++) {
3132e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        beginBox(i + 1); // key id (1-based)
3133e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        beginBox("data");
3134e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        AMessage::Type type;
3135e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        const char *key = mMetaKeys->getEntryNameAt(i, &type);
3136e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        switch (type) {
3137e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            case AMessage::kTypeFloat:
3138e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            {
3139e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                float val;
3140e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                CHECK(mMetaKeys->findFloat(key, &val));
3141e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                writeInt32(kKeyType_BE32Float);
3142e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                writeInt32(*reinterpret_cast<int32_t *>(&val));
3143e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                break;
3144e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            }
3145e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3146e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            case AMessage::kTypeInt32:
3147e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            {
3148e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                int32_t val;
3149e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                CHECK(mMetaKeys->findInt32(key, &val));
3150e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                writeInt32(kKeyType_BE32SignedInteger);
3151e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                writeInt32(val);
3152e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                break;
3153e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            }
3154e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3155e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            default:
3156e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            {
3157e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                ALOGW("Unsupported key type, writing 0 instead");
3158e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                writeInt32(kKeyType_BE32UnsignedInteger);
3159e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                writeInt32(0);
3160e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                break;
3161e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            }
3162e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        }
3163e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        endBox(); // data
3164e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        endBox(); // key id
3165e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
3166e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox(); // ilst
3167e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3168e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3169e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeMetaBox() {
3170e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    size_t count = mMetaKeys->countEntries();
3171e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    if (count == 0) {
3172e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        return;
3173e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
3174e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3175e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("meta");
3176e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeHdlr();
3177e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeKeys();
3178e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeIlst();
3179e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox();
3180e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3181e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3182e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
318307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/*
318407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard.
318507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */
318607b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeGeoDataBox() {
318707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    beginBox("\xA9xyz");
318807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    /*
318907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * For historical reasons, any user data start
319007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * with "\0xA9", must be followed by its assoicated
319107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * language code.
3192432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong     * 0x0012: text string length
3193432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong     * 0x15c7: lang (locale) code: en
319407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     */
319507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeInt32(0x001215c7);
319607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeLatitude(mLatitudex10000);
319707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeLongitude(mLongitudex10000);
319807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeInt8(0x2F);
319907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    endBox();
320007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
320107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
320220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
3203