MPEG4Writer.cpp revision 0ca31521644b9396829850f7400d23f9b107cc64
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
667c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangstatic const char kMetaKey_Version[]    = "com.android.version";
673b0da19c78f6a61ed343a07f2448b94faafe4c02Lajos Molnar#ifdef SHOW_MODEL_BUILD
683b0da19c78f6a61ed343a07f2448b94faafe4c02Lajos Molnarstatic const char kMetaKey_Model[]      = "com.android.model";
697c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangstatic const char kMetaKey_Build[]      = "com.android.build";
703b0da19c78f6a61ed343a07f2448b94faafe4c02Lajos Molnar#endif
717c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangstatic const char kMetaKey_CaptureFps[] = "com.android.capture.fps";
727c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
737c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang/* uncomment to include model and build in meta */
747c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang//#define SHOW_MODEL_BUILD 1
757c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
7620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Writer::Track {
7720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic:
78bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    Track(MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId);
798f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
8020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    ~Track();
8120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t start(MetaData *params);
8337187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t stop();
8437187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t pause();
8525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool reachedEOS();
8620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
873b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber    int64_t getDurationUs() const;
88d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t getEstimatedTrackSizeBytes() const;
89b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeTrackHeader(bool use32BitOffset = true);
901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void bufferChunk(int64_t timestampUs);
911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isAvc() const { return mIsAvc; }
921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isAudio() const { return mIsAudio; }
931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isMPEG4() const { return mIsMPEG4; }
94c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    void addChunkOffset(off64_t offset);
9570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int32_t getTrackId() const { return mTrackId; }
96dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    status_t dump(int fd, const Vector<String16>& args) const;
978b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    static const char *getFourCCForMime(const char *mime);
9820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate:
100000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    enum {
101000e18370baae60ffd9f25b509501dd8c26deabfJames Dong        kMaxCttsOffsetTimeUs = 1000000LL,  // 1 second
1028c460498c028888c533ab442be12b6d4b669b965James Dong        kSampleArraySize = 1000,
103000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    };
104000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
105c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    // A helper class to handle faster write box with table entries
106c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    template<class TYPE>
107c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    struct ListTableEntries {
108c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        ListTableEntries(uint32_t elementCapacity, uint32_t entryCapacity)
109c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            : mElementCapacity(elementCapacity),
110c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mEntryCapacity(entryCapacity),
111c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mTotalNumTableEntries(0),
112c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mNumValuesInCurrEntry(0),
113c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mCurrTableEntriesElement(NULL) {
114c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_GT(mElementCapacity, 0);
115c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_GT(mEntryCapacity, 0);
1162177f21c1ae5bf5cb8c1113a1adbe1fd7db34206Wei Jia            // Ensure no integer overflow on allocation in add().
1172177f21c1ae5bf5cb8c1113a1adbe1fd7db34206Wei Jia            CHECK_LT(mEntryCapacity, UINT32_MAX / mElementCapacity);
118c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
119c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
120c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Free the allocated memory.
121c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        ~ListTableEntries() {
122c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            while (!mTableEntryList.empty()) {
123c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                typename List<TYPE *>::iterator it = mTableEntryList.begin();
124c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                delete[] (*it);
125c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mTableEntryList.erase(it);
126c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
127c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
128c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
129c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Replace the value at the given position by the given value.
130c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // There must be an existing value at the given position.
131c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg value must be in network byte order
132c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg pos location the value must be in.
133c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        void set(const TYPE& value, uint32_t pos) {
13425f0d7ba1987de61c75f8c68b19de48e0ad9736cJames Dong            CHECK_LT(pos, mTotalNumTableEntries * mEntryCapacity);
135c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
136c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            typename List<TYPE *>::iterator it = mTableEntryList.begin();
137c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t iterations = (pos / (mElementCapacity * mEntryCapacity));
138c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            while (it != mTableEntryList.end() && iterations > 0) {
139c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                ++it;
140c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                --iterations;
141c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
142c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK(it != mTableEntryList.end());
143c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_EQ(iterations, 0);
144c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
145c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            (*it)[(pos % (mElementCapacity * mEntryCapacity))] = value;
146c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
147c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
148c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Get the value at the given position by the given value.
149c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg value the retrieved value at the position in network byte order.
150c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg pos location the value must be in.
151c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @return true if a value is found.
152c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        bool get(TYPE& value, uint32_t pos) const {
15325f0d7ba1987de61c75f8c68b19de48e0ad9736cJames Dong            if (pos >= mTotalNumTableEntries * mEntryCapacity) {
154c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                return false;
155c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
156c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
157c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            typename List<TYPE *>::iterator it = mTableEntryList.begin();
158c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t iterations = (pos / (mElementCapacity * mEntryCapacity));
159c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            while (it != mTableEntryList.end() && iterations > 0) {
160c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                ++it;
161c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                --iterations;
162c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
163c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK(it != mTableEntryList.end());
164c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_EQ(iterations, 0);
165c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
166c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            value = (*it)[(pos % (mElementCapacity * mEntryCapacity))];
167c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            return true;
168c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
169c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
170c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Store a single value.
171c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg value must be in network byte order.
172c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        void add(const TYPE& value) {
173c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_LT(mNumValuesInCurrEntry, mElementCapacity);
174c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t nEntries = mTotalNumTableEntries % mElementCapacity;
175c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t nValues  = mNumValuesInCurrEntry % mEntryCapacity;
176c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (nEntries == 0 && nValues == 0) {
177c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mCurrTableEntriesElement = new TYPE[mEntryCapacity * mElementCapacity];
178c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                CHECK(mCurrTableEntriesElement != NULL);
179c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mTableEntryList.push_back(mCurrTableEntriesElement);
180c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
181c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
182c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t pos = nEntries * mEntryCapacity + nValues;
183c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mCurrTableEntriesElement[pos] = value;
184c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
185c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            ++mNumValuesInCurrEntry;
186c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if ((mNumValuesInCurrEntry % mEntryCapacity) == 0) {
187c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                ++mTotalNumTableEntries;
188c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mNumValuesInCurrEntry = 0;
189c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
190c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
191c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
192c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Write out the table entries:
193c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // 1. the number of entries goes first
194c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // 2. followed by the values in the table enties in order
195c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg writer the writer to actual write to the storage
196c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        void write(MPEG4Writer *writer) const {
197c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_EQ(mNumValuesInCurrEntry % mEntryCapacity, 0);
198c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t nEntries = mTotalNumTableEntries;
199c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            writer->writeInt32(nEntries);
200c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            for (typename List<TYPE *>::iterator it = mTableEntryList.begin();
201c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                it != mTableEntryList.end(); ++it) {
202c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                CHECK_GT(nEntries, 0);
203c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                if (nEntries >= mElementCapacity) {
204c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    writer->write(*it, sizeof(TYPE) * mEntryCapacity, mElementCapacity);
205c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    nEntries -= mElementCapacity;
206c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                } else {
207c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    writer->write(*it, sizeof(TYPE) * mEntryCapacity, nEntries);
208c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    break;
209c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                }
210c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
211c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
212c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
213c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Return the number of entries in the table.
214c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t count() const { return mTotalNumTableEntries; }
215c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
216c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    private:
217c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t         mElementCapacity;  // # entries in an element
218c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t         mEntryCapacity;    // # of values in each entry
219c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t         mTotalNumTableEntries;
220c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t         mNumValuesInCurrEntry;  // up to mEntryCapacity
221c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        TYPE             *mCurrTableEntriesElement;
222c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mutable List<TYPE *>     mTableEntryList;
223c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
224c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        DISALLOW_EVIL_CONSTRUCTORS(ListTableEntries);
225c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    };
226c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
227c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
228c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
22920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Writer *mOwner;
23020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MetaData> mMeta;
231693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    sp<MediaSource> mSource;
23220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    volatile bool mDone;
233a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mPaused;
234a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mResumed;
235eaae38445a340c4857c1c5569475879a728e63b7James Dong    volatile bool mStarted;
2361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAvc;
2371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAudio;
2381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsMPEG4;
239bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    int32_t mTrackId;
240c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    int64_t mTrackDurationUs;
24143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    int64_t mMaxChunkDurationUs;
242e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
243d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t mEstimatedTrackSizeBytes;
2441f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    int64_t mMdatSizeBytes;
2458f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int32_t mTimeScale;
24620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
24720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_t mThread;
24820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
249be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
25013aec890216948b0c364f8f92792129d0335f506James Dong    List<MediaBuffer *> mChunkSamples;
2511f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
252c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    bool                mSamplesHaveSameSize;
253c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mStszTableEntries;
254be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
255c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mStcoTableEntries;
256c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<off64_t> *mCo64TableEntries;
257c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mStscTableEntries;
258c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mStssTableEntries;
259c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mSttsTableEntries;
260c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mCttsTableEntries;
261965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
262000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t mMinCttsOffsetTimeUs;
263000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t mMaxCttsOffsetTimeUs;
264965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Sequence parameter set or picture parameter set
2663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    struct AVCParamSet {
2673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        AVCParamSet(uint16_t length, const uint8_t *data)
2683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            : mLength(length), mData(data) {}
2693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
2703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t mLength;
2713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *mData;
2723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    };
2733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    List<AVCParamSet> mSeqParamSets;
2743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    List<AVCParamSet> mPicParamSets;
2753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mProfileIdc;
2763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mProfileCompatible;
2773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mLevelIdc;
2783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
27920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *mCodecSpecificData;
28020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t mCodecSpecificDataSize;
281548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    bool mGotAllCodecSpecificData;
28293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    bool mTrackingProgressStatus;
28320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
28425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool mReachedEOS;
2853c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    int64_t mStartTimestampUs;
28670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int64_t mStartTimeRealUs;
28770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int64_t mFirstSampleTimeRealUs;
28893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mPreviousTrackTimeUs;
28993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mTrackEveryTimeDurationUs;
29025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
291872a481558350634a3fd5cb67939de288af00ecbJames Dong    // Update the audio track's drift information.
292872a481558350634a3fd5cb67939de288af00ecbJames Dong    void updateDriftTime(const sp<MetaData>& meta);
293872a481558350634a3fd5cb67939de288af00ecbJames Dong
294000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int32_t getStartTimeOffsetScaledTime() const;
295000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
29620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    static void *ThreadWrapper(void *me);
29737187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t threadEntry();
29820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *parseParamSet(
3003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen);
3013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
302b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t makeAVCCodecSpecificData(const uint8_t *data, size_t size);
303b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t copyAVCCodecSpecificData(const uint8_t *data, size_t size);
304b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t parseAVCCodecSpecificData(const uint8_t *data, size_t size);
305215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong
306215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    // Track authoring progress status
307faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    void trackProgressStatus(int64_t timeUs, status_t err = OK);
30893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    void initTrackingProgressStatus(MetaData *params);
30903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
31019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    void getCodecSpecificDataFromInputFormatIfPossible();
31119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
312c059860c73678a202bfa33062723e8f82fb779d9James Dong    // Determine the track time scale
313c059860c73678a202bfa33062723e8f82fb779d9James Dong    // If it is an audio track, try to use the sampling rate as
314c059860c73678a202bfa33062723e8f82fb779d9James Dong    // the time scale; however, if user chooses the overwrite
315c059860c73678a202bfa33062723e8f82fb779d9James Dong    // value, the user-supplied time scale will be used.
316c059860c73678a202bfa33062723e8f82fb779d9James Dong    void setTimeScale();
317c059860c73678a202bfa33062723e8f82fb779d9James Dong
318690f546b0ee548dbfe997df36418e5302ec2d786James Dong    // Simple validation on the codec specific data
319690f546b0ee548dbfe997df36418e5302ec2d786James Dong    status_t checkCodecSpecificData() const;
32013f6284305e4b27395a23db7882d670bdb1bcae1James Dong    int32_t mRotation;
321690f546b0ee548dbfe997df36418e5302ec2d786James Dong
3221f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void updateTrackSizeEstimate();
3231f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void addOneStscTableEntry(size_t chunkId, size_t sampleId);
3241f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void addOneStssTableEntry(size_t sampleId);
32579761ab096f57c3027fad9556c2bc436672d614eJames Dong
32679761ab096f57c3027fad9556c2bc436672d614eJames Dong    // Duration is time scale based
32779761ab096f57c3027fad9556c2bc436672d614eJames Dong    void addOneSttsTableEntry(size_t sampleCount, int32_t timescaledDur);
328965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    void addOneCttsTableEntry(size_t sampleCount, int32_t timescaledDur);
32945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
33045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    bool isTrackMalFormed() const;
33143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    void sendTrackSummary(bool hasMultipleTracks);
3321f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
333b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Write the boxes
334b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStcoBox(bool use32BitOffset);
335b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStscBox();
336b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStszBox();
337b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStssBox();
338b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeSttsBox();
339965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    void writeCttsBox();
340b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeD263Box();
341b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writePaspBox();
342b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeAvccBox();
343b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeUrlBox();
344b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDrefBox();
345b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDinfBox();
346b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDamrBox();
347efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    void writeMdhdBox(uint32_t now);
348b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeSmhdBox();
349b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeVmhdBox();
350b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeHdlrBox();
351efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    void writeTkhdBox(uint32_t now);
352b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeMp4aEsdsBox();
353b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeMp4vEsdsBox();
354b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeAudioFourCCBox();
355b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeVideoFourCCBox();
356b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStblBox(bool use32BitOffset);
357b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
35820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track(const Track &);
35920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track &operator=(const Track &);
36020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
36120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
36230ab66297501757d745b9ae10da61adcd891f497Andreas HuberMPEG4Writer::MPEG4Writer(int fd)
363674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    : mFd(dup(fd)),
364674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong      mInitCheck(mFd < 0? NO_INIT: OK),
365de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui      mIsRealTimeRecording(true),
366b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong      mUse4ByteNalLength(true),
3671acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong      mUse32BitOffset(true),
368a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong      mIsFileSizeLimitExplicitlyRequested(false),
369a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
370a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mStarted(false),
371411ba422e3635d534928ffd81abf54f4f291c739James Dong      mWriterThreadStarted(false),
37230ab66297501757d745b9ae10da61adcd891f497Andreas Huber      mOffset(0),
37313aec890216948b0c364f8f92792129d0335f506James Dong      mMdatOffset(0),
374e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mMoovBoxBuffer(NULL),
375e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mMoovBoxBufferOffset(0),
376e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mWriteMoovBoxToMemory(false),
377e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mFreeBoxOffset(0),
378e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mStreamableFile(false),
3797837c17063a4c50bc856ba59418516fdab731de7James Dong      mEstimatedMoovBoxSize(0),
3807c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang      mMoovExtraSize(0),
38107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mInterleaveDurationUs(1000000),
382e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mTimeScale(-1),
383e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mStartTimestampUs(-1ll),
38407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mLatitudex10000(0),
38507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mLongitudex10000(0),
38686b7f47aa7482424cf8fd248f1315311919be3b0James Dong      mAreGeoTagsAvailable(false),
387ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar      mStartTimeOffsetMs(-1),
388ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar      mMetaKeys(new AMessage()) {
3897c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    addDeviceMeta();
3902aa74dc097fe860abc84769abf2b6e0962718471Robert Shih
3912aa74dc097fe860abc84769abf2b6e0962718471Robert Shih    // Verify mFd is seekable
3922aa74dc097fe860abc84769abf2b6e0962718471Robert Shih    off64_t off = lseek64(mFd, 0, SEEK_SET);
3932aa74dc097fe860abc84769abf2b6e0962718471Robert Shih    if (off < 0) {
3942aa74dc097fe860abc84769abf2b6e0962718471Robert Shih        ALOGE("cannot seek mFd: %s (%d)", strerror(errno), errno);
3952aa74dc097fe860abc84769abf2b6e0962718471Robert Shih        release();
3962aa74dc097fe860abc84769abf2b6e0962718471Robert Shih    }
39730ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
39830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
39920111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() {
4008bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dong    reset();
40120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4021f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    while (!mTracks.empty()) {
4031f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        List<Track *>::iterator it = mTracks.begin();
40420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        delete *it;
4051f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        (*it) = NULL;
4061f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mTracks.erase(it);
40720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
40820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.clear();
40920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
41020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
411dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::dump(
412dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        int fd, const Vector<String16>& args) {
413dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    const size_t SIZE = 256;
414dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    char buffer[SIZE];
415dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    String8 result;
416dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "   MPEG4Writer %p\n", this);
417dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
418dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "     mStarted: %s\n", mStarted? "true": "false");
419dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
420dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    ::write(fd, result.string(), result.size());
421dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    for (List<Track *>::iterator it = mTracks.begin();
422dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong         it != mTracks.end(); ++it) {
423dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        (*it)->dump(fd, args);
424dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    }
425dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    return OK;
426dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong}
427dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong
428dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::Track::dump(
42984333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        int fd, const Vector<String16>& /* args */) const {
430dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    const size_t SIZE = 256;
431dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    char buffer[SIZE];
432dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    String8 result;
433dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "     %s track\n", mIsAudio? "Audio": "Video");
434dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
435dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "       reached EOS: %s\n",
436dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong            mReachedEOS? "true": "false");
437dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
438c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    snprintf(buffer, SIZE, "       frames encoded : %d\n", mStszTableEntries->count());
43913210f3346462a86ce9fe3af72a0c200dba84e27James Dong    result.append(buffer);
440377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    snprintf(buffer, SIZE, "       duration encoded : %" PRId64 " us\n", mTrackDurationUs);
44113210f3346462a86ce9fe3af72a0c200dba84e27James Dong    result.append(buffer);
442dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    ::write(fd, result.string(), result.size());
443dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    return OK;
444dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong}
445dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong
4468b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan// static
4478b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavanconst char *MPEG4Writer::Track::getFourCCForMime(const char *mime) {
4488b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (mime == NULL) {
4498b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        return NULL;
4508b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    }
4518b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (!strncasecmp(mime, "audio/", 6)) {
4528b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) {
4538b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "samr";
4548b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
4558b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "sawb";
4568b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
4578b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "mp4a";
4588b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        }
4598b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    } else if (!strncasecmp(mime, "video/", 6)) {
4608b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
4618b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "mp4v";
4628b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
4638b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "s263";
4648b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
4658b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "avc1";
4668b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        }
4678b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    } else {
4688b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        ALOGE("Track (%s) other than video or audio is not supported", mime);
4698b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    }
4708b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    return NULL;
4718b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan}
4728b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan
4732dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huberstatus_t MPEG4Writer::addSource(const sp<MediaSource> &source) {
474bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    Mutex::Autolock l(mLock);
475bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    if (mStarted) {
47629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Attempt to add source AFTER recording is started");
477bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        return UNKNOWN_ERROR;
478bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    }
479acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
480acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // At most 2 tracks can be supported.
481acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    if (mTracks.size() >= 2) {
482a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGE("Too many tracks (%zu) to add", mTracks.size());
483acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        return ERROR_UNSUPPORTED;
484acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    }
485acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
486acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    CHECK(source.get() != NULL);
487acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
488acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    const char *mime;
489acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    source->getFormat()->findCString(kKeyMIMEType, &mime);
490acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    bool isAudio = !strncasecmp(mime, "audio/", 6);
4918b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (Track::getFourCCForMime(mime) == NULL) {
4928b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        ALOGE("Unsupported mime '%s'", mime);
493acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        return ERROR_UNSUPPORTED;
494acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    }
495acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
496acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // At this point, we know the track to be added is either
497acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // video or audio. Thus, we only need to check whether it
498acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // is an audio track or not (if it is not, then it must be
499acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // a video track).
500acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
501acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // No more than one video or one audio track is supported.
502acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    for (List<Track*>::iterator it = mTracks.begin();
503acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong         it != mTracks.end(); ++it) {
504acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        if ((*it)->isAudio() == isAudio) {
505acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong            ALOGE("%s track already exists", isAudio? "Audio": "Video");
506acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong            return ERROR_UNSUPPORTED;
507acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        }
508acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    }
509acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
510acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // This is the first track of either audio or video.
511acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // Go ahead to add the track.
512219f195159f93d627af2b243732e3f9020511a46James Dong    Track *track = new Track(this, source, 1 + mTracks.size());
51320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.push_back(track);
5142dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
5152dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    return OK;
51620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
51720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
51893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::startTracks(MetaData *params) {
519acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    if (mTracks.empty()) {
520acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        ALOGE("No source added");
521acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        return INVALID_OPERATION;
522acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    }
523acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
524a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
525a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
52693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        status_t err = (*it)->start(params);
527a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
528a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (err != OK) {
529a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            for (List<Track *>::iterator it2 = mTracks.begin();
530a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                 it2 != it; ++it2) {
531a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                (*it2)->stop();
532a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            }
533a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
534a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            return err;
535a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
536a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
537a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    return OK;
538a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
539a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
5407c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangvoid MPEG4Writer::addDeviceMeta() {
5417c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // add device info and estimate space in 'moov'
5427c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    char val[PROPERTY_VALUE_MAX];
5437c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    size_t n;
5447c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // meta size is estimated by adding up the following:
5457c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // - meta header structures, which occur only once (total 66 bytes)
5467c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // - size for each key, which consists of a fixed header (32 bytes),
5477c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    //   plus key length and data length.
5487c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMoovExtraSize += 66;
5497c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    if (property_get("ro.build.version.release", val, NULL)
5507c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            && (n = strlen(val)) > 0) {
5517c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMetaKeys->setString(kMetaKey_Version, val, n + 1);
5527c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMoovExtraSize += sizeof(kMetaKey_Version) + n + 32;
5537c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    }
5547c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang#ifdef SHOW_MODEL_BUILD
5557c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    if (property_get("ro.product.model", val, NULL)
5567c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            && (n = strlen(val)) > 0) {
5577c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMetaKeys->setString(kMetaKey_Model, val, n + 1);
5587c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMoovExtraSize += sizeof(kMetaKey_Model) + n + 32;
5597c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    }
5607c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    if (property_get("ro.build.display.id", val, NULL)
5617c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            && (n = strlen(val)) > 0) {
5627c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMetaKeys->setString(kMetaKey_Build, val, n + 1);
5637c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMoovExtraSize += sizeof(kMetaKey_Build) + n + 32;
5647c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    }
5657c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang#endif
5667c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang}
5677c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
5682dec2b5be2056c6d9428897dc672185872d30d17James Dongint64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) {
5692dec2b5be2056c6d9428897dc672185872d30d17James Dong    // This implementation is highly experimental/heurisitic.
5702dec2b5be2056c6d9428897dc672185872d30d17James Dong    //
5712dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Statistical analysis shows that metadata usually accounts
5722dec2b5be2056c6d9428897dc672185872d30d17James Dong    // for a small portion of the total file size, usually < 0.6%.
5732dec2b5be2056c6d9428897dc672185872d30d17James Dong
57478a1a286f736888ae7af8860b2c424af0d978848James Dong    // The default MIN_MOOV_BOX_SIZE is set to 0.6% x 1MB / 2,
5752dec2b5be2056c6d9428897dc672185872d30d17James Dong    // where 1MB is the common file size limit for MMS application.
57678a1a286f736888ae7af8860b2c424af0d978848James Dong    // The default MAX _MOOV_BOX_SIZE value is based on about 3
5772dec2b5be2056c6d9428897dc672185872d30d17James Dong    // minute video recording with a bit rate about 3 Mbps, because
5782dec2b5be2056c6d9428897dc672185872d30d17James Dong    // statistics also show that most of the video captured are going
5792dec2b5be2056c6d9428897dc672185872d30d17James Dong    // to be less than 3 minutes.
5802dec2b5be2056c6d9428897dc672185872d30d17James Dong
5812dec2b5be2056c6d9428897dc672185872d30d17James Dong    // If the estimation is wrong, we will pay the price of wasting
5822dec2b5be2056c6d9428897dc672185872d30d17James Dong    // some reserved space. This should not happen so often statistically.
5832dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int32_t factor = mUse32BitOffset? 1: 2;
58478a1a286f736888ae7af8860b2c424af0d978848James Dong    static const int64_t MIN_MOOV_BOX_SIZE = 3 * 1024;  // 3 KB
5852dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000);
5862dec2b5be2056c6d9428897dc672185872d30d17James Dong    int64_t size = MIN_MOOV_BOX_SIZE;
5872dec2b5be2056c6d9428897dc672185872d30d17James Dong
58878a1a286f736888ae7af8860b2c424af0d978848James Dong    // Max file size limit is set
589a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
59078a1a286f736888ae7af8860b2c424af0d978848James Dong        size = mMaxFileSizeLimitBytes * 6 / 1000;
59178a1a286f736888ae7af8860b2c424af0d978848James Dong    }
59278a1a286f736888ae7af8860b2c424af0d978848James Dong
59378a1a286f736888ae7af8860b2c424af0d978848James Dong    // Max file duration limit is set
59478a1a286f736888ae7af8860b2c424af0d978848James Dong    if (mMaxFileDurationLimitUs != 0) {
59578a1a286f736888ae7af8860b2c424af0d978848James Dong        if (bitRate > 0) {
59678a1a286f736888ae7af8860b2c424af0d978848James Dong            int64_t size2 =
5970ca31521644b9396829850f7400d23f9b107cc64Johan Redestig                ((mMaxFileDurationLimitUs / 1000) * bitRate * 6) / 8000000;
59878a1a286f736888ae7af8860b2c424af0d978848James Dong            if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
59978a1a286f736888ae7af8860b2c424af0d978848James Dong                // When both file size and duration limits are set,
60078a1a286f736888ae7af8860b2c424af0d978848James Dong                // we use the smaller limit of the two.
60178a1a286f736888ae7af8860b2c424af0d978848James Dong                if (size > size2) {
60278a1a286f736888ae7af8860b2c424af0d978848James Dong                    size = size2;
60378a1a286f736888ae7af8860b2c424af0d978848James Dong                }
60478a1a286f736888ae7af8860b2c424af0d978848James Dong            } else {
60578a1a286f736888ae7af8860b2c424af0d978848James Dong                // Only max file duration limit is set
60678a1a286f736888ae7af8860b2c424af0d978848James Dong                size = size2;
60778a1a286f736888ae7af8860b2c424af0d978848James Dong            }
6082dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
6092dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
61078a1a286f736888ae7af8860b2c424af0d978848James Dong
6112dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size < MIN_MOOV_BOX_SIZE) {
6122dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MIN_MOOV_BOX_SIZE;
6132dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
6142dec2b5be2056c6d9428897dc672185872d30d17James Dong
6152dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Any long duration recording will be probably end up with
6162dec2b5be2056c6d9428897dc672185872d30d17James Dong    // non-streamable mp4 file.
6172dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size > MAX_MOOV_BOX_SIZE) {
6182dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MAX_MOOV_BOX_SIZE;
6192dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
6202dec2b5be2056c6d9428897dc672185872d30d17James Dong
6217c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // Account for the extra stuff (Geo, meta keys, etc.)
6227c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    size += mMoovExtraSize;
6237c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
624a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGI("limits: %" PRId64 "/%" PRId64 " bytes/us, bit rate: %d bps and the"
625a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn         " estimated moov size %" PRId64 " bytes",
6262dec2b5be2056c6d9428897dc672185872d30d17James Dong         mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size);
6272dec2b5be2056c6d9428897dc672185872d30d17James Dong    return factor * size;
6282dec2b5be2056c6d9428897dc672185872d30d17James Dong}
6292dec2b5be2056c6d9428897dc672185872d30d17James Dong
6302dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t MPEG4Writer::start(MetaData *param) {
631674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
63225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return UNKNOWN_ERROR;
63320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
63420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
635a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    /*
636a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * Check mMaxFileSizeLimitBytes at the beginning
637a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * since mMaxFileSizeLimitBytes may be implicitly
638a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * changed later for 32-bit file offset even if
639a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * user does not ask to set it explicitly.
640a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     */
641a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    if (mMaxFileSizeLimitBytes != 0) {
642a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong        mIsFileSizeLimitExplicitlyRequested = true;
643a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    }
644a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong
6452dec2b5be2056c6d9428897dc672185872d30d17James Dong    int32_t use64BitOffset;
6462dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (param &&
6472dec2b5be2056c6d9428897dc672185872d30d17James Dong        param->findInt32(kKey64BitFileOffset, &use64BitOffset) &&
6482dec2b5be2056c6d9428897dc672185872d30d17James Dong        use64BitOffset) {
6492dec2b5be2056c6d9428897dc672185872d30d17James Dong        mUse32BitOffset = false;
6502dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
6512dec2b5be2056c6d9428897dc672185872d30d17James Dong
6521f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    if (mUse32BitOffset) {
6531f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // Implicit 32 bit file size limit
6541f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        if (mMaxFileSizeLimitBytes == 0) {
6551f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            mMaxFileSizeLimitBytes = kMax32BitFileSize;
6561f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        }
6571f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
6581f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // If file size is set to be larger than the 32 bit file
6591f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // size limit, treat it as an error.
6601f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        if (mMaxFileSizeLimitBytes > kMax32BitFileSize) {
661a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGW("32-bit file size limit (%" PRId64 " bytes) too big. "
662a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn                 "It is changed to %" PRId64 " bytes",
663d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong                mMaxFileSizeLimitBytes, kMax32BitFileSize);
664d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong            mMaxFileSizeLimitBytes = kMax32BitFileSize;
6651f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        }
6661f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    }
6671f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
668b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    int32_t use2ByteNalLength;
669b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (param &&
670b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        param->findInt32(kKey2ByteNalLength, &use2ByteNalLength) &&
671b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        use2ByteNalLength) {
672b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mUse4ByteNalLength = false;
6732dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
6742dec2b5be2056c6d9428897dc672185872d30d17James Dong
675de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    int32_t isRealTimeRecording;
676de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    if (param && param->findInt32(kKeyRealTimeRecording, &isRealTimeRecording)) {
677de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        mIsRealTimeRecording = isRealTimeRecording;
678de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    }
679de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui
680065d1aff96818df54456053f1574aec8a234d0deJames Dong    mStartTimestampUs = -1;
68193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
682a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (mStarted) {
683a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused) {
684a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mPaused = false;
68593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            return startTracks(param);
686a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
687a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
688a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
689a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
6908f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    if (!param ||
6918f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        !param->findInt32(kKeyTimeScale, &mTimeScale)) {
6928f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        mTimeScale = 1000;
6938f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    }
69443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mTimeScale, 0);
6953856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("movie time scale: %d", mTimeScale);
6968f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
69777e8ae9967a078770416619e99ddb5b010def312James Dong    /*
69877e8ae9967a078770416619e99ddb5b010def312James Dong     * When the requested file size limit is small, the priority
69977e8ae9967a078770416619e99ddb5b010def312James Dong     * is to meet the file size limit requirement, rather than
7007b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * to make the file streamable. mStreamableFile does not tell
7017b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * whether the actual recorded file is streamable or not.
70277e8ae9967a078770416619e99ddb5b010def312James Dong     */
70377e8ae9967a078770416619e99ddb5b010def312James Dong    mStreamableFile =
70477e8ae9967a078770416619e99ddb5b010def312James Dong        (mMaxFileSizeLimitBytes != 0 &&
70577e8ae9967a078770416619e99ddb5b010def312James Dong         mMaxFileSizeLimitBytes >= kMinStreamableFileSizeInBytes);
70677e8ae9967a078770416619e99ddb5b010def312James Dong
7077b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    /*
7087b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * mWriteMoovBoxToMemory is true if the amount of data in moov box is
7097b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * smaller than the reserved free space at the beginning of a file, AND
7107b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * when the content of moov box is constructed. Note that video/audio
7117b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * frame data is always written to the file but not in the memory.
7127b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
7137b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * Before stop()/reset() is called, mWriteMoovBoxToMemory is always
7147b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * false. When reset() is called at the end of a recording session,
7157b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * Moov box needs to be constructed.
7167b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
7177b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * 1) Right before a moov box is constructed, mWriteMoovBoxToMemory
7187b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * to set to mStreamableFile so that if
7197b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * the file is intended to be streamable, it is set to true;
7207b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * otherwise, it is set to false. When the value is set to false,
7217b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * all the content of the moov box is written immediately to
7227b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * the end of the file. When the value is set to true, all the
7237b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * content of the moov box is written to an in-memory cache,
7247b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * mMoovBoxBuffer, util the following condition happens. Note
7257b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * that the size of the in-memory cache is the same as the
7267b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * reserved free space at the beginning of the file.
7277b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
7287b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * 2) While the data of the moov box is written to an in-memory
7297b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * cache, the data size is checked against the reserved space.
7307b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * If the data size surpasses the reserved space, subsequent moov
7317b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * data could no longer be hold in the in-memory cache. This also
7327b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * indicates that the reserved space was too small. At this point,
7337b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * _all_ moov data must be written to the end of the file.
7347b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * mWriteMoovBoxToMemory must be set to false to direct the write
7357b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * to the file.
7367b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
7377b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * 3) If the data size in moov box is smaller than the reserved
7387b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * space after moov box is completely constructed, the in-memory
7397b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * cache copy of the moov box is written to the reserved free
7407b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * space. Thus, immediately after the moov is completedly
7417b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * constructed, mWriteMoovBoxToMemory is always set to false.
7427b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     */
7437b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    mWriteMoovBoxToMemory = false;
7447837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBuffer = NULL;
7457837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
7467837c17063a4c50bc856ba59418516fdab731de7James Dong
747b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeFtypBox(param);
74820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7497837c17063a4c50bc856ba59418516fdab731de7James Dong    mFreeBoxOffset = mOffset;
75020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7517837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mEstimatedMoovBoxSize == 0) {
7522dec2b5be2056c6d9428897dc672185872d30d17James Dong        int32_t bitRate = -1;
7532dec2b5be2056c6d9428897dc672185872d30d17James Dong        if (param) {
7542dec2b5be2056c6d9428897dc672185872d30d17James Dong            param->findInt32(kKeyBitRate, &bitRate);
7552dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
7562dec2b5be2056c6d9428897dc672185872d30d17James Dong        mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate);
7577837c17063a4c50bc856ba59418516fdab731de7James Dong    }
75843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GE(mEstimatedMoovBoxSize, 8);
75977e8ae9967a078770416619e99ddb5b010def312James Dong    if (mStreamableFile) {
76077e8ae9967a078770416619e99ddb5b010def312James Dong        // Reserve a 'free' box only for streamable file
76177e8ae9967a078770416619e99ddb5b010def312James Dong        lseek64(mFd, mFreeBoxOffset, SEEK_SET);
76277e8ae9967a078770416619e99ddb5b010def312James Dong        writeInt32(mEstimatedMoovBoxSize);
76377e8ae9967a078770416619e99ddb5b010def312James Dong        write("free", 4);
76477e8ae9967a078770416619e99ddb5b010def312James Dong        mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize;
76577e8ae9967a078770416619e99ddb5b010def312James Dong    } else {
76677e8ae9967a078770416619e99ddb5b010def312James Dong        mMdatOffset = mOffset;
76777e8ae9967a078770416619e99ddb5b010def312James Dong    }
7687837c17063a4c50bc856ba59418516fdab731de7James Dong
7697837c17063a4c50bc856ba59418516fdab731de7James Dong    mOffset = mMdatOffset;
770c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    lseek64(mFd, mMdatOffset, SEEK_SET);
7711acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
7721acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("????mdat", 8);
7731acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
7741acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("\x00\x00\x00\x01mdat????????", 16);
7751acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
7761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
7771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    status_t err = startWriterThread();
7781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (err != OK) {
7791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        return err;
7801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
7811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
7821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    err = startTracks(param);
783a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (err != OK) {
784a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return err;
78520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
7861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
787a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mStarted = true;
78825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
78920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
79020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7911f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongbool MPEG4Writer::use32BitFileOffset() const {
7921f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    return mUse32BitOffset;
7931f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
7941f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
79537187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::pause() {
796674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
79737187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
798a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
799a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
80037187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = OK;
801a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
802a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
80337187916a486504acaf83bea30147eb5fbf46ae5James Dong        status_t status = (*it)->pause();
80437187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (status != OK) {
80537187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
80637187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
807a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
80837187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
809a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
810a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
8111c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::stopWriterThread() {
812b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("Stopping writer thread");
813411ba422e3635d534928ffd81abf54f4f291c739James Dong    if (!mWriterThreadStarted) {
814411ba422e3635d534928ffd81abf54f4f291c739James Dong        return;
815411ba422e3635d534928ffd81abf54f4f291c739James Dong    }
8161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    {
8181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        Mutex::Autolock autolock(mLock);
8191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mDone = true;
8211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkReadyCondition.signal();
8221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
8231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void *dummy;
8251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_join(mThread, &dummy);
826411ba422e3635d534928ffd81abf54f4f291c739James Dong    mWriterThreadStarted = false;
827b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("Writer thread stopped");
8281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
8291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
83013f6284305e4b27395a23db7882d670bdb1bcae1James Dong/*
83113f6284305e4b27395a23db7882d670bdb1bcae1James Dong * MP4 file standard defines a composition matrix:
83213f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | a  b  u |
83313f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | c  d  v |
83413f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | x  y  w |
83513f6284305e4b27395a23db7882d670bdb1bcae1James Dong *
83613f6284305e4b27395a23db7882d670bdb1bcae1James Dong * the element in the matrix is stored in the following
83713f6284305e4b27395a23db7882d670bdb1bcae1James Dong * order: {a, b, u, c, d, v, x, y, w},
83813f6284305e4b27395a23db7882d670bdb1bcae1James Dong * where a, b, c, d, x, and y is in 16.16 format, while
83913f6284305e4b27395a23db7882d670bdb1bcae1James Dong * u, v and w is in 2.30 format.
84013f6284305e4b27395a23db7882d670bdb1bcae1James Dong */
84113f6284305e4b27395a23db7882d670bdb1bcae1James Dongvoid MPEG4Writer::writeCompositionMatrix(int degrees) {
8423856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("writeCompositionMatrix");
84313f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t a = 0x00010000;
84413f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t b = 0;
84513f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t c = 0;
84613f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t d = 0x00010000;
84713f6284305e4b27395a23db7882d670bdb1bcae1James Dong    switch (degrees) {
84813f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 0:
84913f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
85013f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 90:
85113f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0;
85213f6284305e4b27395a23db7882d670bdb1bcae1James Dong            b = 0x00010000;
85313f6284305e4b27395a23db7882d670bdb1bcae1James Dong            c = 0xFFFF0000;
85413f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0;
85513f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
85613f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 180:
85713f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0xFFFF0000;
85813f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0xFFFF0000;
85913f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
86013f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 270:
86113f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0;
86213f6284305e4b27395a23db7882d670bdb1bcae1James Dong            b = 0xFFFF0000;
86313f6284305e4b27395a23db7882d670bdb1bcae1James Dong            c = 0x00010000;
86413f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0;
86513f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
86613f6284305e4b27395a23db7882d670bdb1bcae1James Dong        default:
86713f6284305e4b27395a23db7882d670bdb1bcae1James Dong            CHECK(!"Should never reach this unknown rotation");
86813f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
86913f6284305e4b27395a23db7882d670bdb1bcae1James Dong    }
87013f6284305e4b27395a23db7882d670bdb1bcae1James Dong
87113f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(a);           // a
87213f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(b);           // b
87313f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // u
87413f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(c);           // c
87513f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(d);           // d
87613f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // v
87713f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // x
87813f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // y
87913f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0x40000000);  // w
88013f6284305e4b27395a23db7882d670bdb1bcae1James Dong}
88113f6284305e4b27395a23db7882d670bdb1bcae1James Dong
882411ba422e3635d534928ffd81abf54f4f291c739James Dongvoid MPEG4Writer::release() {
883411ba422e3635d534928ffd81abf54f4f291c739James Dong    close(mFd);
884411ba422e3635d534928ffd81abf54f4f291c739James Dong    mFd = -1;
885411ba422e3635d534928ffd81abf54f4f291c739James Dong    mInitCheck = NO_INIT;
886411ba422e3635d534928ffd81abf54f4f291c739James Dong    mStarted = false;
8874c845fde3d60ad93984879f69b164e35536e080dSuresh Choudhary    free(mMoovBoxBuffer);
8884c845fde3d60ad93984879f69b164e35536e080dSuresh Choudhary    mMoovBoxBuffer = NULL;
889411ba422e3635d534928ffd81abf54f4f291c739James Dong}
89013f6284305e4b27395a23db7882d670bdb1bcae1James Dong
8918bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dongstatus_t MPEG4Writer::reset() {
892674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
89337187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
894411ba422e3635d534928ffd81abf54f4f291c739James Dong    } else {
895411ba422e3635d534928ffd81abf54f4f291c739James Dong        if (!mWriterThreadStarted ||
896411ba422e3635d534928ffd81abf54f4f291c739James Dong            !mStarted) {
897411ba422e3635d534928ffd81abf54f4f291c739James Dong            if (mWriterThreadStarted) {
898411ba422e3635d534928ffd81abf54f4f291c739James Dong                stopWriterThread();
899411ba422e3635d534928ffd81abf54f4f291c739James Dong            }
900411ba422e3635d534928ffd81abf54f4f291c739James Dong            release();
901411ba422e3635d534928ffd81abf54f4f291c739James Dong            return OK;
902411ba422e3635d534928ffd81abf54f4f291c739James Dong        }
90320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
90420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
90537187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = OK;
9068f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t maxDurationUs = 0;
90765b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    int64_t minDurationUs = 0x7fffffffffffffffLL;
90820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
90920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber         it != mTracks.end(); ++it) {
91037187916a486504acaf83bea30147eb5fbf46ae5James Dong        status_t status = (*it)->stop();
91137187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (err == OK && status != OK) {
91237187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
91337187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
91420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9158f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int64_t durationUs = (*it)->getDurationUs();
9168f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        if (durationUs > maxDurationUs) {
9178f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            maxDurationUs = durationUs;
91820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
91965b3d76025c71d755b0fb3b6ead90255f25417edJames Dong        if (durationUs < minDurationUs) {
92065b3d76025c71d755b0fb3b6ead90255f25417edJames Dong            minDurationUs = durationUs;
92165b3d76025c71d755b0fb3b6ead90255f25417edJames Dong        }
92265b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    }
92365b3d76025c71d755b0fb3b6ead90255f25417edJames Dong
92465b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    if (mTracks.size() > 1) {
925a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGD("Duration from tracks range is [%" PRId64 ", %" PRId64 "] us",
92665b3d76025c71d755b0fb3b6ead90255f25417edJames Dong            minDurationUs, maxDurationUs);
92720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
92820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    stopWriterThread();
9307837c17063a4c50bc856ba59418516fdab731de7James Dong
93137187916a486504acaf83bea30147eb5fbf46ae5James Dong    // Do not write out movie header on error.
93237187916a486504acaf83bea30147eb5fbf46ae5James Dong    if (err != OK) {
933411ba422e3635d534928ffd81abf54f4f291c739James Dong        release();
93437187916a486504acaf83bea30147eb5fbf46ae5James Dong        return err;
93537187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
93637187916a486504acaf83bea30147eb5fbf46ae5James Dong
93720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // Fix up the size of the 'mdat' chunk.
9381acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
939c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mMdatOffset, SEEK_SET);
9401f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad        uint32_t size = htonl(static_cast<uint32_t>(mOffset - mMdatOffset));
941c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &size, 4);
9421acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
943c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mMdatOffset + 8, SEEK_SET);
9441f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad        uint64_t size = mOffset - mMdatOffset;
9451acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        size = hton64(size);
946c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &size, 8);
9471acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
948c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    lseek64(mFd, mOffset, SEEK_SET);
94920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9507b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // Construct moov box now
9517837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
9527b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    mWriteMoovBoxToMemory = mStreamableFile;
9537b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    if (mWriteMoovBoxToMemory) {
9547b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // There is no need to allocate in-memory cache
9557b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // for moov box if the file is not streamable.
9567b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
9577b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize);
9587b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        CHECK(mMoovBoxBuffer != NULL);
9597b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    }
960b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeMoovBox(maxDurationUs);
96120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9627b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // mWriteMoovBoxToMemory could be set to false in
9637b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // MPEG4Writer::write() method
9647b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    if (mWriteMoovBoxToMemory) {
9657b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        mWriteMoovBoxToMemory = false;
9667b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // Content of the moov box is saved in the cache, and the in-memory
9677b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // moov box needs to be written to the file in a single shot.
9687b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
96943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_LE(mMoovBoxBufferOffset + 8, mEstimatedMoovBoxSize);
9707837c17063a4c50bc856ba59418516fdab731de7James Dong
9717837c17063a4c50bc856ba59418516fdab731de7James Dong        // Moov box
972c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mFreeBoxOffset, SEEK_SET);
9737837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset = mFreeBoxOffset;
974674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset);
9757837c17063a4c50bc856ba59418516fdab731de7James Dong
9767837c17063a4c50bc856ba59418516fdab731de7James Dong        // Free box
977c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mOffset, SEEK_SET);
9787837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset);
9797837c17063a4c50bc856ba59418516fdab731de7James Dong        write("free", 4);
9807b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    } else {
9817b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        ALOGI("The mp4 file will not be streamable.");
9827b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    }
9837837c17063a4c50bc856ba59418516fdab731de7James Dong
9847b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // Free in-memory cache for moov box
9857b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    if (mMoovBoxBuffer != NULL) {
9867837c17063a4c50bc856ba59418516fdab731de7James Dong        free(mMoovBoxBuffer);
9877837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBuffer = NULL;
9887837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBufferOffset = 0;
9897837c17063a4c50bc856ba59418516fdab731de7James Dong    }
9907837c17063a4c50bc856ba59418516fdab731de7James Dong
9910c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(mBoxes.empty());
99220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
993411ba422e3635d534928ffd81abf54f4f291c739James Dong    release();
99437187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
99520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
99620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
997efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonuint32_t MPEG4Writer::getMpeg4Time() {
998b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    time_t now = time(NULL);
999efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    // MP4 file uses time counting seconds since midnight, Jan. 1, 1904
1000efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    // while time function returns Unix epoch values which starts
1001efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    // at 1970-01-01. Lets add the number of seconds between them
1002ecf509a9211ca168ffa98c5992f3a4f5f32106cfMarco Nelissen    static const uint32_t delta = (66 * 365 + 17) * (24 * 60 * 60);
1003ecf509a9211ca168ffa98c5992f3a4f5f32106cfMarco Nelissen    if (now < 0 || uint32_t(now) > UINT32_MAX - delta) {
1004ecf509a9211ca168ffa98c5992f3a4f5f32106cfMarco Nelissen        return 0;
1005ecf509a9211ca168ffa98c5992f3a4f5f32106cfMarco Nelissen    }
1006ecf509a9211ca168ffa98c5992f3a4f5f32106cfMarco Nelissen    uint32_t mpeg4Time = uint32_t(now) + delta;
1007efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    return mpeg4Time;
1008efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson}
1009efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson
1010efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::writeMvhdBox(int64_t durationUs) {
1011efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    uint32_t now = getMpeg4Time();
1012b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("mvhd");
1013b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // version=0, flags=0
1014b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(now);           // creation time
1015b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(now);           // modification time
1016b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(mTimeScale);    // mvhd timescale
1017b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t duration = (durationUs * mTimeScale + 5E5) / 1E6;
1018b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(duration);
1019b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0x10000);       // rate: 1.0
1020b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt16(0x100);         // volume
1021b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt16(0);             // reserved
1022b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // reserved
1023b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // reserved
1024b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeCompositionMatrix(0); // matrix
1025b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1026b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1027b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1028b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1029b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1030b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1031b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(mTracks.size() + 1);  // nextTrackID
1032b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();  // mvhd
1033b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
1034b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
1035b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::writeMoovBox(int64_t durationUs) {
1036b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("moov");
1037b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeMvhdBox(durationUs);
103807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (mAreGeoTagsAvailable) {
103907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        writeUdtaBox();
104007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
1041e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeMetaBox();
1042b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t id = 1;
1043b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    for (List<Track *>::iterator it = mTracks.begin();
1044b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        it != mTracks.end(); ++it, ++id) {
1045b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        (*it)->writeTrackHeader(mUse32BitOffset);
1046b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
1047b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();  // moov
1048b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
1049b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
10502cf9c5073ca3342ee52673ad68763fadd2c2be79James Dongvoid MPEG4Writer::writeFtypBox(MetaData *param) {
1051b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("ftyp");
1052b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
1053b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t fileType;
1054b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (param && param->findInt32(kKeyFileType, &fileType) &&
1055b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        fileType != OUTPUT_FORMAT_MPEG_4) {
1056b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeFourcc("3gp4");
10578284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeInt32(0);
10588284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("isom");
10598284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("3gp4");
1060b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
10618284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("mp42");
10628284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeInt32(0);
1063b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeFourcc("isom");
10648284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("mp42");
1065b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
1066b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
1067b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();
1068b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
1069b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
107007ec01904613a0bac32caaa8444b4690998faed7James Dongstatic bool isTestModeEnabled() {
107107ec01904613a0bac32caaa8444b4690998faed7James Dong#if (PROPERTY_VALUE_MAX < 5)
107207ec01904613a0bac32caaa8444b4690998faed7James Dong#error "PROPERTY_VALUE_MAX must be at least 5"
107307ec01904613a0bac32caaa8444b4690998faed7James Dong#endif
107407ec01904613a0bac32caaa8444b4690998faed7James Dong
107507ec01904613a0bac32caaa8444b4690998faed7James Dong    // Test mode is enabled only if rw.media.record.test system
107607ec01904613a0bac32caaa8444b4690998faed7James Dong    // property is enabled.
107707ec01904613a0bac32caaa8444b4690998faed7James Dong    char value[PROPERTY_VALUE_MAX];
107807ec01904613a0bac32caaa8444b4690998faed7James Dong    if (property_get("rw.media.record.test", value, NULL) &&
107907ec01904613a0bac32caaa8444b4690998faed7James Dong        (!strcasecmp(value, "true") || !strcasecmp(value, "1"))) {
108007ec01904613a0bac32caaa8444b4690998faed7James Dong        return true;
108107ec01904613a0bac32caaa8444b4690998faed7James Dong    }
108207ec01904613a0bac32caaa8444b4690998faed7James Dong    return false;
108307ec01904613a0bac32caaa8444b4690998faed7James Dong}
108407ec01904613a0bac32caaa8444b4690998faed7James Dong
108570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongvoid MPEG4Writer::sendSessionSummary() {
108607ec01904613a0bac32caaa8444b4690998faed7James Dong    // Send session summary only if test mode is enabled
108707ec01904613a0bac32caaa8444b4690998faed7James Dong    if (!isTestModeEnabled()) {
108807ec01904613a0bac32caaa8444b4690998faed7James Dong        return;
108907ec01904613a0bac32caaa8444b4690998faed7James Dong    }
109007ec01904613a0bac32caaa8444b4690998faed7James Dong
109170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
109270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong         it != mChunkInfos.end(); ++it) {
109370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        int trackNum = it->mTrack->getTrackId() << 28;
109470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
109570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                trackNum | MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS,
109670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                it->mMaxInterChunkDurUs);
109770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    }
109870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong}
109970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
110013aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) {
110113aec890216948b0c364f8f92792129d0335f506James Dong    mInterleaveDurationUs = durationUs;
110213aec890216948b0c364f8f92792129d0335f506James Dong    return OK;
110313aec890216948b0c364f8f92792129d0335f506James Dong}
110413aec890216948b0c364f8f92792129d0335f506James Dong
110513aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() {
110613aec890216948b0c364f8f92792129d0335f506James Dong    mLock.lock();
110713aec890216948b0c364f8f92792129d0335f506James Dong}
110813aec890216948b0c364f8f92792129d0335f506James Dong
110913aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() {
111013aec890216948b0c364f8f92792129d0335f506James Dong    mLock.unlock();
111113aec890216948b0c364f8f92792129d0335f506James Dong}
111220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1113c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addSample_l(MediaBuffer *buffer) {
1114c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t old_offset = mOffset;
111520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1116c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    ::write(mFd,
1117c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong          (const uint8_t *)buffer->data() + buffer->range_offset(),
1118c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong          buffer->range_length());
111920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
112020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += buffer->range_length();
112120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
112220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return old_offset;
112320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
112420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
112503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) {
112603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (buffer->range_length() < 4) {
112703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return;
112803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
112903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
113003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    const uint8_t *ptr =
113103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        (const uint8_t *)buffer->data() + buffer->range_offset();
113203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
113303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) {
113403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        buffer->set_range(
113503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                buffer->range_offset() + 4, buffer->range_length() - 4);
113603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
113703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
113803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
1139c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) {
1140c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t old_offset = mOffset;
114130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
114230ab66297501757d745b9ae10da61adcd891f497Andreas Huber    size_t length = buffer->range_length();
114303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
1144b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (mUse4ByteNalLength) {
1145b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        uint8_t x = length >> 24;
1146c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1147b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = (length >> 16) & 0xff;
1148c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1149b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = (length >> 8) & 0xff;
1150c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1151b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = length & 0xff;
1152c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1153c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong
1154c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd,
1155c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong              (const uint8_t *)buffer->data() + buffer->range_offset(),
1156c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong              length);
1157b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong
1158b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mOffset += length + 4;
1159b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    } else {
116043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_LT(length, 65536);
116130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
1162b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        uint8_t x = length >> 8;
1163c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1164b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = length & 0xff;
1165c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1166c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, (const uint8_t *)buffer->data() + buffer->range_offset(), length);
1167b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mOffset += length + 2;
1168b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    }
116930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
117030ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return old_offset;
117130ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
117230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
11737837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write(
1174674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        const void *ptr, size_t size, size_t nmemb) {
11757837c17063a4c50bc856ba59418516fdab731de7James Dong
11767837c17063a4c50bc856ba59418516fdab731de7James Dong    const size_t bytes = size * nmemb;
11777837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
11787b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
1179c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes;
11801acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        if (moovBoxSize > mEstimatedMoovBoxSize) {
11817b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // The reserved moov box at the beginning of the file
11827b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // is not big enough. Moov box should be written to
11837b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // the end of the file from now on, but not to the
11847b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // in-memory cache.
11857b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
11867b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // We write partial moov box that is in the memory to
11877b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // the file first.
1188c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            for (List<off64_t>::iterator it = mBoxes.begin();
11897837c17063a4c50bc856ba59418516fdab731de7James Dong                 it != mBoxes.end(); ++it) {
11907837c17063a4c50bc856ba59418516fdab731de7James Dong                (*it) += mOffset;
11917837c17063a4c50bc856ba59418516fdab731de7James Dong            }
1192674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong            lseek64(mFd, mOffset, SEEK_SET);
1193674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong            ::write(mFd, mMoovBoxBuffer, mMoovBoxBufferOffset);
11947b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            ::write(mFd, ptr, bytes);
11957837c17063a4c50bc856ba59418516fdab731de7James Dong            mOffset += (bytes + mMoovBoxBufferOffset);
11967b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
11977b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // All subsequent moov box content will be written
11987b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // to the end of the file.
11997837c17063a4c50bc856ba59418516fdab731de7James Dong            mWriteMoovBoxToMemory = false;
12007837c17063a4c50bc856ba59418516fdab731de7James Dong        } else {
12017837c17063a4c50bc856ba59418516fdab731de7James Dong            memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes);
12027837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset += bytes;
12037837c17063a4c50bc856ba59418516fdab731de7James Dong        }
12047837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
1205674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        ::write(mFd, ptr, size * nmemb);
12067837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset += bytes;
12077837c17063a4c50bc856ba59418516fdab731de7James Dong    }
12087837c17063a4c50bc856ba59418516fdab731de7James Dong    return bytes;
12097837c17063a4c50bc856ba59418516fdab731de7James Dong}
12107837c17063a4c50bc856ba59418516fdab731de7James Dong
1211e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::beginBox(uint32_t id) {
1212e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    mBoxes.push_back(mWriteMoovBoxToMemory?
1213e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            mMoovBoxBufferOffset: mOffset);
1214e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
1215e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0);
1216e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(id);
1217e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
1218e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
121920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) {
12200c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(fourcc), 4);
122120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12227837c17063a4c50bc856ba59418516fdab731de7James Dong    mBoxes.push_back(mWriteMoovBoxToMemory?
12237837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset: mOffset);
122420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
122520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeInt32(0);
122620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeFourcc(fourcc);
122720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
122820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
122920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() {
12300c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(!mBoxes.empty());
123120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1232c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t offset = *--mBoxes.end();
123320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mBoxes.erase(--mBoxes.end());
123420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12357837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
12367837c17063a4c50bc856ba59418516fdab731de7James Dong       int32_t x = htonl(mMoovBoxBufferOffset - offset);
12377837c17063a4c50bc856ba59418516fdab731de7James Dong       memcpy(mMoovBoxBuffer + offset, &x, 4);
12387837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
1239c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, offset, SEEK_SET);
12407837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mOffset - offset);
12417837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset -= 4;
1242c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mOffset, SEEK_SET);
12437837c17063a4c50bc856ba59418516fdab731de7James Dong    }
124420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
124520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
124620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) {
1247674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 1);
124820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
124920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
125020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) {
125120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htons(x);
1252674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 2);
125320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
125420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
125520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) {
125620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htonl(x);
1257674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 4);
125820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
125920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
126020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) {
126120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = hton64(x);
1262674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 8);
126320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
126420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
126520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) {
126620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t n = strlen(s);
1267674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(s, 1, n + 1);
126820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
126920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
127020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) {
12710c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(s), 4);
1272674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(s, 1, 4);
127320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
127420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
127507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
127607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/-DD.DDDD format
127707b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLatitude(int degreex10000) {
127807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    bool isNegative = (degreex10000 < 0);
127907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char sign = isNegative? '-': '+';
128007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
128107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the whole part
128207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char str[9];
128307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int wholePart = degreex10000 / 10000;
128407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (wholePart == 0) {
128507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 5, "%c%.2d.", sign, wholePart);
128607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    } else {
128707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 5, "%+.2d.", wholePart);
128807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
128907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
129007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the fractional part
129107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int fractionalPart = degreex10000 - (wholePart * 10000);
129207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (fractionalPart < 0) {
129307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        fractionalPart = -fractionalPart;
129407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
129507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    snprintf(&str[4], 5, "%.4d", fractionalPart);
129607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
129707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Do not write the null terminator
129807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    write(str, 1, 8);
129907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
130007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
130107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/- DDD.DDDD format
130207b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLongitude(int degreex10000) {
130307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    bool isNegative = (degreex10000 < 0);
130407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char sign = isNegative? '-': '+';
130507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
130607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the whole part
130707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char str[10];
130807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int wholePart = degreex10000 / 10000;
130907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (wholePart == 0) {
131007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 6, "%c%.3d.", sign, wholePart);
131107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    } else {
131207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 6, "%+.3d.", wholePart);
131307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
131407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
131507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the fractional part
131607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int fractionalPart = degreex10000 - (wholePart * 10000);
131707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (fractionalPart < 0) {
131807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        fractionalPart = -fractionalPart;
131907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
132007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    snprintf(&str[5], 5, "%.4d", fractionalPart);
132107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
132207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Do not write the null terminator
132307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    write(str, 1, 9);
132407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
132507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
132607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/*
132707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard.
132807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * latitudex10000 is latitude in degrees times 10000, and
132907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * longitudex10000 is longitude in degrees times 10000.
133007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the latitude is in [-90, +90], and
133107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the longitude is in [-180, +180]
133207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */
133307b1bb529a1ae76c46a71b01338c166f9490629dJames Dongstatus_t MPEG4Writer::setGeoData(int latitudex10000, int longitudex10000) {
133407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Is latitude or longitude out of range?
133507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (latitudex10000 < -900000 || latitudex10000 > 900000 ||
133607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        longitudex10000 < -1800000 || longitudex10000 > 1800000) {
133707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        return BAD_VALUE;
133807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
133907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
134007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mLatitudex10000 = latitudex10000;
134107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mLongitudex10000 = longitudex10000;
134207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mAreGeoTagsAvailable = true;
13437c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMoovExtraSize += 30;
134407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    return OK;
134507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
134607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
1347e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangstatus_t MPEG4Writer::setCaptureRate(float captureFps) {
1348e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    if (captureFps <= 0.0f) {
1349e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        return BAD_VALUE;
1350e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
1351e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
13527c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMetaKeys->setFloat(kMetaKey_CaptureFps, captureFps);
13537c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMoovExtraSize += sizeof(kMetaKey_CaptureFps) + 4 + 32;
13547c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
1355e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    return OK;
1356e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
1357e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
135820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) {
1359674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(data, 1, size);
136020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
136120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
136278a1a286f736888ae7af8860b2c424af0d978848James Dongbool MPEG4Writer::isFileStreamable() const {
136378a1a286f736888ae7af8860b2c424af0d978848James Dong    return mStreamableFile;
136478a1a286f736888ae7af8860b2c424af0d978848James Dong}
136578a1a286f736888ae7af8860b2c424af0d978848James Dong
1366d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() {
1367d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
1368d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileSizeLimitBytes == 0) {
1369d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
1370d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1371d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1372956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize);
1373d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
1374d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
1375d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes();
1376d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
13771f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
137877e8ae9967a078770416619e99ddb5b010def312James Dong    if (!mStreamableFile) {
137977e8ae9967a078770416619e99ddb5b010def312James Dong        // Add 1024 bytes as error tolerance
138077e8ae9967a078770416619e99ddb5b010def312James Dong        return nTotalBytesEstimate + 1024 >= mMaxFileSizeLimitBytes;
138177e8ae9967a078770416619e99ddb5b010def312James Dong    }
1382acd234bba9f048971d66890009eeff9a8db94be3James Dong    // Be conservative in the estimate: do not exceed 95% of
1383acd234bba9f048971d66890009eeff9a8db94be3James Dong    // the target file limit. For small target file size limit, though,
1384acd234bba9f048971d66890009eeff9a8db94be3James Dong    // this will not help.
1385acd234bba9f048971d66890009eeff9a8db94be3James Dong    return (nTotalBytesEstimate >= (95 * mMaxFileSizeLimitBytes) / 100);
1386d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
1387d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1388d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() {
1389d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
1390d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileDurationLimitUs == 0) {
1391d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
1392d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1393d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1394d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
1395d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
1396d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) {
1397d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            return true;
1398d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
1399d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1400d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return false;
1401d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
1402d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
140325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() {
140425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool allDone = true;
140525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
140625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber         it != mTracks.end(); ++it) {
140725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        if (!(*it)->reachedEOS()) {
140825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            allDone = false;
140925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            break;
141025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        }
141125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
141225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
141325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return allDone;
141425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
141525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
1416f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) {
1417a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGI("setStartTimestampUs: %" PRId64, timeUs);
141843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GE(timeUs, 0ll);
14193c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
1420065d1aff96818df54456053f1574aec8a234d0deJames Dong    if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) {
1421f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mStartTimestampUs = timeUs;
1422a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGI("Earliest track starting time: %" PRId64, mStartTimestampUs);
14233c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    }
14243c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
14253c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
1426f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() {
14273c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
14283c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    return mStartTimestampUs;
14293c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
14303c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
143158ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() {
143258ae9c530247668f8af36e30d228c716c226b3d4James Dong    Mutex::Autolock autolock(mLock);
143358ae9c530247668f8af36e30d228c716c226b3d4James Dong    return mTracks.size();
143458ae9c530247668f8af36e30d228c716c226b3d4James Dong}
143558ae9c530247668f8af36e30d228c716c226b3d4James Dong
143620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
143720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
143820111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track(
1439bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId)
144020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mOwner(owner),
144125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mMeta(source->getFormat()),
144220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSource(source),
144320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDone(false),
1444a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
1445a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mResumed(false),
1446eaae38445a340c4857c1c5569475879a728e63b7James Dong      mStarted(false),
1447bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong      mTrackId(trackId),
1448c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong      mTrackDurationUs(0),
1449956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      mEstimatedTrackSizeBytes(0),
1450be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong      mSamplesHaveSameSize(true),
1451c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mStszTableEntries(new ListTableEntries<uint32_t>(1000, 1)),
1452c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mStcoTableEntries(new ListTableEntries<uint32_t>(1000, 1)),
1453c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mCo64TableEntries(new ListTableEntries<off64_t>(1000, 1)),
1454c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mStscTableEntries(new ListTableEntries<uint32_t>(1000, 3)),
1455c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mStssTableEntries(new ListTableEntries<uint32_t>(1000, 1)),
1456c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mSttsTableEntries(new ListTableEntries<uint32_t>(1000, 2)),
1457c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mCttsTableEntries(new ListTableEntries<uint32_t>(1000, 2)),
145820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCodecSpecificData(NULL),
145925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mCodecSpecificDataSize(0),
1460548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber      mGotAllCodecSpecificData(false),
146113f6284305e4b27395a23db7882d670bdb1bcae1James Dong      mReachedEOS(false),
146213f6284305e4b27395a23db7882d670bdb1bcae1James Dong      mRotation(0) {
146319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    getCodecSpecificDataFromInputFormatIfPossible();
14648f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
14651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    const char *mime;
14661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mMeta->findCString(kKeyMIMEType, &mime);
14671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
14681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAudio = !strncasecmp(mime, "audio/", 6);
14691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
14701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong               !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC);
14711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1472c059860c73678a202bfa33062723e8f82fb779d9James Dong    setTimeScale();
1473c059860c73678a202bfa33062723e8f82fb779d9James Dong}
1474c059860c73678a202bfa33062723e8f82fb779d9James Dong
14751f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::updateTrackSizeEstimate() {
14761f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1477c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t stcoBoxCount = (mOwner->use32BitFileOffset()
1478c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                            ? mStcoTableEntries->count()
1479c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                            : mCo64TableEntries->count());
1480c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    int64_t stcoBoxSizeBytes = stcoBoxCount * 4;
1481c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mStszTableEntries->count() * 4);
14821f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
148378a1a286f736888ae7af8860b2c424af0d978848James Dong    mEstimatedTrackSizeBytes = mMdatSizeBytes;  // media data size
148478a1a286f736888ae7af8860b2c424af0d978848James Dong    if (!mOwner->isFileStreamable()) {
148578a1a286f736888ae7af8860b2c424af0d978848James Dong        // Reserved free space is not large enough to hold
148678a1a286f736888ae7af8860b2c424af0d978848James Dong        // all meta data and thus wasted.
1487c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mEstimatedTrackSizeBytes += mStscTableEntries->count() * 12 +  // stsc box size
1488c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mStssTableEntries->count() * 4 +   // stss box size
1489c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mSttsTableEntries->count() * 8 +   // stts box size
1490c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mCttsTableEntries->count() * 8 +   // ctts box size
149178a1a286f736888ae7af8860b2c424af0d978848James Dong                                    stcoBoxSizeBytes +           // stco box size
149278a1a286f736888ae7af8860b2c424af0d978848James Dong                                    stszBoxSizeBytes;            // stsz box size
149378a1a286f736888ae7af8860b2c424af0d978848James Dong    }
14941f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
14951f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
14961f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStscTableEntry(
14971f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        size_t chunkId, size_t sampleId) {
14981f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1499c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStscTableEntries->add(htonl(chunkId));
1500c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStscTableEntries->add(htonl(sampleId));
1501c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStscTableEntries->add(htonl(1));
15021f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
15031f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
15041f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) {
1505c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries->add(htonl(sampleId));
15061f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
15071f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
15081f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneSttsTableEntry(
150979761ab096f57c3027fad9556c2bc436672d614eJames Dong        size_t sampleCount, int32_t duration) {
15101f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
15115a217fba010e801c255503602bda4b86ac5a6ac9James Dong    if (duration == 0) {
1512377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        ALOGW("0-duration samples found: %zu", sampleCount);
15135a217fba010e801c255503602bda4b86ac5a6ac9James Dong    }
1514c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->add(htonl(sampleCount));
1515c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->add(htonl(duration));
15161f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
15171f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1518965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::addOneCttsTableEntry(
1519965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        size_t sampleCount, int32_t duration) {
1520965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
1521965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    if (mIsAudio) {
1522965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
1523965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
1524c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->add(htonl(sampleCount));
1525c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->add(htonl(duration));
1526965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong}
1527965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
1528c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongvoid MPEG4Writer::Track::addChunkOffset(off64_t offset) {
1529c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mOwner->use32BitFileOffset()) {
1530c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t value = offset;
1531c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStcoTableEntries->add(htonl(value));
1532c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    } else {
1533c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mCo64TableEntries->add(hton64(offset));
1534c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    }
15351f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
15361f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1537c059860c73678a202bfa33062723e8f82fb779d9James Dongvoid MPEG4Writer::Track::setTimeScale() {
15383856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setTimeScale");
1539c059860c73678a202bfa33062723e8f82fb779d9James Dong    // Default time scale
1540c059860c73678a202bfa33062723e8f82fb779d9James Dong    mTimeScale = 90000;
1541c059860c73678a202bfa33062723e8f82fb779d9James Dong
1542c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mIsAudio) {
1543c059860c73678a202bfa33062723e8f82fb779d9James Dong        // Use the sampling rate as the default time scale for audio track.
1544c059860c73678a202bfa33062723e8f82fb779d9James Dong        int32_t sampleRate;
1545c059860c73678a202bfa33062723e8f82fb779d9James Dong        bool success = mMeta->findInt32(kKeySampleRate, &sampleRate);
1546c059860c73678a202bfa33062723e8f82fb779d9James Dong        CHECK(success);
1547c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = sampleRate;
1548c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
1549c059860c73678a202bfa33062723e8f82fb779d9James Dong
1550c059860c73678a202bfa33062723e8f82fb779d9James Dong    // If someone would like to overwrite the timescale, use user-supplied value.
1551c059860c73678a202bfa33062723e8f82fb779d9James Dong    int32_t timeScale;
1552c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mMeta->findInt32(kKeyTimeScale, &timeScale)) {
1553c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = timeScale;
1554c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
1555c059860c73678a202bfa33062723e8f82fb779d9James Dong
155643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mTimeScale, 0);
155719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber}
155819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
155919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Hubervoid MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() {
156019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    const char *mime;
156119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
156219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
156319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
156419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        uint32_t type;
156519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        const void *data;
156619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        size_t size;
156719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        if (mMeta->findData(kKeyAVCC, &type, &data, &size)) {
156819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mCodecSpecificData = malloc(size);
156919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mCodecSpecificDataSize = size;
157019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            memcpy(mCodecSpecificData, data, size);
157119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mGotAllCodecSpecificData = true;
157219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        }
157319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
157419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
157519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        uint32_t type;
157619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        const void *data;
157719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        size_t size;
157819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        if (mMeta->findData(kKeyESDS, &type, &data, &size)) {
157919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            ESDS esds(data, size);
158019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            if (esds.getCodecSpecificInfo(&data, &size) == OK) {
158119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mCodecSpecificData = malloc(size);
158219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mCodecSpecificDataSize = size;
158319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                memcpy(mCodecSpecificData, data, size);
158419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mGotAllCodecSpecificData = true;
158519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            }
158619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        }
158719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
158820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
158920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
159020111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() {
159120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    stop();
159220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1593c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStszTableEntries;
1594c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStcoTableEntries;
1595c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mCo64TableEntries;
1596c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStscTableEntries;
1597c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mSttsTableEntries;
1598c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStssTableEntries;
1599c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mCttsTableEntries;
1600c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
1601c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStszTableEntries = NULL;
1602c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStcoTableEntries = NULL;
1603c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCo64TableEntries = NULL;
1604c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStscTableEntries = NULL;
1605c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries = NULL;
1606c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries = NULL;
1607c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries = NULL;
1608c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
160920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mCodecSpecificData != NULL) {
161020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        free(mCodecSpecificData);
161120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mCodecSpecificData = NULL;
161220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
161320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
161420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
161593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) {
16163856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("initTrackingProgressStatus");
161793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mPreviousTrackTimeUs = -1;
161893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackingProgressStatus = false;
161993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackEveryTimeDurationUs = 0;
162093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    {
162193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        int64_t timeUs;
162293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) {
1623a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGV("Receive request to track progress status for every %" PRId64 " us", timeUs);
162493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackEveryTimeDurationUs = timeUs;
162593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackingProgressStatus = true;
162693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
162793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
162893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
162993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
16301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong// static
16311c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid *MPEG4Writer::ThreadWrapper(void *me) {
16323856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("ThreadWrapper: %p", me);
16331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    MPEG4Writer *writer = static_cast<MPEG4Writer *>(me);
16341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    writer->threadFunc();
16351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return NULL;
16361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
16371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
16381c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::bufferChunk(const Chunk& chunk) {
16393856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("bufferChunk: %p", chunk.mTrack);
16401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Mutex::Autolock autolock(mLock);
16411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    CHECK_EQ(mDone, false);
16421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
16431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
16441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
16451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
16461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (chunk.mTrack == it->mTrack) {  // Found owner
16471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            it->mChunks.push_back(chunk);
16481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.signal();
16491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            return;
16501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
16511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
16521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
165343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK(!"Received a chunk for a unknown track");
16541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
16551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1656fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeChunkToFile(Chunk* chunk) {
1657a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("writeChunkToFile: %" PRId64 " from %s track",
16585410afcbb0af5d29d9f710a1c2978c500f9792dcPannag Sanketi        chunk->mTimeStampUs, chunk->mTrack->isAudio()? "audio": "video");
1659fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1660fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    int32_t isFirstSample = true;
1661fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    while (!chunk->mSamples.empty()) {
1662fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        List<MediaBuffer *>::iterator it = chunk->mSamples.begin();
1663fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1664fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        off64_t offset = chunk->mTrack->isAvc()
1665fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong                                ? addLengthPrefixedSample_l(*it)
1666fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong                                : addSample_l(*it);
1667fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1668fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        if (isFirstSample) {
1669fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            chunk->mTrack->addChunkOffset(offset);
1670fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            isFirstSample = false;
16711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
16721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
16731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it)->release();
16741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it) = NULL;
1675fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        chunk->mSamples.erase(it);
16761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1677fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    chunk->mSamples.clear();
16781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
16791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1680fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeAllChunks() {
16813856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("writeAllChunks");
16821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    size_t outstandingChunks = 0;
168370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    Chunk chunk;
168470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    while (findChunkToWrite(&chunk)) {
1685e9f6d0579603372fd2547e6c5ba6e114c6f8cba7James Dong        writeChunkToFile(&chunk);
168670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        ++outstandingChunks;
16871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
168870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
168970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    sendSessionSummary();
169070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
16911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mChunkInfos.clear();
1692377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    ALOGD("%zu chunks are written in the last batch", outstandingChunks);
16931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
16941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1695fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongbool MPEG4Writer::findChunkToWrite(Chunk *chunk) {
16963856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("findChunkToWrite");
16971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
16981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL;
16991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Track *track = NULL;
17001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
17011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
17021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (!it->mChunks.empty()) {
17031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            List<Chunk>::iterator chunkIt = it->mChunks.begin();
17041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (chunkIt->mTimeStampUs < minTimestampUs) {
17051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                minTimestampUs = chunkIt->mTimeStampUs;
17061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                track = it->mTrack;
17071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            }
17081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
17091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
17101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (track == NULL) {
17123856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("Nothing to be written after all");
1713fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        return false;
17141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
17151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (mIsFirstChunk) {
17171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsFirstChunk = false;
17181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1719fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
17201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
17211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
17221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (it->mTrack == track) {
1723fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            *chunk = *(it->mChunks.begin());
1724fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            it->mChunks.erase(it->mChunks.begin());
1725fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            CHECK_EQ(chunk->mTrack, track);
172670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
172770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            int64_t interChunkTimeUs =
172870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                chunk->mTimeStampUs - it->mPrevChunkTimestampUs;
172970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            if (interChunkTimeUs > it->mPrevChunkTimestampUs) {
173070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                it->mMaxInterChunkDurUs = interChunkTimeUs;
173170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            }
173270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
1733fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            return true;
17341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
17351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1736fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1737fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    return false;
17381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
17391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17401c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::threadFunc() {
17413856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("threadFunc");
17421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1743a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    prctl(PR_SET_NAME, (unsigned long)"MPEG4Writer", 0, 0, 0);
1744fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1745fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    Mutex::Autolock autoLock(mLock);
17461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    while (!mDone) {
1747fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        Chunk chunk;
1748fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        bool chunkFound = false;
1749fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1750fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        while (!mDone && !(chunkFound = findChunkToWrite(&chunk))) {
17511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.wait(mLock);
17521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
17531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1754de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // In real time recording mode, write without holding the lock in order
1755de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // to reduce the blocking time for media track threads.
1756de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // Otherwise, hold the lock until the existing chunks get written to the
1757de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // file.
1758fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        if (chunkFound) {
1759de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            if (mIsRealTimeRecording) {
1760de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui                mLock.unlock();
1761de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            }
1762fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            writeChunkToFile(&chunk);
1763de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            if (mIsRealTimeRecording) {
1764de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui                mLock.lock();
1765de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            }
1766fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        }
17671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1768fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1769fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    writeAllChunks();
17701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
17711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17721c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::startWriterThread() {
17733856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("startWriterThread");
17741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mDone = false;
17761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsFirstChunk = true;
1777e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    mDriftTimeUs = 0;
17781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<Track *>::iterator it = mTracks.begin();
17791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mTracks.end(); ++it) {
17801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        ChunkInfo info;
17811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        info.mTrack = *it;
178270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        info.mPrevChunkTimestampUs = 0;
178370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        info.mMaxInterChunkDurUs = 0;
17841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkInfos.push_back(info);
17851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
17861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_t attr;
17881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_init(&attr);
17891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
17901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_create(&mThread, &attr, ThreadWrapper, this);
17911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_destroy(&attr);
1792411ba422e3635d534928ffd81abf54f4f291c739James Dong    mWriterThreadStarted = true;
17931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return OK;
17941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
17951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17961f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
179793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) {
1798a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (!mDone && mPaused) {
1799a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mPaused = false;
1800a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mResumed = true;
1801a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
1802a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
180325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
180493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t startTimeUs;
180519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) {
180619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        startTimeUs = 0;
180719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
180870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    mStartTimeRealUs = startTimeUs;
180919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
181013f6284305e4b27395a23db7882d670bdb1bcae1James Dong    int32_t rotationDegrees;
181113f6284305e4b27395a23db7882d670bdb1bcae1James Dong    if (!mIsAudio && params && params->findInt32(kKeyRotation, &rotationDegrees)) {
181213f6284305e4b27395a23db7882d670bdb1bcae1James Dong        mRotation = rotationDegrees;
181313f6284305e4b27395a23db7882d670bdb1bcae1James Dong    }
181413f6284305e4b27395a23db7882d670bdb1bcae1James Dong
181593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    initTrackingProgressStatus(params);
181693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
1817f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    sp<MetaData> meta = new MetaData;
1818de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    if (mOwner->isRealTimeRecording() && mOwner->numTracks() > 1) {
1819a472613aec322e25891abf5c77bf3f7e3c244920James Dong        /*
1820a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * This extra delay of accepting incoming audio/video signals
1821a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * helps to align a/v start time at the beginning of a recording
1822a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * session, and it also helps eliminate the "recording" sound for
1823a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * camcorder applications.
1824a472613aec322e25891abf5c77bf3f7e3c244920James Dong         *
182586b7f47aa7482424cf8fd248f1315311919be3b0James Dong         * If client does not set the start time offset, we fall back to
182686b7f47aa7482424cf8fd248f1315311919be3b0James Dong         * use the default initial delay value.
1827a472613aec322e25891abf5c77bf3f7e3c244920James Dong         */
182886b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL;
182986b7f47aa7482424cf8fd248f1315311919be3b0James Dong        if (startTimeOffsetUs < 0) {  // Start time offset was not set
183086b7f47aa7482424cf8fd248f1315311919be3b0James Dong            startTimeOffsetUs = kInitialDelayTimeUs;
183186b7f47aa7482424cf8fd248f1315311919be3b0James Dong        }
183286b7f47aa7482424cf8fd248f1315311919be3b0James Dong        startTimeUs += startTimeOffsetUs;
1833a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGI("Start time offset: %" PRId64 " us", startTimeOffsetUs);
1834a472613aec322e25891abf5c77bf3f7e3c244920James Dong    }
1835a472613aec322e25891abf5c77bf3f7e3c244920James Dong
1836f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    meta->setInt64(kKeyTime, startTimeUs);
1837a472613aec322e25891abf5c77bf3f7e3c244920James Dong
1838f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    status_t err = mSource->start(meta.get());
183925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    if (err != OK) {
184025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        mDone = mReachedEOS = true;
184125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return err;
184225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
184320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
184420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_t attr;
184520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_init(&attr);
184620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
184720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
184820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = false;
1849eaae38445a340c4857c1c5569475879a728e63b7James Dong    mStarted = true;
1850c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs = 0;
185125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = false;
1852956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    mEstimatedTrackSizeBytes = 0;
18531f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mMdatSizeBytes = 0;
185443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mMaxChunkDurationUs = 0;
185520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
185625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    pthread_create(&mThread, &attr, ThreadWrapper, this);
185720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_destroy(&attr);
185825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
185925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
186020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
186120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
186237187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::pause() {
1863a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
186437187916a486504acaf83bea30147eb5fbf46ae5James Dong    return OK;
1865a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
1866a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
186737187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::stop() {
186872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGD("%s track stopping", mIsAudio? "Audio": "Video");
1869eaae38445a340c4857c1c5569475879a728e63b7James Dong    if (!mStarted) {
187029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Stop() called but track is not started");
1871eaae38445a340c4857c1c5569475879a728e63b7James Dong        return ERROR_END_OF_STREAM;
1872eaae38445a340c4857c1c5569475879a728e63b7James Dong    }
1873eaae38445a340c4857c1c5569475879a728e63b7James Dong
187420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mDone) {
187537187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
187620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
187720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = true;
187820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
187972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGD("%s track source stopping", mIsAudio? "Audio": "Video");
188072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mSource->stop();
188172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGD("%s track source stopped", mIsAudio? "Audio": "Video");
188272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
188320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *dummy;
188420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_join(mThread, &dummy);
1885377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    status_t err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy));
188637187916a486504acaf83bea30147eb5fbf46ae5James Dong
1887b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("%s track stopped", mIsAudio? "Audio": "Video");
188837187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
188920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
189020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
189125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() {
189225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return mReachedEOS;
189325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
189425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
189520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static
189620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) {
189720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = static_cast<Track *>(me);
189820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
189937187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = track->threadEntry();
1900377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    return (void *)(uintptr_t)err;
190120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
190220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
19033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic void getNalUnitType(uint8_t byte, uint8_t* type) {
19043856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("getNalUnitType: %d", byte);
19053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // nal_unit_type: 5-bit unsigned integer
19073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *type = (byte & 0x1F);
19083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
19093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t *findNextStartCode(
19113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length) {
19123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
1913a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("findNextStartCode: %p %zu", data, length);
19143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t bytesLeft = length;
19163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    while (bytesLeft > 4  &&
19173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            memcmp("\x00\x00\x00\x01", &data[length - bytesLeft], 4)) {
19183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        --bytesLeft;
19193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
19203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (bytesLeft <= 4) {
19213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        bytesLeft = 0; // Last parameter set
19223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
19233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return &data[length - bytesLeft];
19243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
19253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongconst uint8_t *MPEG4Writer::Track::parseParamSet(
19273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen) {
19283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19293856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("parseParamSet");
19303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    CHECK(type == kNalUnitTypeSeqParamSet ||
19313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong          type == kNalUnitTypePicParamSet);
19323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *nextStartCode = findNextStartCode(data, length);
19343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *paramSetLen = nextStartCode - data;
19353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (*paramSetLen == 0) {
193629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Param set is malformed, since its length is 0");
19373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return NULL;
19383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
19393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    AVCParamSet paramSet(*paramSetLen, data);
19413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (type == kNalUnitTypeSeqParamSet) {
19423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (*paramSetLen < 4) {
194329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Seq parameter set malformed");
19443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return NULL;
19453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
19463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mSeqParamSets.empty()) {
19473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc = data[1];
19483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileCompatible = data[2];
19493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mLevelIdc = data[3];
19503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
19513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (mProfileIdc != data[1] ||
19523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mProfileCompatible != data[2] ||
19533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mLevelIdc != data[3]) {
195429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("Inconsistent profile/level found in seq parameter sets");
19553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return NULL;
19563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
19573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
19583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mSeqParamSets.push_back(paramSet);
19593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    } else {
19603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mPicParamSets.push_back(paramSet);
19613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
19623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return nextStartCode;
19633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
19643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::copyAVCCodecSpecificData(
19663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
19673856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("copyAVCCodecSpecificData");
19683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 2 bytes for each of the parameter set length field
19703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // plus the 7 bytes for the header
19713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (size < 4 + 7) {
1972377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        ALOGE("Codec specific data length too short: %zu", size);
19733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return ERROR_MALFORMED;
19743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
19753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize = size;
19773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificData = malloc(size);
19783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    memcpy(mCodecSpecificData, data, size);
19793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
19803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
19813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::parseAVCCodecSpecificData(
19833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
19843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19853856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("parseAVCCodecSpecificData");
19863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data starts with a start code.
19873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // SPS and PPS are separated with start codes.
19883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Also, SPS must come before PPS
19893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t type = kNalUnitTypeSeqParamSet;
19903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotSps = false;
19913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotPps = false;
19923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *tmp = data;
19933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *nextStartCode = data;
19943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t bytesLeft = size;
19953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t paramSetLen = 0;
19963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize = 0;
19973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) {
19983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        getNalUnitType(*(tmp + 4), &type);
19993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (type == kNalUnitTypeSeqParamSet) {
20003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (gotPps) {
200129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("SPS must come before PPS");
20023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
20033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
20043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
20053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotSps = true;
20063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
20073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
20083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else if (type == kNalUnitTypePicParamSet) {
20093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
201029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("SPS must come before PPS");
20113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
20123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
20133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotPps) {
20143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotPps = true;
20153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
20163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
20173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
201829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Only SPS and PPS Nal units are expected");
20193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
20203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
20213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nextStartCode == NULL) {
20233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
20243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
20253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Move on to find the next parameter set
20273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        bytesLeft -= nextStartCode - tmp;
20283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        tmp = nextStartCode;
20293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mCodecSpecificDataSize += (2 + paramSetLen);
20303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
20313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
20333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of seq parameter sets
20343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nSeqParamSets = mSeqParamSets.size();
20353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets == 0) {
203629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Cound not find sequence parameter set");
20373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
20383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
20393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets > 0x1F) {
2041377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT            ALOGE("Too many seq parameter sets (%zu) found", nSeqParamSets);
20423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
20433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
20443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
20453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
20473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of pic parameter sets
20483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nPicParamSets = mPicParamSets.size();
20493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets == 0) {
205029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Cound not find picture parameter set");
20513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
20523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
20533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets > 0xFF) {
2054377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT            ALOGE("Too many pic parameter sets (%zd) found", nPicParamSets);
20553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
20563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
20573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
20581374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// FIXME:
20591374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// Add chromat_format_idc, bit depth values, etc for AVC/h264 high profile and above
20601374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// and remove #if 0
20611374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#if 0
20623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
20633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the profiles
20643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // These profiles requires additional parameter set extensions
20653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mProfileIdc == 100 || mProfileIdc == 110 ||
20663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc == 122 || mProfileIdc == 144) {
206729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Sorry, no support for profile_idc: %d!", mProfileIdc);
20683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return BAD_VALUE;
20693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
20703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
20711374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#endif
20723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
20733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
2074548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
207503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData(
207603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        const uint8_t *data, size_t size) {
2077548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
207803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (mCodecSpecificData != NULL) {
207929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Already have codec specific data");
208003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
208103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
208203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
20833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (size < 4) {
2084377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        ALOGE("Codec specific data length too short: %zu", size);
208503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
208603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
208703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
20883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data is in the form of AVCCodecSpecificData
20893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (memcmp("\x00\x00\x00\x01", data, 4)) {
20903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return copyAVCCodecSpecificData(data, size);
209103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
209203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
20933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (parseAVCCodecSpecificData(data, size) != OK) {
209403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
209503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
209603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
20973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // ISO 14496-15: AVC file format
20983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize += 7;  // 7 more bytes in the header
209903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    mCodecSpecificData = malloc(mCodecSpecificDataSize);
210003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    uint8_t *header = (uint8_t *)mCodecSpecificData;
21013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = 1;                     // version
21023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[1] = mProfileIdc;           // profile indication
21033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[2] = mProfileCompatible;    // profile compatibility
21043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[3] = mLevelIdc;
210503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
21063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne
2107b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (mOwner->useNalLengthFour()) {
2108b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        header[4] = 0xfc | 3;  // length size == 4 bytes
2109b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    } else {
2110b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        header[4] = 0xfc | 1;  // length size == 2 bytes
2111b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    }
211203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
21133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 3-bit '111' followed by 5-bit numSequenceParameterSets
21143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nSequenceParamSets = mSeqParamSets.size();
21153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[5] = 0xe0 | nSequenceParamSets;
21163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 6;
21173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mSeqParamSets.begin();
21183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mSeqParamSets.end(); ++it) {
21193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit sequence parameter set length
21203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t seqParamSetLength = it->mLength;
21213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = seqParamSetLength >> 8;
21223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = seqParamSetLength & 0xff;
21233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
21243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // SPS NAL unit (sequence parameter length bytes)
21253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, seqParamSetLength);
21263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + seqParamSetLength);
21273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
21283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
21293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 8-bit nPictureParameterSets
21303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nPictureParamSets = mPicParamSets.size();
21313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = nPictureParamSets;
21323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 1;
21333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mPicParamSets.begin();
21343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mPicParamSets.end(); ++it) {
21353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit picture parameter set length
21363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t picParamSetLength = it->mLength;
21373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = picParamSetLength >> 8;
21383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = picParamSetLength & 0xff;
21393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
21403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // PPS Nal unit (picture parameter set length bytes)
21413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, picParamSetLength);
21423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + picParamSetLength);
21433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
214403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
214503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    return OK;
214603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
214703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
2148872a481558350634a3fd5cb67939de288af00ecbJames Dong/*
2149872a481558350634a3fd5cb67939de288af00ecbJames Dong * Updates the drift time from the audio track so that
2150872a481558350634a3fd5cb67939de288af00ecbJames Dong * the video track can get the updated drift time information
2151872a481558350634a3fd5cb67939de288af00ecbJames Dong * from the file writer. The fluctuation of the drift time of the audio
2152872a481558350634a3fd5cb67939de288af00ecbJames Dong * encoding path is smoothed out with a simple filter by giving a larger
2153872a481558350634a3fd5cb67939de288af00ecbJames Dong * weight to more recently drift time. The filter coefficients, 0.5 and 0.5,
2154872a481558350634a3fd5cb67939de288af00ecbJames Dong * are heuristically determined.
2155872a481558350634a3fd5cb67939de288af00ecbJames Dong */
2156872a481558350634a3fd5cb67939de288af00ecbJames Dongvoid MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) {
2157872a481558350634a3fd5cb67939de288af00ecbJames Dong    int64_t driftTimeUs = 0;
2158872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) {
2159872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t prevDriftTimeUs = mOwner->getDriftTimeUs();
2160872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1;
2161872a481558350634a3fd5cb67939de288af00ecbJames Dong        mOwner->setDriftTimeUs(timeUs);
2162872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
2163872a481558350634a3fd5cb67939de288af00ecbJames Dong}
2164872a481558350634a3fd5cb67939de288af00ecbJames Dong
216537187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::threadEntry() {
216630ab66297501757d745b9ae10da61adcd891f497Andreas Huber    int32_t count = 0;
216713aec890216948b0c364f8f92792129d0335f506James Dong    const int64_t interleaveDurationUs = mOwner->interleaveDuration();
216843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    const bool hasMultipleTracks = (mOwner->numTracks() > 1);
216913aec890216948b0c364f8f92792129d0335f506James Dong    int64_t chunkTimestampUs = 0;
217013aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nChunks = 0;
217113aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nZeroLengthFrames = 0;
2172965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastTimestampUs = 0;      // Previous sample time stamp
2173965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastDurationUs = 0;       // Between the previous two samples
2174965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t currDurationTicks = 0;    // Timescale based ticks
2175965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastDurationTicks = 0;    // Timescale based ticks
2176965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int32_t sampleCount = 1;          // Sample count in the current stts table entry
2177000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    uint32_t previousSampleSize = 0;  // Size of the previous sample
2178a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    int64_t previousPausedDurationUs = 0;
2179965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t timestampUs = 0;
2180000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t cttsOffsetTimeUs = 0;
2181000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t currCttsOffsetTimeTicks = 0;   // Timescale based ticks
2182000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t lastCttsOffsetTimeTicks = -1;  // Timescale based ticks
218343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    int32_t cttsSampleCount = 0;           // Sample count in the current ctts table entry
2184c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t lastSamplesPerChunk = 0;
2185e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
2186a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    if (mIsAudio) {
2187a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong        prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0);
2188a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    } else {
2189a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong        prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0);
2190a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    }
2191de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui
2192de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    if (mOwner->isRealTimeRecording()) {
2193de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
2194de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    }
2195985f838934510983d8a887461e98dca60a6e858fJames Dong
2196d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong    sp<MetaData> meta_data;
219720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
219893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t err = OK;
219920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBuffer *buffer;
220011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih    const char *trackName = mIsAudio ? "Audio" : "Video";
220193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    while (!mDone && (err = mSource->read(&buffer)) == OK) {
220220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (buffer->range_length() == 0) {
220320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer->release();
220420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer = NULL;
220513aec890216948b0c364f8f92792129d0335f506James Dong            ++nZeroLengthFrames;
220620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            continue;
220720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
220820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2209a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // If the codec specific data has not been received yet, delay pause.
2210a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // After the codec specific data is received, discard what we received
2211a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // when the track is to be paused.
2212a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused && !mResumed) {
2213a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer->release();
2214a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer = NULL;
2215a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            continue;
2216a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
2217a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
221830ab66297501757d745b9ae10da61adcd891f497Andreas Huber        ++count;
221930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
222003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        int32_t isCodecConfig;
222103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig)
222203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                && isCodecConfig) {
2223548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            CHECK(!mGotAllCodecSpecificData);
2224548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
22251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (mIsAvc) {
222603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                status_t err = makeAVCCodecSpecificData(
222703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        (const uint8_t *)buffer->data()
222803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                            + buffer->range_offset(),
222903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        buffer->range_length());
223043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                CHECK_EQ((status_t)OK, err);
22311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            } else if (mIsMPEG4) {
223203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificDataSize = buffer->range_length();
223303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificData = malloc(mCodecSpecificDataSize);
223403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                memcpy(mCodecSpecificData,
223503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        (const uint8_t *)buffer->data()
223603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                            + buffer->range_offset(),
223703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                       buffer->range_length());
223830ab66297501757d745b9ae10da61adcd891f497Andreas Huber            }
223930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
224030ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer->release();
224130ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer = NULL;
224230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
2243548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            mGotAllCodecSpecificData = true;
224430ab66297501757d745b9ae10da61adcd891f497Andreas Huber            continue;
2245a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
2246a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
2247d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // Make a deep copy of the MediaBuffer and Metadata and release
2248d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // the original as soon as we can
2249d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        MediaBuffer *copy = new MediaBuffer(buffer->range_length());
2250d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(),
2251d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong                buffer->range_length());
2252d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        copy->set_range(0, buffer->range_length());
2253d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data = new MetaData(*buffer->meta_data().get());
2254d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer->release();
2255d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer = NULL;
2256d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
22571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (mIsAvc) StripStartcode(copy);
2258e136c3bb38e88315bf8797a464ebf2c788296b22James Dong
2259b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        size_t sampleSize = copy->range_length();
2260b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        if (mIsAvc) {
2261b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            if (mOwner->useNalLengthFour()) {
2262b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                sampleSize += 4;
2263b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            } else {
2264b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                sampleSize += 2;
2265b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            }
2266b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        }
2267050b28a593350047845a45a14cc5026221ac1620James Dong
2268d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        // Max file size or duration handling
22691f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mMdatSizeBytes += sampleSize;
22701f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        updateTrackSizeEstimate();
22711f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
2272d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileSizeLimit()) {
2273d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
2274d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
2275d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
2276d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileDurationLimit()) {
2277d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
2278d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
2279d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
2280d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
2281050b28a593350047845a45a14cc5026221ac1620James Dong
2282d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        int32_t isSync = false;
2283d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data->findInt32(kKeyIsSyncFrame, &isSync);
2284d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        CHECK(meta_data->findInt64(kKeyTime, &timestampUs));
2285d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
2286d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong////////////////////////////////////////////////////////////////////////////////
2287c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        if (mStszTableEntries->count() == 0) {
228870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            mFirstSampleTimeRealUs = systemTime() / 1000;
2289f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mStartTimestampUs = timestampUs;
2290f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mOwner->setStartTimestampUs(mStartTimestampUs);
22918428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            previousPausedDurationUs = mStartTimestampUs;
22923c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        }
229348c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber
2294a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mResumed) {
22958428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs;
229611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(durExcludingEarlierPausesUs >= 0ll, "for %s track", trackName)) {
229711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
229811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                return ERROR_MALFORMED;
229911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
230011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
23018428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs;
230211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(pausedDurationUs >= lastDurationUs, "for %s track", trackName)) {
230311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
230411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                return ERROR_MALFORMED;
230511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
230611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
23078428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            previousPausedDurationUs += pausedDurationUs - lastDurationUs;
2308a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mResumed = false;
2309a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
2310a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
2311a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        timestampUs -= previousPausedDurationUs;
231211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) {
231311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            copy->release();
231411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            return ERROR_MALFORMED;
231511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        }
231611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
2317000e18370baae60ffd9f25b509501dd8c26deabfJames Dong        if (!mIsAudio) {
2318965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            /*
2319965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             * Composition time: timestampUs
2320965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             * Decoding time: decodingTimeUs
2321000e18370baae60ffd9f25b509501dd8c26deabfJames Dong             * Composition time offset = composition time - decoding time
2322965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             */
2323965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            int64_t decodingTimeUs;
2324965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs));
2325965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            decodingTimeUs -= previousPausedDurationUs;
2326000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            cttsOffsetTimeUs =
2327000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs;
232811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(cttsOffsetTimeUs >= 0ll, "for %s track", trackName)) {
232911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
233011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                return ERROR_MALFORMED;
233111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
233211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
2333965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            timestampUs = decodingTimeUs;
2334a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGV("decoding time: %" PRId64 " and ctts offset time: %" PRId64,
2335000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                timestampUs, cttsOffsetTimeUs);
2336000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2337000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            // Update ctts box table if necessary
2338000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            currCttsOffsetTimeTicks =
2339000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    (cttsOffsetTimeUs * mTimeScale + 500000LL) / 1000000LL;
234011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(currCttsOffsetTimeTicks <= 0x0FFFFFFFFLL, "for %s track", trackName)) {
234111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
234211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                return ERROR_MALFORMED;
234311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
234411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
2345c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() == 0) {
234643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // Force the first ctts table entry to have one single entry
234743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // so that we can do adjustment for the initial track start
234843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // time offset easily in writeCttsBox().
234943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks;
235043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                addOneCttsTableEntry(1, currCttsOffsetTimeTicks);
235143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                cttsSampleCount = 0;      // No sample in ctts box is pending
235243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            } else {
235343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                if (currCttsOffsetTimeTicks != lastCttsOffsetTimeTicks) {
235443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
235543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks;
235643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    cttsSampleCount = 1;  // One sample in ctts box is pending
235743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                } else {
235843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    ++cttsSampleCount;
235943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                }
236043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            }
2361000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2362000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            // Update ctts time offset range
2363c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() == 0) {
2364000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2365000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2366000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            } else {
2367000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                if (currCttsOffsetTimeTicks > mMaxCttsOffsetTimeUs) {
2368000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2369000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                } else if (currCttsOffsetTimeTicks < mMinCttsOffsetTimeUs) {
2370000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2371000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                }
2372000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            }
2373000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2374965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        }
2375872a481558350634a3fd5cb67939de288af00ecbJames Dong
2376de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        if (mOwner->isRealTimeRecording()) {
2377872a481558350634a3fd5cb67939de288af00ecbJames Dong            if (mIsAudio) {
2378872a481558350634a3fd5cb67939de288af00ecbJames Dong                updateDriftTime(meta_data);
2379e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            }
2380e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        }
2381872a481558350634a3fd5cb67939de288af00ecbJames Dong
238211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) {
238311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            copy->release();
238411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            return ERROR_MALFORMED;
238511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        }
238611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
2387a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("%s media time stamp: %" PRId64 " and previous paused duration %" PRId64,
238811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                trackName, timestampUs, previousPausedDurationUs);
2389c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong        if (timestampUs > mTrackDurationUs) {
2390c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong            mTrackDurationUs = timestampUs;
23913b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber        }
23923b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber
23935a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // We need to use the time scale based ticks, rather than the
23945a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // timestamp itself to determine whether we have to use a new
23955a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // stts entry, since we may have rounding errors.
23965a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // The calculation is intended to reduce the accumulated
23975a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // rounding errors.
23985a217fba010e801c255503602bda4b86ac5a6ac9James Dong        currDurationTicks =
23995a217fba010e801c255503602bda4b86ac5a6ac9James Dong            ((timestampUs * mTimeScale + 500000LL) / 1000000LL -
24005a217fba010e801c255503602bda4b86ac5a6ac9James Dong                (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL);
2401c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        if (currDurationTicks < 0ll) {
2402a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGE("timestampUs %" PRId64 " < lastTimestampUs %" PRId64 " for %s track",
240311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                timestampUs, lastTimestampUs, trackName);
240411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            copy->release();
2405c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            return UNKNOWN_ERROR;
24068c460498c028888c533ab442be12b6d4b669b965James Dong        }
24078c460498c028888c533ab442be12b6d4b669b965James Dong
240885fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // if the duration is different for this sample, see if it is close enough to the previous
240985fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // duration that we can fudge it and use the same value, to avoid filling the stts table
241085fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // with lots of near-identical entries.
241185fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // "close enough" here means that the current duration needs to be adjusted by less
241285fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // than 0.1 milliseconds
241385fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        if (lastDurationTicks && (currDurationTicks != lastDurationTicks)) {
241485fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen            int64_t deltaUs = ((lastDurationTicks - currDurationTicks) * 1000000LL
241585fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                    + (mTimeScale / 2)) / mTimeScale;
241685fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen            if (deltaUs > -100 && deltaUs < 100) {
241785fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                // use previous ticks, and adjust timestamp as if it was actually that number
241885fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                // of ticks
241985fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                currDurationTicks = lastDurationTicks;
242085fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                timestampUs += deltaUs;
242185fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen            }
242285fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        }
242385fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen
2424c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStszTableEntries->add(htonl(sampleSize));
2425c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        if (mStszTableEntries->count() > 2) {
2426c059860c73678a202bfa33062723e8f82fb779d9James Dong
2427a472613aec322e25891abf5c77bf3f7e3c244920James Dong            // Force the first sample to have its own stts entry so that
2428a472613aec322e25891abf5c77bf3f7e3c244920James Dong            // we can adjust its value later to maintain the A/V sync.
2429c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() == 3 || currDurationTicks != lastDurationTicks) {
243079761ab096f57c3027fad9556c2bc436672d614eJames Dong                addOneSttsTableEntry(sampleCount, lastDurationTicks);
2431be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                sampleCount = 1;
2432be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            } else {
2433be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                ++sampleCount;
2434be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
2435965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2436be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
2437be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        if (mSamplesHaveSameSize) {
2438c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() >= 2 && previousSampleSize != sampleSize) {
2439be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mSamplesHaveSameSize = false;
2440be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
24418644c14618d30d9e57a69df40ed939986ebf02c4James Dong            previousSampleSize = sampleSize;
2442be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
2443a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("%s timestampUs/lastTimestampUs: %" PRId64 "/%" PRId64,
244411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                trackName, timestampUs, lastTimestampUs);
24458644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastDurationUs = timestampUs - lastTimestampUs;
2446c059860c73678a202bfa33062723e8f82fb779d9James Dong        lastDurationTicks = currDurationTicks;
24478644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastTimestampUs = timestampUs;
244820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2449d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        if (isSync != 0) {
2450c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            addOneStssTableEntry(mStszTableEntries->count());
2451d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        }
2452d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
245393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (mTrackingProgressStatus) {
245493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            if (mPreviousTrackTimeUs <= 0) {
245593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong                mPreviousTrackTimeUs = mStartTimestampUs;
245693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            }
2457faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong            trackProgressStatus(timestampUs);
245893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
245943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong        if (!hasMultipleTracks) {
2460c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t offset = mIsAvc? mOwner->addLengthPrefixedSample_l(copy)
246158ae9c530247668f8af36e30d228c716c226b3d4James Dong                                 : mOwner->addSample_l(copy);
2462c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
2463c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t count = (mOwner->use32BitFileOffset()
2464c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        ? mStcoTableEntries->count()
2465c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        : mCo64TableEntries->count());
2466c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
2467c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (count == 0) {
24681f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                addChunkOffset(offset);
246958ae9c530247668f8af36e30d228c716c226b3d4James Dong            }
247058ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy->release();
247158ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy = NULL;
247258ae9c530247668f8af36e30d228c716c226b3d4James Dong            continue;
247358ae9c530247668f8af36e30d228c716c226b3d4James Dong        }
247413aec890216948b0c364f8f92792129d0335f506James Dong
247513aec890216948b0c364f8f92792129d0335f506James Dong        mChunkSamples.push_back(copy);
247613aec890216948b0c364f8f92792129d0335f506James Dong        if (interleaveDurationUs == 0) {
24771f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            addOneStscTableEntry(++nChunks, 1);
24781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            bufferChunk(timestampUs);
247913aec890216948b0c364f8f92792129d0335f506James Dong        } else {
248013aec890216948b0c364f8f92792129d0335f506James Dong            if (chunkTimestampUs == 0) {
248113aec890216948b0c364f8f92792129d0335f506James Dong                chunkTimestampUs = timestampUs;
248213aec890216948b0c364f8f92792129d0335f506James Dong            } else {
248343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                int64_t chunkDurationUs = timestampUs - chunkTimestampUs;
248443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                if (chunkDurationUs > interleaveDurationUs) {
248543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    if (chunkDurationUs > mMaxChunkDurationUs) {
248643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                        mMaxChunkDurationUs = chunkDurationUs;
248743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    }
248813aec890216948b0c364f8f92792129d0335f506James Dong                    ++nChunks;
248913aec890216948b0c364f8f92792129d0335f506James Dong                    if (nChunks == 1 ||  // First chunk
2490c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        lastSamplesPerChunk != mChunkSamples.size()) {
2491c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        lastSamplesPerChunk = mChunkSamples.size();
2492c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        addOneStscTableEntry(nChunks, lastSamplesPerChunk);
249313aec890216948b0c364f8f92792129d0335f506James Dong                    }
24941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                    bufferChunk(timestampUs);
249513aec890216948b0c364f8f92792129d0335f506James Dong                    chunkTimestampUs = timestampUs;
249613aec890216948b0c364f8f92792129d0335f506James Dong                }
249713aec890216948b0c364f8f92792129d0335f506James Dong            }
249813aec890216948b0c364f8f92792129d0335f506James Dong        }
249913aec890216948b0c364f8f92792129d0335f506James Dong
250020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
250125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
250245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    if (isTrackMalFormed()) {
2503690f546b0ee548dbfe997df36418e5302ec2d786James Dong        err = ERROR_MALFORMED;
2504f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong    }
250545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
2506bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    mOwner->trackProgressStatus(mTrackId, -1, err);
2507be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
250813aec890216948b0c364f8f92792129d0335f506James Dong    // Last chunk
250943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    if (!hasMultipleTracks) {
2510c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        addOneStscTableEntry(1, mStszTableEntries->count());
251158ae9c530247668f8af36e30d228c716c226b3d4James Dong    } else if (!mChunkSamples.empty()) {
25121f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        addOneStscTableEntry(++nChunks, mChunkSamples.size());
25131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        bufferChunk(timestampUs);
251413aec890216948b0c364f8f92792129d0335f506James Dong    }
251513aec890216948b0c364f8f92792129d0335f506James Dong
2516be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // We don't really know how long the last frame lasts, since
2517be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // there is no frame time after it, just repeat the previous
2518be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // frame's duration.
2519c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mStszTableEntries->count() == 1) {
25208f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        lastDurationUs = 0;  // A single sample's duration
252179761ab096f57c3027fad9556c2bc436672d614eJames Dong        lastDurationTicks = 0;
2522be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    } else {
2523be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        ++sampleCount;  // Count for the last sample
2524be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    }
2525a472613aec322e25891abf5c77bf3f7e3c244920James Dong
2526c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mStszTableEntries->count() <= 2) {
252779761ab096f57c3027fad9556c2bc436672d614eJames Dong        addOneSttsTableEntry(1, lastDurationTicks);
2528a472613aec322e25891abf5c77bf3f7e3c244920James Dong        if (sampleCount - 1 > 0) {
252979761ab096f57c3027fad9556c2bc436672d614eJames Dong            addOneSttsTableEntry(sampleCount - 1, lastDurationTicks);
2530a472613aec322e25891abf5c77bf3f7e3c244920James Dong        }
2531a472613aec322e25891abf5c77bf3f7e3c244920James Dong    } else {
253279761ab096f57c3027fad9556c2bc436672d614eJames Dong        addOneSttsTableEntry(sampleCount, lastDurationTicks);
2533a472613aec322e25891abf5c77bf3f7e3c244920James Dong    }
2534a472613aec322e25891abf5c77bf3f7e3c244920James Dong
253543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    // The last ctts box may not have been written yet, and this
253643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    // is to make sure that we write out the last ctts box.
253743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    if (currCttsOffsetTimeTicks == lastCttsOffsetTimeTicks) {
253843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        if (cttsSampleCount > 0) {
253943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
254043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        }
254143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    }
254243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong
2543c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs += lastDurationUs;
254425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = true;
254543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
254643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    sendTrackSummary(hasMultipleTracks);
254743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
2548df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s",
254911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            count, nZeroLengthFrames, mStszTableEntries->count(), trackName);
2550872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (mIsAudio) {
2551a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGI("Audio track drift time: %" PRId64 " us", mOwner->getDriftTimeUs());
2552872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
2553365a963142093a1cd8efdcea76b5f65096a5b115James Dong
255437187916a486504acaf83bea30147eb5fbf46ae5James Dong    if (err == ERROR_END_OF_STREAM) {
255537187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
255637187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
255737187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
2558365a963142093a1cd8efdcea76b5f65096a5b115James Dong}
2559365a963142093a1cd8efdcea76b5f65096a5b115James Dong
256045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dongbool MPEG4Writer::Track::isTrackMalFormed() const {
2561c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mStszTableEntries->count() == 0) {                      // no samples written
256229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("The number of recorded samples is 0");
256345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
256445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
256545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
2566c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (!mIsAudio && mStssTableEntries->count() == 0) {  // no sync frames for video
256729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("There are no sync frames for video track");
256845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
256945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
257045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
257145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    if (OK != checkCodecSpecificData()) {         // no codec specific data
257245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
257345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
257445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
257545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    return false;
257645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong}
257745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
257843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dongvoid MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) {
257907ec01904613a0bac32caaa8444b4690998faed7James Dong
258007ec01904613a0bac32caaa8444b4690998faed7James Dong    // Send track summary only if test mode is enabled.
258107ec01904613a0bac32caaa8444b4690998faed7James Dong    if (!isTestModeEnabled()) {
258207ec01904613a0bac32caaa8444b4690998faed7James Dong        return;
258307ec01904613a0bac32caaa8444b4690998faed7James Dong    }
258407ec01904613a0bac32caaa8444b4690998faed7James Dong
258543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    int trackNum = (mTrackId << 28);
258643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
258743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
258843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_TYPE,
258943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mIsAudio? 0: 1);
259043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
259143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
259243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_DURATION_MS,
259343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mTrackDurationUs / 1000);
259443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
259543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
259643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES,
2597c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    mStszTableEntries->count());
259843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
259986b7f47aa7482424cf8fd248f1315311919be3b0James Dong    {
260086b7f47aa7482424cf8fd248f1315311919be3b0James Dong        // The system delay time excluding the requested initial delay that
260186b7f47aa7482424cf8fd248f1315311919be3b0James Dong        // is used to eliminate the recording sound.
260286b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL;
260386b7f47aa7482424cf8fd248f1315311919be3b0James Dong        if (startTimeOffsetUs < 0) {  // Start time offset was not set
260486b7f47aa7482424cf8fd248f1315311919be3b0James Dong            startTimeOffsetUs = kInitialDelayTimeUs;
260586b7f47aa7482424cf8fd248f1315311919be3b0James Dong        }
260686b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t initialDelayUs =
260786b7f47aa7482424cf8fd248f1315311919be3b0James Dong            mFirstSampleTimeRealUs - mStartTimeRealUs - startTimeOffsetUs;
260886b7f47aa7482424cf8fd248f1315311919be3b0James Dong
260986b7f47aa7482424cf8fd248f1315311919be3b0James Dong        mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
261070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS,
261170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    (initialDelayUs) / 1000);
261286b7f47aa7482424cf8fd248f1315311919be3b0James Dong    }
261370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
261407ec01904613a0bac32caaa8444b4690998faed7James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
261507ec01904613a0bac32caaa8444b4690998faed7James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES,
261607ec01904613a0bac32caaa8444b4690998faed7James Dong                    mMdatSizeBytes / 1024);
261707ec01904613a0bac32caaa8444b4690998faed7James Dong
261843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    if (hasMultipleTracks) {
261943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong        mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
262043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS,
262143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mMaxChunkDurationUs / 1000);
262270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
262370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
262470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        if (mStartTimestampUs != moovStartTimeUs) {
262570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            int64_t startTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
262670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
262770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS,
262870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    startTimeOffsetUs / 1000);
262970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        }
263043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    }
263143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong}
263243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
2633faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) {
2634a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("trackProgressStatus: %" PRId64 " us", timeUs);
2635c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
2636215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    if (mTrackEveryTimeDurationUs > 0 &&
2637215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) {
2638a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("Fire time tracking progress status at %" PRId64 " us", timeUs);
2639bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err);
264093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        mPreviousTrackTimeUs = timeUs;
264193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
264293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
264393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
2644faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::trackProgressStatus(
2645bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        size_t trackId, int64_t timeUs, status_t err) {
2646faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    Mutex::Autolock lock(mLock);
2647bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    int32_t trackNum = (trackId << 28);
2648faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
2649faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Error notification
2650faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Do not consider ERROR_END_OF_STREAM an error
2651faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (err != OK && err != ERROR_END_OF_STREAM) {
2652bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_ERROR,
2653bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL,
2654faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
2655faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        return;
2656faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
2657faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
2658faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (timeUs == -1) {
2659faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send completion notification
2660bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
2661bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS,
2662faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
2663faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    } else {
2664faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send progress status
2665bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
2666bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME,
2667faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               timeUs / 1000);
2668faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
2669faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong}
2670faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
2671d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dongvoid MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) {
2672a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("setDriftTimeUs: %" PRId64 " us", driftTimeUs);
2673e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
2674d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong    mDriftTimeUs = driftTimeUs;
2675e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
2676e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
2677e259531ce59ab1f31de5a23124b22536f6a5a767James Dongint64_t MPEG4Writer::getDriftTimeUs() {
2678a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("getDriftTimeUs: %" PRId64 " us", mDriftTimeUs);
2679e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
2680e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    return mDriftTimeUs;
2681e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
2682e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
2683de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghuibool MPEG4Writer::isRealTimeRecording() const {
2684de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    return mIsRealTimeRecording;
2685de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui}
2686de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui
2687b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dongbool MPEG4Writer::useNalLengthFour() {
2688b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    return mUse4ByteNalLength;
2689b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong}
2690b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong
26911c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::Track::bufferChunk(int64_t timestampUs) {
26923856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("bufferChunk");
26931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
26941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Chunk chunk(this, timestampUs, mChunkSamples);
26951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mOwner->bufferChunk(chunk);
269613aec890216948b0c364f8f92792129d0335f506James Dong    mChunkSamples.clear();
269720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
269820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
26993b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const {
2700c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    return mTrackDurationUs;
270120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
270220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2703d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const {
2704d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return mEstimatedTrackSizeBytes;
2705d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
2706d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
2707690f546b0ee548dbfe997df36418e5302ec2d786James Dongstatus_t MPEG4Writer::Track::checkCodecSpecificData() const {
2708690f546b0ee548dbfe997df36418e5302ec2d786James Dong    const char *mime;
2709690f546b0ee548dbfe997df36418e5302ec2d786James Dong    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
2710690f546b0ee548dbfe997df36418e5302ec2d786James Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) ||
2711690f546b0ee548dbfe997df36418e5302ec2d786James Dong        !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) ||
2712690f546b0ee548dbfe997df36418e5302ec2d786James Dong        !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
2713690f546b0ee548dbfe997df36418e5302ec2d786James Dong        if (!mCodecSpecificData ||
2714690f546b0ee548dbfe997df36418e5302ec2d786James Dong            mCodecSpecificDataSize <= 0) {
271529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Missing codec specific data");
2716690f546b0ee548dbfe997df36418e5302ec2d786James Dong            return ERROR_MALFORMED;
2717690f546b0ee548dbfe997df36418e5302ec2d786James Dong        }
2718690f546b0ee548dbfe997df36418e5302ec2d786James Dong    } else {
2719690f546b0ee548dbfe997df36418e5302ec2d786James Dong        if (mCodecSpecificData ||
2720690f546b0ee548dbfe997df36418e5302ec2d786James Dong            mCodecSpecificDataSize > 0) {
272129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Unexepected codec specific data found");
2722690f546b0ee548dbfe997df36418e5302ec2d786James Dong            return ERROR_MALFORMED;
2723690f546b0ee548dbfe997df36418e5302ec2d786James Dong        }
2724690f546b0ee548dbfe997df36418e5302ec2d786James Dong    }
2725690f546b0ee548dbfe997df36418e5302ec2d786James Dong    return OK;
2726690f546b0ee548dbfe997df36418e5302ec2d786James Dong}
2727690f546b0ee548dbfe997df36418e5302ec2d786James Dong
2728b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeTrackHeader(bool use32BitOffset) {
272920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
27303856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("%s track time scale: %d",
27311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsAudio? "Audio": "Video", mTimeScale);
27328f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
2733efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    uint32_t now = getMpeg4Time();
2734b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("trak");
2735b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeTkhdBox(now);
2736b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->beginBox("mdia");
2737b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            writeMdhdBox(now);
2738b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            writeHdlrBox();
2739b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            mOwner->beginBox("minf");
2740b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                if (mIsAudio) {
2741b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                    writeSmhdBox();
2742b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                } else {
2743b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                    writeVmhdBox();
2744b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                }
2745b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                writeDinfBox();
2746b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                writeStblBox(use32BitOffset);
2747b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            mOwner->endBox();  // minf
2748b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->endBox();  // mdia
2749b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // trak
2750b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2751b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2752b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStblBox(bool use32BitOffset) {
2753b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stbl");
2754b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsd");
2755b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);               // version=0, flags=0
2756b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);               // entry count
2757b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mIsAudio) {
2758b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeAudioFourCCBox();
2759b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
2760b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeVideoFourCCBox();
2761b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2762b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsd
2763b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeSttsBox();
2764965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    writeCttsBox();
2765b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!mIsAudio) {
2766b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeStssBox();
2767b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2768b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStszBox();
2769b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStscBox();
2770b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStcoBox(use32BitOffset);
2771b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stbl
2772b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2773b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2774b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVideoFourCCBox() {
2775b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    const char *mime;
2776b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    bool success = mMeta->findCString(kKeyMIMEType, &mime);
2777b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
27788b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    const char *fourcc = getFourCCForMime(mime);
27798b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (fourcc == NULL) {
278029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Unknown mime type '%s'.", mime);
2781b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        CHECK(!"should not be here, unknown mime type.");
2782b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2783b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
27848b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    mOwner->beginBox(fourcc);        // video format
2785b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2786b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2787b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(1);           // data ref index
2788b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // predefined
2789b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2790b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
2791b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
2792b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
2793b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2794b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t width, height;
2795b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = mMeta->findInt32(kKeyWidth, &width);
2796b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = success && mMeta->findInt32(kKeyHeight, &height);
2797b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
2798b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2799b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(width);
2800b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(height);
2801b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x480000);    // horiz resolution
2802b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x480000);    // vert resolution
2803b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2804b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(1);           // frame count
2805c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo    mOwner->writeInt8(0);            // compressor string length
2806c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo    mOwner->write("                               ", 31);
2807b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x18);        // depth
2808b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(-1);          // predefined
2809b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
281043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_LT(23 + mCodecSpecificDataSize, 128);
2811b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2812b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
2813b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeMp4vEsdsBox();
2814b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
2815b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeD263Box();
2816b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
2817b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeAvccBox();
2818b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2819b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2820b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writePaspBox();
2821b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // mp4v, s263 or avc1
2822b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2823b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2824b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAudioFourCCBox() {
2825b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    const char *mime;
2826b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    bool success = mMeta->findCString(kKeyMIMEType, &mime);
2827b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
28288b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    const char *fourcc = getFourCCForMime(mime);
28298b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (fourcc == NULL) {
283029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Unknown mime type '%s'.", mime);
2831b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        CHECK(!"should not be here, unknown mime type.");
2832b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2833b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2834b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox(fourcc);        // audio format
2835b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2836b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2837b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x1);         // data ref index
2838b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2839b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2840b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t nChannels;
2841b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels));
2842b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(nChannels);   // channel count
2843b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(16);          // sample size
2844b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // predefined
2845b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2846b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2847b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t samplerate;
2848b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = mMeta->findInt32(kKeySampleRate, &samplerate);
2849b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
2850b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(samplerate << 16);
2851b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
2852b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeMp4aEsdsBox();
2853b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) ||
2854b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong               !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
2855b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeDamrBox();
2856b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2857b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2858b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2859b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2860b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4aEsdsBox() {
2861b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("esds");
2862b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
286343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mCodecSpecificDataSize, 0);
2864b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2865b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Make sure all sizes encode to a single byte.
286643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_LT(mCodecSpecificDataSize + 23, 128);
2867b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2868b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);     // version=0, flags=0
2869b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x03);   // ES_DescrTag
2870b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(23 + mCodecSpecificDataSize);
2871b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x0000);// ES_ID
2872b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x00);
2873b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2874b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x04);   // DecoderConfigDescrTag
2875b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(15 + mCodecSpecificDataSize);
2876b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x40);   // objectTypeIndication ISO/IEC 14492-2
2877b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x15);   // streamType AudioStream
2878b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2879b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x03);  // XXX
2880b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x00);   // buffer size 24-bit
2881ebada74ec20c6bd46e81d2f4c160ac176c10784dDaniel Bonnevier    int32_t bitRate;
2882ebada74ec20c6bd46e81d2f4c160ac176c10784dDaniel Bonnevier    bool success = mMeta->findInt32(kKeyBitRate, &bitRate);
2883ebada74ec20c6bd46e81d2f4c160ac176c10784dDaniel Bonnevier    mOwner->writeInt32(success ? bitRate : 96000); // max bit rate
2884ebada74ec20c6bd46e81d2f4c160ac176c10784dDaniel Bonnevier    mOwner->writeInt32(success ? bitRate : 96000); // avg bit rate
2885b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2886b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x05);   // DecoderSpecificInfoTag
2887b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(mCodecSpecificDataSize);
2888b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
2889b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2890b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData2[] = {
2891b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x06,  // SLConfigDescriptorTag
2892b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x01,
2893b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x02
2894b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
2895b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData2, sizeof(kData2));
2896b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2897b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // esds
2898b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2899b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2900b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4vEsdsBox() {
2901b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
290243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mCodecSpecificDataSize, 0);
2903b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("esds");
2904b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2905b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);    // version=0, flags=0
2906b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2907b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x03);  // ES_DescrTag
2908b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(23 + mCodecSpecificDataSize);
2909b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x0000);  // ES_ID
2910b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x1f);
2911b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2912b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x04);  // DecoderConfigDescrTag
2913b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(15 + mCodecSpecificDataSize);
2914b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x20);  // objectTypeIndication ISO/IEC 14492-2
2915b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x11);  // streamType VisualStream
2916b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2917b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData[] = {
2918b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x01, 0x77, 0x00,
2919b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x00, 0x03, 0xe8, 0x00,
2920b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x00, 0x03, 0xe8, 0x00
2921b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
2922b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData, sizeof(kData));
2923b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2924b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x05);  // DecoderSpecificInfoTag
2925b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2926b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(mCodecSpecificDataSize);
2927b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
2928b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2929b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData2[] = {
2930b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x06,  // SLConfigDescriptorTag
2931b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x01,
2932b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x02
2933b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
2934b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData2, sizeof(kData2));
2935b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2936b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // esds
2937b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2938b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2939efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeTkhdBox(uint32_t now) {
2940b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("tkhd");
2941b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Flags = 7 to indicate that the track is enabled, and
2942b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // part of the presentation
2943b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x07);          // version=0, flags=7
2944b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // creation time
2945b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // modification time
2946219f195159f93d627af2b243732e3f9020511a46James Dong    mOwner->writeInt32(mTrackId);      // track id starts with 1
2947b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
29488f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t trakDurationUs = getDurationUs();
2949b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t mvhdTimeScale = mOwner->getTimeScale();
2950b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t tkhdDuration =
2951b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
2952b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(tkhdDuration);  // in mvhd timescale
2953b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
2954b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
2955b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // layer
2956b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // alternate group
2957b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(mIsAudio ? 0x100 : 0);  // volume
2958b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // reserved
2959b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2960b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCompositionMatrix(mRotation);       // matrix
296120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2962b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mIsAudio) {
2963b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(0);
2964b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(0);
2965b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
2966b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        int32_t width, height;
2967b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        bool success = mMeta->findInt32(kKeyWidth, &width);
2968b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        success = success && mMeta->findInt32(kKeyHeight, &height);
2969b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        CHECK(success);
2970b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2971b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(width << 16);   // 32-bit fixed-point value
2972b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(height << 16);  // 32-bit fixed-point value
2973b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2974b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // tkhd
2975b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2976b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2977b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVmhdBox() {
2978b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("vmhd");
2979b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x01);        // version=0, flags=1
2980b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // graphics mode
2981b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // opcolor
2982b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);
2983b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);
2984b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2985b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2986b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2987b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeSmhdBox() {
2988b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("smhd");
2989b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // version=0, flags=0
2990b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // balance
2991b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2992b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2993b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2994b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2995b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeHdlrBox() {
2996b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("hdlr");
2997b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // version=0, flags=0
2998b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // component type: should be mhlr
2999b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeFourcc(mIsAudio ? "soun" : "vide");  // component subtype
3000b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3001b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3002b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3003b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Removing "r" for the name string just makes the string 4 byte aligned
3004b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle");  // name
3005b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3006b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3007b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3008efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeMdhdBox(uint32_t now) {
3009b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int64_t trakDurationUs = getDurationUs();
3010b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("mdhd");
3011b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // version=0, flags=0
3012b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // creation time
3013b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // modification time
3014b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(mTimeScale);    // media timescale
3015b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6;
3016b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(mdhdDuration);  // use media timescale
3017b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Language follows the three letter standard ISO-639-2/T
3018b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // 'e', 'n', 'g' for "English", for instance.
3019b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Each character is packed as the difference between its ASCII value and 0x60.
3020b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // For "English", these are 00101, 01110, 00111.
3021b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // XXX: Where is the padding bit located: 0x15C7?
3022b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // language code
3023b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // predefined
3024b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3025b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3026b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3027b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDamrBox() {
3028b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // 3gpp2 Spec AMRSampleEntry fields
3029b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("damr");
3030b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCString("   ");  // vendor: 4 bytes
3031b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);         // decoder version
3032b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x83FF);   // mode set: all enabled
3033b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);         // mode change period
3034b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(1);         // frames per sample
3035b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3036b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3037b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3038b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeUrlBox() {
3039b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // The table index here refers to the sample description index
3040b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // in the sample table entries.
3041b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("url ");
3042b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);  // version=0, flags=1 (self-contained)
3043b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // url
3044b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3045b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3046b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDrefBox() {
3047b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("dref");
3048b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3049b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);  // entry count (either url or urn)
3050b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeUrlBox();
3051b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // dref
3052b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3053b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3054b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDinfBox() {
3055b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("dinf");
3056b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeDrefBox();
3057b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // dinf
3058b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3059b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3060b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAvccBox() {
3061b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
306243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GE(mCodecSpecificDataSize, 5);
3063b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3064b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Patch avcc's lengthSize field to match the number
3065b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // of bytes we use to indicate the size of a nal unit.
3066b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    uint8_t *ptr = (uint8_t *)mCodecSpecificData;
3067b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    ptr[4] = (ptr[4] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1);
3068b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("avcC");
3069b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
3070b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // avcC
3071b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3072b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3073b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeD263Box() {
3074b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("d263");
3075b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // vendor
3076b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);   // decoder version
3077b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(10);  // level: 10
3078b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);   // profile: 0
3079b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // d263
3080b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3081b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3082b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong// This is useful if the pixel is not square
3083b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writePaspBox() {
3084b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("pasp");
3085b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1 << 16);  // hspacing
3086b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1 << 16);  // vspacing
3087b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // pasp
3088b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3089b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3090000e18370baae60ffd9f25b509501dd8c26deabfJames Dongint32_t MPEG4Writer::Track::getStartTimeOffsetScaledTime() const {
3091a472613aec322e25891abf5c77bf3f7e3c244920James Dong    int64_t trackStartTimeOffsetUs = 0;
3092b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
3093b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mStartTimestampUs != moovStartTimeUs) {
309443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_GT(mStartTimestampUs, moovStartTimeUs);
3095b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        trackStartTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
3096b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3097000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    return (trackStartTimeOffsetUs *  mTimeScale + 500000LL) / 1000000LL;
3098000e18370baae60ffd9f25b509501dd8c26deabfJames Dong}
3099000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
3100000e18370baae60ffd9f25b509501dd8c26deabfJames Dongvoid MPEG4Writer::Track::writeSttsBox() {
3101000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->beginBox("stts");
3102000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3103c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t duration;
3104c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    CHECK(mSttsTableEntries->get(duration, 1));
3105c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    duration = htonl(duration);  // Back to host byte order
3106c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime()), 1);
3107c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->write(mOwner);
3108b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stts
3109b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
311020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3111965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::writeCttsBox() {
3112965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    if (mIsAudio) {  // ctts is not for audio
3113965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
3114965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
3115965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
3116000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    // There is no B frame at all
3117000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    if (mMinCttsOffsetTimeUs == mMaxCttsOffsetTimeUs) {
3118000e18370baae60ffd9f25b509501dd8c26deabfJames Dong        return;
3119000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    }
3120000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
3121965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    // Do not write ctts box when there is no need to have it.
3122c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mCttsTableEntries->count() == 0) {
3123965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
3124965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
3125965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
3126a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("ctts box has %d entries with range [%" PRId64 ", %" PRId64 "]",
3127c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mCttsTableEntries->count(), mMinCttsOffsetTimeUs, mMaxCttsOffsetTimeUs);
3128965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
3129965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mOwner->beginBox("ctts");
3130000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3131c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t duration;
3132c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    CHECK(mCttsTableEntries->get(duration, 1));
3133c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    duration = htonl(duration);  // Back host byte order
3134c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime() - mMinCttsOffsetTimeUs), 1);
3135c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->write(mOwner);
3136965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mOwner->endBox();  // ctts
3137965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong}
3138965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
3139b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStssBox() {
3140b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stss");
3141b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3142c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries->write(mOwner);
3143b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stss
3144b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
314525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
3146b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStszBox() {
3147b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsz");
3148b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3149c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mOwner->writeInt32(0);
3150c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStszTableEntries->write(mOwner);
3151b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsz
3152b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
315320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3154b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStscBox() {
3155b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsc");
3156b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3157c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStscTableEntries->write(mOwner);
3158b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsc
3159b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
316020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3161b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) {
3162b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox(use32BitOffset? "stco": "co64");
3163b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3164c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (use32BitOffset) {
3165c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStcoTableEntries->write(mOwner);
3166c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    } else {
3167c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mCo64TableEntries->write(mOwner);
3168b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3169b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stco or co64
317020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
317120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
317207b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeUdtaBox() {
317307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    beginBox("udta");
317407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeGeoDataBox();
317507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    endBox();
317607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
317707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
3178e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeHdlr() {
3179e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("hdlr");
3180e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Version, Flags
3181e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Predefined
3182e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeFourcc("mdta");
3183e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Reserved[0]
3184e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Reserved[1]
3185e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Reserved[2]
3186e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt8(0);  // Name (empty)
3187e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox();
3188e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3189e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3190e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeKeys() {
3191e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    size_t count = mMetaKeys->countEntries();
3192e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3193e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("keys");
3194e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0);     // Version, Flags
3195e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(count); // Entry_count
3196e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    for (size_t i = 0; i < count; i++) {
3197e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        AMessage::Type type;
3198e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        const char *key = mMetaKeys->getEntryNameAt(i, &type);
3199e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        size_t n = strlen(key);
3200e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        writeInt32(n + 8);
3201e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        writeFourcc("mdta");
3202e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        write(key, n); // write without the \0
3203e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
3204e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox();
3205e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3206e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3207e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeIlst() {
3208e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    size_t count = mMetaKeys->countEntries();
3209e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3210e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("ilst");
3211e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    for (size_t i = 0; i < count; i++) {
3212e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        beginBox(i + 1); // key id (1-based)
3213e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        beginBox("data");
3214e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        AMessage::Type type;
3215e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        const char *key = mMetaKeys->getEntryNameAt(i, &type);
3216e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        switch (type) {
32177c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            case AMessage::kTypeString:
32187c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            {
32197c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                AString val;
32207c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                CHECK(mMetaKeys->findString(key, &val));
32217c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(1); // type = UTF8
32227c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0); // default country/language
32237c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                write(val.c_str(), strlen(val.c_str())); // write without \0
32247c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                break;
32257c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            }
32267c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
3227e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            case AMessage::kTypeFloat:
3228e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            {
3229e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                float val;
3230e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                CHECK(mMetaKeys->findFloat(key, &val));
32317c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(23); // type = float32
32327c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0);  // default country/language
3233e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                writeInt32(*reinterpret_cast<int32_t *>(&val));
3234e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                break;
3235e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            }
3236e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3237e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            case AMessage::kTypeInt32:
3238e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            {
3239e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                int32_t val;
3240e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                CHECK(mMetaKeys->findInt32(key, &val));
32417c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(67); // type = signed int32
32427c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0);  // default country/language
3243e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                writeInt32(val);
3244e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                break;
3245e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            }
3246e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3247e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            default:
3248e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            {
3249e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                ALOGW("Unsupported key type, writing 0 instead");
32507c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(77); // type = unsigned int32
32517c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0);  // default country/language
3252e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                writeInt32(0);
3253e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                break;
3254e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            }
3255e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        }
3256e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        endBox(); // data
3257e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        endBox(); // key id
3258e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
3259e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox(); // ilst
3260e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3261e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3262e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeMetaBox() {
3263e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    size_t count = mMetaKeys->countEntries();
3264e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    if (count == 0) {
3265e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        return;
3266e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
3267e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3268e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("meta");
3269e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeHdlr();
3270e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeKeys();
3271e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeIlst();
3272e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox();
3273e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3274e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
327507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/*
327607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard.
327707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */
327807b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeGeoDataBox() {
327907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    beginBox("\xA9xyz");
328007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    /*
328107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * For historical reasons, any user data start
328207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * with "\0xA9", must be followed by its assoicated
328307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * language code.
3284432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong     * 0x0012: text string length
3285432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong     * 0x15c7: lang (locale) code: en
328607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     */
328707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeInt32(0x001215c7);
328807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeLatitude(mLatitudex10000);
328907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeLongitude(mLongitudex10000);
329007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeInt8(0x2F);
329107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    endBox();
329207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
329307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
329420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
3295