MPEG4Writer.cpp revision e502b443ce9d229d1e9108834887c6e520948816
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);
116c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
117c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
118c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Free the allocated memory.
119c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        ~ListTableEntries() {
120c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            while (!mTableEntryList.empty()) {
121c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                typename List<TYPE *>::iterator it = mTableEntryList.begin();
122c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                delete[] (*it);
123c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mTableEntryList.erase(it);
124c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
125c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
126c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
127c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Replace the value at the given position by the given value.
128c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // There must be an existing value at the given position.
129c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg value must be in network byte order
130c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg pos location the value must be in.
131c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        void set(const TYPE& value, uint32_t pos) {
13225f0d7ba1987de61c75f8c68b19de48e0ad9736cJames Dong            CHECK_LT(pos, mTotalNumTableEntries * mEntryCapacity);
133c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
134c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            typename List<TYPE *>::iterator it = mTableEntryList.begin();
135c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t iterations = (pos / (mElementCapacity * mEntryCapacity));
136c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            while (it != mTableEntryList.end() && iterations > 0) {
137c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                ++it;
138c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                --iterations;
139c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
140c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK(it != mTableEntryList.end());
141c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_EQ(iterations, 0);
142c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
143c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            (*it)[(pos % (mElementCapacity * mEntryCapacity))] = value;
144c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
145c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
146c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Get the value at the given position by the given value.
147c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg value the retrieved value at the position in network byte order.
148c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg pos location the value must be in.
149c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @return true if a value is found.
150c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        bool get(TYPE& value, uint32_t pos) const {
15125f0d7ba1987de61c75f8c68b19de48e0ad9736cJames Dong            if (pos >= mTotalNumTableEntries * mEntryCapacity) {
152c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                return false;
153c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
154c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
155c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            typename List<TYPE *>::iterator it = mTableEntryList.begin();
156c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t iterations = (pos / (mElementCapacity * mEntryCapacity));
157c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            while (it != mTableEntryList.end() && iterations > 0) {
158c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                ++it;
159c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                --iterations;
160c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
161c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK(it != mTableEntryList.end());
162c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_EQ(iterations, 0);
163c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
164c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            value = (*it)[(pos % (mElementCapacity * mEntryCapacity))];
165c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            return true;
166c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
167c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
168c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Store a single value.
169c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg value must be in network byte order.
170c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        void add(const TYPE& value) {
171c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_LT(mNumValuesInCurrEntry, mElementCapacity);
172c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t nEntries = mTotalNumTableEntries % mElementCapacity;
173c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t nValues  = mNumValuesInCurrEntry % mEntryCapacity;
174c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (nEntries == 0 && nValues == 0) {
175c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mCurrTableEntriesElement = new TYPE[mEntryCapacity * mElementCapacity];
176c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                CHECK(mCurrTableEntriesElement != NULL);
177c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mTableEntryList.push_back(mCurrTableEntriesElement);
178c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
179c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
180c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t pos = nEntries * mEntryCapacity + nValues;
181c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mCurrTableEntriesElement[pos] = value;
182c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
183c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            ++mNumValuesInCurrEntry;
184c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if ((mNumValuesInCurrEntry % mEntryCapacity) == 0) {
185c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                ++mTotalNumTableEntries;
186c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mNumValuesInCurrEntry = 0;
187c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
188c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
189c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
190c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Write out the table entries:
191c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // 1. the number of entries goes first
192c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // 2. followed by the values in the table enties in order
193c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg writer the writer to actual write to the storage
194c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        void write(MPEG4Writer *writer) const {
195c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_EQ(mNumValuesInCurrEntry % mEntryCapacity, 0);
196c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t nEntries = mTotalNumTableEntries;
197c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            writer->writeInt32(nEntries);
198c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            for (typename List<TYPE *>::iterator it = mTableEntryList.begin();
199c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                it != mTableEntryList.end(); ++it) {
200c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                CHECK_GT(nEntries, 0);
201c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                if (nEntries >= mElementCapacity) {
202c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    writer->write(*it, sizeof(TYPE) * mEntryCapacity, mElementCapacity);
203c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    nEntries -= mElementCapacity;
204c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                } else {
205c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    writer->write(*it, sizeof(TYPE) * mEntryCapacity, nEntries);
206c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    break;
207c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                }
208c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
209c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
210c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
211c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Return the number of entries in the table.
212c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t count() const { return mTotalNumTableEntries; }
213c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
214c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    private:
215c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t         mElementCapacity;  // # entries in an element
216c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t         mEntryCapacity;    // # of values in each entry
217c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t         mTotalNumTableEntries;
218c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t         mNumValuesInCurrEntry;  // up to mEntryCapacity
219c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        TYPE             *mCurrTableEntriesElement;
220c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mutable List<TYPE *>     mTableEntryList;
221c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
222c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        DISALLOW_EVIL_CONSTRUCTORS(ListTableEntries);
223c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    };
224c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
225c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
226c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
22720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Writer *mOwner;
22820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MetaData> mMeta;
229693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    sp<MediaSource> mSource;
23020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    volatile bool mDone;
231a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mPaused;
232a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mResumed;
233eaae38445a340c4857c1c5569475879a728e63b7James Dong    volatile bool mStarted;
2341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAvc;
2351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAudio;
2361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsMPEG4;
237bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    int32_t mTrackId;
238c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    int64_t mTrackDurationUs;
23943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    int64_t mMaxChunkDurationUs;
240e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
241d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t mEstimatedTrackSizeBytes;
2421f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    int64_t mMdatSizeBytes;
2438f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int32_t mTimeScale;
24420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
24520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_t mThread;
24620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
247be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
24813aec890216948b0c364f8f92792129d0335f506James Dong    List<MediaBuffer *> mChunkSamples;
2491f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
250c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    bool                mSamplesHaveSameSize;
251c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mStszTableEntries;
252be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
253c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mStcoTableEntries;
254c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<off64_t> *mCo64TableEntries;
255c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mStscTableEntries;
256c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mStssTableEntries;
257c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mSttsTableEntries;
258c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mCttsTableEntries;
259965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
260000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t mMinCttsOffsetTimeUs;
261000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t mMaxCttsOffsetTimeUs;
262965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Sequence parameter set or picture parameter set
2643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    struct AVCParamSet {
2653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        AVCParamSet(uint16_t length, const uint8_t *data)
2663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            : mLength(length), mData(data) {}
2673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
2683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t mLength;
2693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *mData;
2703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    };
2713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    List<AVCParamSet> mSeqParamSets;
2723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    List<AVCParamSet> mPicParamSets;
2733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mProfileIdc;
2743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mProfileCompatible;
2753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mLevelIdc;
2763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
27720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *mCodecSpecificData;
27820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t mCodecSpecificDataSize;
279548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    bool mGotAllCodecSpecificData;
28093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    bool mTrackingProgressStatus;
28120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
28225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool mReachedEOS;
2833c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    int64_t mStartTimestampUs;
28470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int64_t mStartTimeRealUs;
28570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int64_t mFirstSampleTimeRealUs;
28693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mPreviousTrackTimeUs;
28793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mTrackEveryTimeDurationUs;
28825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
289872a481558350634a3fd5cb67939de288af00ecbJames Dong    // Update the audio track's drift information.
290872a481558350634a3fd5cb67939de288af00ecbJames Dong    void updateDriftTime(const sp<MetaData>& meta);
291872a481558350634a3fd5cb67939de288af00ecbJames Dong
292000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int32_t getStartTimeOffsetScaledTime() const;
293000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
29420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    static void *ThreadWrapper(void *me);
29537187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t threadEntry();
29620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *parseParamSet(
2983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen);
2993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
300b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t makeAVCCodecSpecificData(const uint8_t *data, size_t size);
301b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t copyAVCCodecSpecificData(const uint8_t *data, size_t size);
302b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t parseAVCCodecSpecificData(const uint8_t *data, size_t size);
303215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong
304215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    // Track authoring progress status
305faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    void trackProgressStatus(int64_t timeUs, status_t err = OK);
30693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    void initTrackingProgressStatus(MetaData *params);
30703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
30819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    void getCodecSpecificDataFromInputFormatIfPossible();
30919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
310c059860c73678a202bfa33062723e8f82fb779d9James Dong    // Determine the track time scale
311c059860c73678a202bfa33062723e8f82fb779d9James Dong    // If it is an audio track, try to use the sampling rate as
312c059860c73678a202bfa33062723e8f82fb779d9James Dong    // the time scale; however, if user chooses the overwrite
313c059860c73678a202bfa33062723e8f82fb779d9James Dong    // value, the user-supplied time scale will be used.
314c059860c73678a202bfa33062723e8f82fb779d9James Dong    void setTimeScale();
315c059860c73678a202bfa33062723e8f82fb779d9James Dong
316690f546b0ee548dbfe997df36418e5302ec2d786James Dong    // Simple validation on the codec specific data
317690f546b0ee548dbfe997df36418e5302ec2d786James Dong    status_t checkCodecSpecificData() const;
31813f6284305e4b27395a23db7882d670bdb1bcae1James Dong    int32_t mRotation;
319690f546b0ee548dbfe997df36418e5302ec2d786James Dong
3201f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void updateTrackSizeEstimate();
3211f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void addOneStscTableEntry(size_t chunkId, size_t sampleId);
3221f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void addOneStssTableEntry(size_t sampleId);
32379761ab096f57c3027fad9556c2bc436672d614eJames Dong
32479761ab096f57c3027fad9556c2bc436672d614eJames Dong    // Duration is time scale based
32579761ab096f57c3027fad9556c2bc436672d614eJames Dong    void addOneSttsTableEntry(size_t sampleCount, int32_t timescaledDur);
326965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    void addOneCttsTableEntry(size_t sampleCount, int32_t timescaledDur);
32745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
32845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    bool isTrackMalFormed() const;
32943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    void sendTrackSummary(bool hasMultipleTracks);
3301f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
331b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Write the boxes
332b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStcoBox(bool use32BitOffset);
333b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStscBox();
334b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStszBox();
335b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStssBox();
336b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeSttsBox();
337965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    void writeCttsBox();
338b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeD263Box();
339b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writePaspBox();
340b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeAvccBox();
341b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeUrlBox();
342b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDrefBox();
343b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDinfBox();
344b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDamrBox();
345efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    void writeMdhdBox(uint32_t now);
346b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeSmhdBox();
347b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeVmhdBox();
348b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeHdlrBox();
349efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    void writeTkhdBox(uint32_t now);
350b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeMp4aEsdsBox();
351b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeMp4vEsdsBox();
352b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeAudioFourCCBox();
353b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeVideoFourCCBox();
354b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStblBox(bool use32BitOffset);
355b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
35620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track(const Track &);
35720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track &operator=(const Track &);
35820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
35920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
36030ab66297501757d745b9ae10da61adcd891f497Andreas HuberMPEG4Writer::MPEG4Writer(int fd)
361674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    : mFd(dup(fd)),
362674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong      mInitCheck(mFd < 0? NO_INIT: OK),
363de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui      mIsRealTimeRecording(true),
364b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong      mUse4ByteNalLength(true),
3651acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong      mUse32BitOffset(true),
366a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong      mIsFileSizeLimitExplicitlyRequested(false),
367a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
368a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mStarted(false),
369411ba422e3635d534928ffd81abf54f4f291c739James Dong      mWriterThreadStarted(false),
37030ab66297501757d745b9ae10da61adcd891f497Andreas Huber      mOffset(0),
37113aec890216948b0c364f8f92792129d0335f506James Dong      mMdatOffset(0),
372e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mMoovBoxBuffer(NULL),
373e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mMoovBoxBufferOffset(0),
374e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mWriteMoovBoxToMemory(false),
375e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mFreeBoxOffset(0),
376e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mStreamableFile(false),
3777837c17063a4c50bc856ba59418516fdab731de7James Dong      mEstimatedMoovBoxSize(0),
3787c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang      mMoovExtraSize(0),
37907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mInterleaveDurationUs(1000000),
380e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mTimeScale(-1),
381e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mStartTimestampUs(-1ll),
38207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mLatitudex10000(0),
38307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mLongitudex10000(0),
38486b7f47aa7482424cf8fd248f1315311919be3b0James Dong      mAreGeoTagsAvailable(false),
385ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar      mStartTimeOffsetMs(-1),
386ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar      mMetaKeys(new AMessage()) {
3877c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    addDeviceMeta();
38830ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
38930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
39020111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() {
3918bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dong    reset();
39220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3931f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    while (!mTracks.empty()) {
3941f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        List<Track *>::iterator it = mTracks.begin();
39520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        delete *it;
3961f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        (*it) = NULL;
3971f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mTracks.erase(it);
39820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
39920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.clear();
40020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
40120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
402dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::dump(
403dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        int fd, const Vector<String16>& args) {
404dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    const size_t SIZE = 256;
405dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    char buffer[SIZE];
406dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    String8 result;
407dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "   MPEG4Writer %p\n", this);
408dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
409dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "     mStarted: %s\n", mStarted? "true": "false");
410dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
411dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    ::write(fd, result.string(), result.size());
412dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    for (List<Track *>::iterator it = mTracks.begin();
413dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong         it != mTracks.end(); ++it) {
414dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        (*it)->dump(fd, args);
415dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    }
416dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    return OK;
417dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong}
418dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong
419dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::Track::dump(
42084333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        int fd, const Vector<String16>& /* args */) const {
421dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    const size_t SIZE = 256;
422dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    char buffer[SIZE];
423dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    String8 result;
424dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "     %s track\n", mIsAudio? "Audio": "Video");
425dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
426dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "       reached EOS: %s\n",
427dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong            mReachedEOS? "true": "false");
428dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
429c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    snprintf(buffer, SIZE, "       frames encoded : %d\n", mStszTableEntries->count());
43013210f3346462a86ce9fe3af72a0c200dba84e27James Dong    result.append(buffer);
431377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    snprintf(buffer, SIZE, "       duration encoded : %" PRId64 " us\n", mTrackDurationUs);
43213210f3346462a86ce9fe3af72a0c200dba84e27James Dong    result.append(buffer);
433dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    ::write(fd, result.string(), result.size());
434dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    return OK;
435dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong}
436dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong
4378b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan// static
4388b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavanconst char *MPEG4Writer::Track::getFourCCForMime(const char *mime) {
4398b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (mime == NULL) {
4408b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        return NULL;
4418b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    }
4428b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (!strncasecmp(mime, "audio/", 6)) {
4438b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) {
4448b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "samr";
4458b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
4468b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "sawb";
4478b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
4488b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "mp4a";
4498b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        }
4508b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    } else if (!strncasecmp(mime, "video/", 6)) {
4518b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
4528b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "mp4v";
4538b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
4548b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "s263";
4558b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
4568b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "avc1";
4578b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        }
4588b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    } else {
4598b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        ALOGE("Track (%s) other than video or audio is not supported", mime);
4608b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    }
4618b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    return NULL;
4628b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan}
4638b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan
4642dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huberstatus_t MPEG4Writer::addSource(const sp<MediaSource> &source) {
465bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    Mutex::Autolock l(mLock);
466bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    if (mStarted) {
46729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Attempt to add source AFTER recording is started");
468bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        return UNKNOWN_ERROR;
469bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    }
470acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
471acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // At most 2 tracks can be supported.
472acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    if (mTracks.size() >= 2) {
473a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGE("Too many tracks (%zu) to add", mTracks.size());
474acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        return ERROR_UNSUPPORTED;
475acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    }
476acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
477acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    CHECK(source.get() != NULL);
478acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
479acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    const char *mime;
480acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    source->getFormat()->findCString(kKeyMIMEType, &mime);
481acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    bool isAudio = !strncasecmp(mime, "audio/", 6);
4828b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (Track::getFourCCForMime(mime) == NULL) {
4838b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        ALOGE("Unsupported mime '%s'", mime);
484acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        return ERROR_UNSUPPORTED;
485acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    }
486acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
487acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // At this point, we know the track to be added is either
488acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // video or audio. Thus, we only need to check whether it
489acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // is an audio track or not (if it is not, then it must be
490acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // a video track).
491acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
492acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // No more than one video or one audio track is supported.
493acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    for (List<Track*>::iterator it = mTracks.begin();
494acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong         it != mTracks.end(); ++it) {
495acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        if ((*it)->isAudio() == isAudio) {
496acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong            ALOGE("%s track already exists", isAudio? "Audio": "Video");
497acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong            return ERROR_UNSUPPORTED;
498acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        }
499acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    }
500acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
501acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // This is the first track of either audio or video.
502acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // Go ahead to add the track.
503219f195159f93d627af2b243732e3f9020511a46James Dong    Track *track = new Track(this, source, 1 + mTracks.size());
50420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.push_back(track);
5052dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
5062dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    return OK;
50720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
50820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
50993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::startTracks(MetaData *params) {
510acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    if (mTracks.empty()) {
511acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        ALOGE("No source added");
512acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        return INVALID_OPERATION;
513acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    }
514acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
515a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
516a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
51793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        status_t err = (*it)->start(params);
518a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
519a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (err != OK) {
520a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            for (List<Track *>::iterator it2 = mTracks.begin();
521a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                 it2 != it; ++it2) {
522a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                (*it2)->stop();
523a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            }
524a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
525a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            return err;
526a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
527a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
528a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    return OK;
529a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
530a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
5317c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangvoid MPEG4Writer::addDeviceMeta() {
5327c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // add device info and estimate space in 'moov'
5337c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    char val[PROPERTY_VALUE_MAX];
5347c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    size_t n;
5357c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // meta size is estimated by adding up the following:
5367c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // - meta header structures, which occur only once (total 66 bytes)
5377c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // - size for each key, which consists of a fixed header (32 bytes),
5387c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    //   plus key length and data length.
5397c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMoovExtraSize += 66;
5407c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    if (property_get("ro.build.version.release", val, NULL)
5417c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            && (n = strlen(val)) > 0) {
5427c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMetaKeys->setString(kMetaKey_Version, val, n + 1);
5437c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMoovExtraSize += sizeof(kMetaKey_Version) + n + 32;
5447c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    }
5457c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang#ifdef SHOW_MODEL_BUILD
5467c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    if (property_get("ro.product.model", val, NULL)
5477c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            && (n = strlen(val)) > 0) {
5487c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMetaKeys->setString(kMetaKey_Model, val, n + 1);
5497c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMoovExtraSize += sizeof(kMetaKey_Model) + n + 32;
5507c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    }
5517c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    if (property_get("ro.build.display.id", val, NULL)
5527c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            && (n = strlen(val)) > 0) {
5537c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMetaKeys->setString(kMetaKey_Build, val, n + 1);
5547c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMoovExtraSize += sizeof(kMetaKey_Build) + n + 32;
5557c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    }
5567c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang#endif
5577c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang}
5587c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
5592dec2b5be2056c6d9428897dc672185872d30d17James Dongint64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) {
5602dec2b5be2056c6d9428897dc672185872d30d17James Dong    // This implementation is highly experimental/heurisitic.
5612dec2b5be2056c6d9428897dc672185872d30d17James Dong    //
5622dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Statistical analysis shows that metadata usually accounts
5632dec2b5be2056c6d9428897dc672185872d30d17James Dong    // for a small portion of the total file size, usually < 0.6%.
5642dec2b5be2056c6d9428897dc672185872d30d17James Dong
56578a1a286f736888ae7af8860b2c424af0d978848James Dong    // The default MIN_MOOV_BOX_SIZE is set to 0.6% x 1MB / 2,
5662dec2b5be2056c6d9428897dc672185872d30d17James Dong    // where 1MB is the common file size limit for MMS application.
56778a1a286f736888ae7af8860b2c424af0d978848James Dong    // The default MAX _MOOV_BOX_SIZE value is based on about 3
5682dec2b5be2056c6d9428897dc672185872d30d17James Dong    // minute video recording with a bit rate about 3 Mbps, because
5692dec2b5be2056c6d9428897dc672185872d30d17James Dong    // statistics also show that most of the video captured are going
5702dec2b5be2056c6d9428897dc672185872d30d17James Dong    // to be less than 3 minutes.
5712dec2b5be2056c6d9428897dc672185872d30d17James Dong
5722dec2b5be2056c6d9428897dc672185872d30d17James Dong    // If the estimation is wrong, we will pay the price of wasting
5732dec2b5be2056c6d9428897dc672185872d30d17James Dong    // some reserved space. This should not happen so often statistically.
5742dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int32_t factor = mUse32BitOffset? 1: 2;
57578a1a286f736888ae7af8860b2c424af0d978848James Dong    static const int64_t MIN_MOOV_BOX_SIZE = 3 * 1024;  // 3 KB
5762dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000);
5772dec2b5be2056c6d9428897dc672185872d30d17James Dong    int64_t size = MIN_MOOV_BOX_SIZE;
5782dec2b5be2056c6d9428897dc672185872d30d17James Dong
57978a1a286f736888ae7af8860b2c424af0d978848James Dong    // Max file size limit is set
580a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
58178a1a286f736888ae7af8860b2c424af0d978848James Dong        size = mMaxFileSizeLimitBytes * 6 / 1000;
58278a1a286f736888ae7af8860b2c424af0d978848James Dong    }
58378a1a286f736888ae7af8860b2c424af0d978848James Dong
58478a1a286f736888ae7af8860b2c424af0d978848James Dong    // Max file duration limit is set
58578a1a286f736888ae7af8860b2c424af0d978848James Dong    if (mMaxFileDurationLimitUs != 0) {
58678a1a286f736888ae7af8860b2c424af0d978848James Dong        if (bitRate > 0) {
58778a1a286f736888ae7af8860b2c424af0d978848James Dong            int64_t size2 =
58878a1a286f736888ae7af8860b2c424af0d978848James Dong                ((mMaxFileDurationLimitUs * bitRate * 6) / 1000 / 8000000);
58978a1a286f736888ae7af8860b2c424af0d978848James Dong            if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
59078a1a286f736888ae7af8860b2c424af0d978848James Dong                // When both file size and duration limits are set,
59178a1a286f736888ae7af8860b2c424af0d978848James Dong                // we use the smaller limit of the two.
59278a1a286f736888ae7af8860b2c424af0d978848James Dong                if (size > size2) {
59378a1a286f736888ae7af8860b2c424af0d978848James Dong                    size = size2;
59478a1a286f736888ae7af8860b2c424af0d978848James Dong                }
59578a1a286f736888ae7af8860b2c424af0d978848James Dong            } else {
59678a1a286f736888ae7af8860b2c424af0d978848James Dong                // Only max file duration limit is set
59778a1a286f736888ae7af8860b2c424af0d978848James Dong                size = size2;
59878a1a286f736888ae7af8860b2c424af0d978848James Dong            }
5992dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
6002dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
60178a1a286f736888ae7af8860b2c424af0d978848James Dong
6022dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size < MIN_MOOV_BOX_SIZE) {
6032dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MIN_MOOV_BOX_SIZE;
6042dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
6052dec2b5be2056c6d9428897dc672185872d30d17James Dong
6062dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Any long duration recording will be probably end up with
6072dec2b5be2056c6d9428897dc672185872d30d17James Dong    // non-streamable mp4 file.
6082dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size > MAX_MOOV_BOX_SIZE) {
6092dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MAX_MOOV_BOX_SIZE;
6102dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
6112dec2b5be2056c6d9428897dc672185872d30d17James Dong
6127c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // Account for the extra stuff (Geo, meta keys, etc.)
6137c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    size += mMoovExtraSize;
6147c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
615a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGI("limits: %" PRId64 "/%" PRId64 " bytes/us, bit rate: %d bps and the"
616a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn         " estimated moov size %" PRId64 " bytes",
6172dec2b5be2056c6d9428897dc672185872d30d17James Dong         mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size);
6182dec2b5be2056c6d9428897dc672185872d30d17James Dong    return factor * size;
6192dec2b5be2056c6d9428897dc672185872d30d17James Dong}
6202dec2b5be2056c6d9428897dc672185872d30d17James Dong
6212dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t MPEG4Writer::start(MetaData *param) {
622674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
62325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return UNKNOWN_ERROR;
62420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
62520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
626a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    /*
627a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * Check mMaxFileSizeLimitBytes at the beginning
628a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * since mMaxFileSizeLimitBytes may be implicitly
629a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * changed later for 32-bit file offset even if
630a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * user does not ask to set it explicitly.
631a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     */
632a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    if (mMaxFileSizeLimitBytes != 0) {
633a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong        mIsFileSizeLimitExplicitlyRequested = true;
634a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    }
635a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong
6362dec2b5be2056c6d9428897dc672185872d30d17James Dong    int32_t use64BitOffset;
6372dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (param &&
6382dec2b5be2056c6d9428897dc672185872d30d17James Dong        param->findInt32(kKey64BitFileOffset, &use64BitOffset) &&
6392dec2b5be2056c6d9428897dc672185872d30d17James Dong        use64BitOffset) {
6402dec2b5be2056c6d9428897dc672185872d30d17James Dong        mUse32BitOffset = false;
6412dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
6422dec2b5be2056c6d9428897dc672185872d30d17James Dong
6431f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    if (mUse32BitOffset) {
6441f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // Implicit 32 bit file size limit
6451f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        if (mMaxFileSizeLimitBytes == 0) {
6461f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            mMaxFileSizeLimitBytes = kMax32BitFileSize;
6471f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        }
6481f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
6491f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // If file size is set to be larger than the 32 bit file
6501f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // size limit, treat it as an error.
6511f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        if (mMaxFileSizeLimitBytes > kMax32BitFileSize) {
652a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGW("32-bit file size limit (%" PRId64 " bytes) too big. "
653a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn                 "It is changed to %" PRId64 " bytes",
654d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong                mMaxFileSizeLimitBytes, kMax32BitFileSize);
655d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong            mMaxFileSizeLimitBytes = kMax32BitFileSize;
6561f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        }
6571f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    }
6581f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
659b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    int32_t use2ByteNalLength;
660b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (param &&
661b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        param->findInt32(kKey2ByteNalLength, &use2ByteNalLength) &&
662b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        use2ByteNalLength) {
663b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mUse4ByteNalLength = false;
6642dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
6652dec2b5be2056c6d9428897dc672185872d30d17James Dong
666de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    int32_t isRealTimeRecording;
667de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    if (param && param->findInt32(kKeyRealTimeRecording, &isRealTimeRecording)) {
668de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        mIsRealTimeRecording = isRealTimeRecording;
669de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    }
670de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui
671065d1aff96818df54456053f1574aec8a234d0deJames Dong    mStartTimestampUs = -1;
67293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
673a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (mStarted) {
674a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused) {
675a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mPaused = false;
67693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            return startTracks(param);
677a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
678a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
679a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
680a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
6818f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    if (!param ||
6828f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        !param->findInt32(kKeyTimeScale, &mTimeScale)) {
6838f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        mTimeScale = 1000;
6848f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    }
68543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mTimeScale, 0);
6863856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("movie time scale: %d", mTimeScale);
6878f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
68877e8ae9967a078770416619e99ddb5b010def312James Dong    /*
68977e8ae9967a078770416619e99ddb5b010def312James Dong     * When the requested file size limit is small, the priority
69077e8ae9967a078770416619e99ddb5b010def312James Dong     * is to meet the file size limit requirement, rather than
6917b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * to make the file streamable. mStreamableFile does not tell
6927b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * whether the actual recorded file is streamable or not.
69377e8ae9967a078770416619e99ddb5b010def312James Dong     */
69477e8ae9967a078770416619e99ddb5b010def312James Dong    mStreamableFile =
69577e8ae9967a078770416619e99ddb5b010def312James Dong        (mMaxFileSizeLimitBytes != 0 &&
69677e8ae9967a078770416619e99ddb5b010def312James Dong         mMaxFileSizeLimitBytes >= kMinStreamableFileSizeInBytes);
69777e8ae9967a078770416619e99ddb5b010def312James Dong
6987b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    /*
6997b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * mWriteMoovBoxToMemory is true if the amount of data in moov box is
7007b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * smaller than the reserved free space at the beginning of a file, AND
7017b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * when the content of moov box is constructed. Note that video/audio
7027b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * frame data is always written to the file but not in the memory.
7037b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
7047b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * Before stop()/reset() is called, mWriteMoovBoxToMemory is always
7057b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * false. When reset() is called at the end of a recording session,
7067b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * Moov box needs to be constructed.
7077b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
7087b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * 1) Right before a moov box is constructed, mWriteMoovBoxToMemory
7097b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * to set to mStreamableFile so that if
7107b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * the file is intended to be streamable, it is set to true;
7117b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * otherwise, it is set to false. When the value is set to false,
7127b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * all the content of the moov box is written immediately to
7137b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * the end of the file. When the value is set to true, all the
7147b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * content of the moov box is written to an in-memory cache,
7157b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * mMoovBoxBuffer, util the following condition happens. Note
7167b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * that the size of the in-memory cache is the same as the
7177b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * reserved free space at the beginning of the file.
7187b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
7197b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * 2) While the data of the moov box is written to an in-memory
7207b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * cache, the data size is checked against the reserved space.
7217b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * If the data size surpasses the reserved space, subsequent moov
7227b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * data could no longer be hold in the in-memory cache. This also
7237b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * indicates that the reserved space was too small. At this point,
7247b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * _all_ moov data must be written to the end of the file.
7257b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * mWriteMoovBoxToMemory must be set to false to direct the write
7267b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * to the file.
7277b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
7287b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * 3) If the data size in moov box is smaller than the reserved
7297b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * space after moov box is completely constructed, the in-memory
7307b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * cache copy of the moov box is written to the reserved free
7317b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * space. Thus, immediately after the moov is completedly
7327b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * constructed, mWriteMoovBoxToMemory is always set to false.
7337b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     */
7347b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    mWriteMoovBoxToMemory = false;
7357837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBuffer = NULL;
7367837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
7377837c17063a4c50bc856ba59418516fdab731de7James Dong
738b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeFtypBox(param);
73920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7407837c17063a4c50bc856ba59418516fdab731de7James Dong    mFreeBoxOffset = mOffset;
74120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7427837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mEstimatedMoovBoxSize == 0) {
7432dec2b5be2056c6d9428897dc672185872d30d17James Dong        int32_t bitRate = -1;
7442dec2b5be2056c6d9428897dc672185872d30d17James Dong        if (param) {
7452dec2b5be2056c6d9428897dc672185872d30d17James Dong            param->findInt32(kKeyBitRate, &bitRate);
7462dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
7472dec2b5be2056c6d9428897dc672185872d30d17James Dong        mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate);
7487837c17063a4c50bc856ba59418516fdab731de7James Dong    }
74943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GE(mEstimatedMoovBoxSize, 8);
75077e8ae9967a078770416619e99ddb5b010def312James Dong    if (mStreamableFile) {
75177e8ae9967a078770416619e99ddb5b010def312James Dong        // Reserve a 'free' box only for streamable file
75277e8ae9967a078770416619e99ddb5b010def312James Dong        lseek64(mFd, mFreeBoxOffset, SEEK_SET);
75377e8ae9967a078770416619e99ddb5b010def312James Dong        writeInt32(mEstimatedMoovBoxSize);
75477e8ae9967a078770416619e99ddb5b010def312James Dong        write("free", 4);
75577e8ae9967a078770416619e99ddb5b010def312James Dong        mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize;
75677e8ae9967a078770416619e99ddb5b010def312James Dong    } else {
75777e8ae9967a078770416619e99ddb5b010def312James Dong        mMdatOffset = mOffset;
75877e8ae9967a078770416619e99ddb5b010def312James Dong    }
7597837c17063a4c50bc856ba59418516fdab731de7James Dong
7607837c17063a4c50bc856ba59418516fdab731de7James Dong    mOffset = mMdatOffset;
761c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    lseek64(mFd, mMdatOffset, SEEK_SET);
7621acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
7631acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("????mdat", 8);
7641acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
7651acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("\x00\x00\x00\x01mdat????????", 16);
7661acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
7671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
7681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    status_t err = startWriterThread();
7691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (err != OK) {
7701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        return err;
7711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
7721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
7731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    err = startTracks(param);
774a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (err != OK) {
775a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return err;
77620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
7771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
778a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mStarted = true;
77925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
78020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
78120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7821f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongbool MPEG4Writer::use32BitFileOffset() const {
7831f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    return mUse32BitOffset;
7841f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
7851f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
78637187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::pause() {
787674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
78837187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
789a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
790a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
79137187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = OK;
792a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
793a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
79437187916a486504acaf83bea30147eb5fbf46ae5James Dong        status_t status = (*it)->pause();
79537187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (status != OK) {
79637187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
79737187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
798a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
79937187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
800a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
801a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
8021c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::stopWriterThread() {
803b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("Stopping writer thread");
804411ba422e3635d534928ffd81abf54f4f291c739James Dong    if (!mWriterThreadStarted) {
805411ba422e3635d534928ffd81abf54f4f291c739James Dong        return;
806411ba422e3635d534928ffd81abf54f4f291c739James Dong    }
8071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    {
8091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        Mutex::Autolock autolock(mLock);
8101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mDone = true;
8121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkReadyCondition.signal();
8131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
8141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void *dummy;
8161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_join(mThread, &dummy);
817411ba422e3635d534928ffd81abf54f4f291c739James Dong    mWriterThreadStarted = false;
818b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("Writer thread stopped");
8191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
8201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
82113f6284305e4b27395a23db7882d670bdb1bcae1James Dong/*
82213f6284305e4b27395a23db7882d670bdb1bcae1James Dong * MP4 file standard defines a composition matrix:
82313f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | a  b  u |
82413f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | c  d  v |
82513f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | x  y  w |
82613f6284305e4b27395a23db7882d670bdb1bcae1James Dong *
82713f6284305e4b27395a23db7882d670bdb1bcae1James Dong * the element in the matrix is stored in the following
82813f6284305e4b27395a23db7882d670bdb1bcae1James Dong * order: {a, b, u, c, d, v, x, y, w},
82913f6284305e4b27395a23db7882d670bdb1bcae1James Dong * where a, b, c, d, x, and y is in 16.16 format, while
83013f6284305e4b27395a23db7882d670bdb1bcae1James Dong * u, v and w is in 2.30 format.
83113f6284305e4b27395a23db7882d670bdb1bcae1James Dong */
83213f6284305e4b27395a23db7882d670bdb1bcae1James Dongvoid MPEG4Writer::writeCompositionMatrix(int degrees) {
8333856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("writeCompositionMatrix");
83413f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t a = 0x00010000;
83513f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t b = 0;
83613f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t c = 0;
83713f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t d = 0x00010000;
83813f6284305e4b27395a23db7882d670bdb1bcae1James Dong    switch (degrees) {
83913f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 0:
84013f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
84113f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 90:
84213f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0;
84313f6284305e4b27395a23db7882d670bdb1bcae1James Dong            b = 0x00010000;
84413f6284305e4b27395a23db7882d670bdb1bcae1James Dong            c = 0xFFFF0000;
84513f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0;
84613f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
84713f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 180:
84813f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0xFFFF0000;
84913f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0xFFFF0000;
85013f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
85113f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 270:
85213f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0;
85313f6284305e4b27395a23db7882d670bdb1bcae1James Dong            b = 0xFFFF0000;
85413f6284305e4b27395a23db7882d670bdb1bcae1James Dong            c = 0x00010000;
85513f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0;
85613f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
85713f6284305e4b27395a23db7882d670bdb1bcae1James Dong        default:
85813f6284305e4b27395a23db7882d670bdb1bcae1James Dong            CHECK(!"Should never reach this unknown rotation");
85913f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
86013f6284305e4b27395a23db7882d670bdb1bcae1James Dong    }
86113f6284305e4b27395a23db7882d670bdb1bcae1James Dong
86213f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(a);           // a
86313f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(b);           // b
86413f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // u
86513f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(c);           // c
86613f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(d);           // d
86713f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // v
86813f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // x
86913f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // y
87013f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0x40000000);  // w
87113f6284305e4b27395a23db7882d670bdb1bcae1James Dong}
87213f6284305e4b27395a23db7882d670bdb1bcae1James Dong
873411ba422e3635d534928ffd81abf54f4f291c739James Dongvoid MPEG4Writer::release() {
874411ba422e3635d534928ffd81abf54f4f291c739James Dong    close(mFd);
875411ba422e3635d534928ffd81abf54f4f291c739James Dong    mFd = -1;
876411ba422e3635d534928ffd81abf54f4f291c739James Dong    mInitCheck = NO_INIT;
877411ba422e3635d534928ffd81abf54f4f291c739James Dong    mStarted = false;
8784c845fde3d60ad93984879f69b164e35536e080dSuresh Choudhary    free(mMoovBoxBuffer);
8794c845fde3d60ad93984879f69b164e35536e080dSuresh Choudhary    mMoovBoxBuffer = NULL;
880411ba422e3635d534928ffd81abf54f4f291c739James Dong}
88113f6284305e4b27395a23db7882d670bdb1bcae1James Dong
8828bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dongstatus_t MPEG4Writer::reset() {
883674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
88437187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
885411ba422e3635d534928ffd81abf54f4f291c739James Dong    } else {
886411ba422e3635d534928ffd81abf54f4f291c739James Dong        if (!mWriterThreadStarted ||
887411ba422e3635d534928ffd81abf54f4f291c739James Dong            !mStarted) {
888411ba422e3635d534928ffd81abf54f4f291c739James Dong            if (mWriterThreadStarted) {
889411ba422e3635d534928ffd81abf54f4f291c739James Dong                stopWriterThread();
890411ba422e3635d534928ffd81abf54f4f291c739James Dong            }
891411ba422e3635d534928ffd81abf54f4f291c739James Dong            release();
892411ba422e3635d534928ffd81abf54f4f291c739James Dong            return OK;
893411ba422e3635d534928ffd81abf54f4f291c739James Dong        }
89420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
89520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
89637187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = OK;
8978f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t maxDurationUs = 0;
89865b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    int64_t minDurationUs = 0x7fffffffffffffffLL;
89920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
90020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber         it != mTracks.end(); ++it) {
90137187916a486504acaf83bea30147eb5fbf46ae5James Dong        status_t status = (*it)->stop();
90237187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (err == OK && status != OK) {
90337187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
90437187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
90520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9068f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int64_t durationUs = (*it)->getDurationUs();
9078f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        if (durationUs > maxDurationUs) {
9088f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            maxDurationUs = durationUs;
90920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
91065b3d76025c71d755b0fb3b6ead90255f25417edJames Dong        if (durationUs < minDurationUs) {
91165b3d76025c71d755b0fb3b6ead90255f25417edJames Dong            minDurationUs = durationUs;
91265b3d76025c71d755b0fb3b6ead90255f25417edJames Dong        }
91365b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    }
91465b3d76025c71d755b0fb3b6ead90255f25417edJames Dong
91565b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    if (mTracks.size() > 1) {
916a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGD("Duration from tracks range is [%" PRId64 ", %" PRId64 "] us",
91765b3d76025c71d755b0fb3b6ead90255f25417edJames Dong            minDurationUs, maxDurationUs);
91820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
91920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    stopWriterThread();
9217837c17063a4c50bc856ba59418516fdab731de7James Dong
92237187916a486504acaf83bea30147eb5fbf46ae5James Dong    // Do not write out movie header on error.
92337187916a486504acaf83bea30147eb5fbf46ae5James Dong    if (err != OK) {
924411ba422e3635d534928ffd81abf54f4f291c739James Dong        release();
92537187916a486504acaf83bea30147eb5fbf46ae5James Dong        return err;
92637187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
92737187916a486504acaf83bea30147eb5fbf46ae5James Dong
92820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // Fix up the size of the 'mdat' chunk.
9291acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
930c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mMdatOffset, SEEK_SET);
9311f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad        uint32_t size = htonl(static_cast<uint32_t>(mOffset - mMdatOffset));
932c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &size, 4);
9331acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
934c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mMdatOffset + 8, SEEK_SET);
9351f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad        uint64_t size = mOffset - mMdatOffset;
9361acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        size = hton64(size);
937c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &size, 8);
9381acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
939c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    lseek64(mFd, mOffset, SEEK_SET);
94020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9417b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // Construct moov box now
9427837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
9437b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    mWriteMoovBoxToMemory = mStreamableFile;
9447b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    if (mWriteMoovBoxToMemory) {
9457b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // There is no need to allocate in-memory cache
9467b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // for moov box if the file is not streamable.
9477b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
9487b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize);
9497b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        CHECK(mMoovBoxBuffer != NULL);
9507b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    }
951b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeMoovBox(maxDurationUs);
95220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9537b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // mWriteMoovBoxToMemory could be set to false in
9547b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // MPEG4Writer::write() method
9557b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    if (mWriteMoovBoxToMemory) {
9567b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        mWriteMoovBoxToMemory = false;
9577b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // Content of the moov box is saved in the cache, and the in-memory
9587b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // moov box needs to be written to the file in a single shot.
9597b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
96043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_LE(mMoovBoxBufferOffset + 8, mEstimatedMoovBoxSize);
9617837c17063a4c50bc856ba59418516fdab731de7James Dong
9627837c17063a4c50bc856ba59418516fdab731de7James Dong        // Moov box
963c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mFreeBoxOffset, SEEK_SET);
9647837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset = mFreeBoxOffset;
965674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset);
9667837c17063a4c50bc856ba59418516fdab731de7James Dong
9677837c17063a4c50bc856ba59418516fdab731de7James Dong        // Free box
968c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mOffset, SEEK_SET);
9697837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset);
9707837c17063a4c50bc856ba59418516fdab731de7James Dong        write("free", 4);
9717b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    } else {
9727b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        ALOGI("The mp4 file will not be streamable.");
9737b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    }
9747837c17063a4c50bc856ba59418516fdab731de7James Dong
9757b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // Free in-memory cache for moov box
9767b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    if (mMoovBoxBuffer != NULL) {
9777837c17063a4c50bc856ba59418516fdab731de7James Dong        free(mMoovBoxBuffer);
9787837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBuffer = NULL;
9797837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBufferOffset = 0;
9807837c17063a4c50bc856ba59418516fdab731de7James Dong    }
9817837c17063a4c50bc856ba59418516fdab731de7James Dong
9820c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(mBoxes.empty());
98320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
984411ba422e3635d534928ffd81abf54f4f291c739James Dong    release();
98537187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
98620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
98720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
988efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonuint32_t MPEG4Writer::getMpeg4Time() {
989b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    time_t now = time(NULL);
990efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    // MP4 file uses time counting seconds since midnight, Jan. 1, 1904
991efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    // while time function returns Unix epoch values which starts
992efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    // at 1970-01-01. Lets add the number of seconds between them
993efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    uint32_t mpeg4Time = now + (66 * 365 + 17) * (24 * 60 * 60);
994efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    return mpeg4Time;
995efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson}
996efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson
997efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::writeMvhdBox(int64_t durationUs) {
998efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    uint32_t now = getMpeg4Time();
999b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("mvhd");
1000b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // version=0, flags=0
1001b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(now);           // creation time
1002b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(now);           // modification time
1003b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(mTimeScale);    // mvhd timescale
1004b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t duration = (durationUs * mTimeScale + 5E5) / 1E6;
1005b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(duration);
1006b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0x10000);       // rate: 1.0
1007b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt16(0x100);         // volume
1008b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt16(0);             // reserved
1009b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // reserved
1010b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // reserved
1011b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeCompositionMatrix(0); // matrix
1012b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1013b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1014b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1015b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1016b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1017b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1018b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(mTracks.size() + 1);  // nextTrackID
1019b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();  // mvhd
1020b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
1021b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
1022b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::writeMoovBox(int64_t durationUs) {
1023b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("moov");
1024b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeMvhdBox(durationUs);
102507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (mAreGeoTagsAvailable) {
102607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        writeUdtaBox();
102707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
1028e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeMetaBox();
1029b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t id = 1;
1030b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    for (List<Track *>::iterator it = mTracks.begin();
1031b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        it != mTracks.end(); ++it, ++id) {
1032b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        (*it)->writeTrackHeader(mUse32BitOffset);
1033b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
1034b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();  // moov
1035b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
1036b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
10372cf9c5073ca3342ee52673ad68763fadd2c2be79James Dongvoid MPEG4Writer::writeFtypBox(MetaData *param) {
1038b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("ftyp");
1039b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
1040b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t fileType;
1041b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (param && param->findInt32(kKeyFileType, &fileType) &&
1042b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        fileType != OUTPUT_FORMAT_MPEG_4) {
1043b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeFourcc("3gp4");
10448284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeInt32(0);
10458284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("isom");
10468284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("3gp4");
1047b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
10488284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("mp42");
10498284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeInt32(0);
1050b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeFourcc("isom");
10518284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("mp42");
1052b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
1053b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
1054b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();
1055b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
1056b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
105707ec01904613a0bac32caaa8444b4690998faed7James Dongstatic bool isTestModeEnabled() {
105807ec01904613a0bac32caaa8444b4690998faed7James Dong#if (PROPERTY_VALUE_MAX < 5)
105907ec01904613a0bac32caaa8444b4690998faed7James Dong#error "PROPERTY_VALUE_MAX must be at least 5"
106007ec01904613a0bac32caaa8444b4690998faed7James Dong#endif
106107ec01904613a0bac32caaa8444b4690998faed7James Dong
106207ec01904613a0bac32caaa8444b4690998faed7James Dong    // Test mode is enabled only if rw.media.record.test system
106307ec01904613a0bac32caaa8444b4690998faed7James Dong    // property is enabled.
106407ec01904613a0bac32caaa8444b4690998faed7James Dong    char value[PROPERTY_VALUE_MAX];
106507ec01904613a0bac32caaa8444b4690998faed7James Dong    if (property_get("rw.media.record.test", value, NULL) &&
106607ec01904613a0bac32caaa8444b4690998faed7James Dong        (!strcasecmp(value, "true") || !strcasecmp(value, "1"))) {
106707ec01904613a0bac32caaa8444b4690998faed7James Dong        return true;
106807ec01904613a0bac32caaa8444b4690998faed7James Dong    }
106907ec01904613a0bac32caaa8444b4690998faed7James Dong    return false;
107007ec01904613a0bac32caaa8444b4690998faed7James Dong}
107107ec01904613a0bac32caaa8444b4690998faed7James Dong
107270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongvoid MPEG4Writer::sendSessionSummary() {
107307ec01904613a0bac32caaa8444b4690998faed7James Dong    // Send session summary only if test mode is enabled
107407ec01904613a0bac32caaa8444b4690998faed7James Dong    if (!isTestModeEnabled()) {
107507ec01904613a0bac32caaa8444b4690998faed7James Dong        return;
107607ec01904613a0bac32caaa8444b4690998faed7James Dong    }
107707ec01904613a0bac32caaa8444b4690998faed7James Dong
107870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
107970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong         it != mChunkInfos.end(); ++it) {
108070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        int trackNum = it->mTrack->getTrackId() << 28;
108170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
108270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                trackNum | MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS,
108370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                it->mMaxInterChunkDurUs);
108470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    }
108570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong}
108670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
108713aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) {
108813aec890216948b0c364f8f92792129d0335f506James Dong    mInterleaveDurationUs = durationUs;
108913aec890216948b0c364f8f92792129d0335f506James Dong    return OK;
109013aec890216948b0c364f8f92792129d0335f506James Dong}
109113aec890216948b0c364f8f92792129d0335f506James Dong
109213aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() {
109313aec890216948b0c364f8f92792129d0335f506James Dong    mLock.lock();
109413aec890216948b0c364f8f92792129d0335f506James Dong}
109513aec890216948b0c364f8f92792129d0335f506James Dong
109613aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() {
109713aec890216948b0c364f8f92792129d0335f506James Dong    mLock.unlock();
109813aec890216948b0c364f8f92792129d0335f506James Dong}
109920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1100c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addSample_l(MediaBuffer *buffer) {
1101c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t old_offset = mOffset;
110220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1103c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    ::write(mFd,
1104c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong          (const uint8_t *)buffer->data() + buffer->range_offset(),
1105c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong          buffer->range_length());
110620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
110720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += buffer->range_length();
110820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
110920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return old_offset;
111020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
111120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
111203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) {
111303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (buffer->range_length() < 4) {
111403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return;
111503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
111603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
111703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    const uint8_t *ptr =
111803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        (const uint8_t *)buffer->data() + buffer->range_offset();
111903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
112003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) {
112103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        buffer->set_range(
112203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                buffer->range_offset() + 4, buffer->range_length() - 4);
112303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
112403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
112503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
1126c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) {
1127c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t old_offset = mOffset;
112830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
112930ab66297501757d745b9ae10da61adcd891f497Andreas Huber    size_t length = buffer->range_length();
113003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
1131b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (mUse4ByteNalLength) {
1132b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        uint8_t x = length >> 24;
1133c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1134b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = (length >> 16) & 0xff;
1135c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1136b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = (length >> 8) & 0xff;
1137c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1138b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = length & 0xff;
1139c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1140c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong
1141c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd,
1142c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong              (const uint8_t *)buffer->data() + buffer->range_offset(),
1143c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong              length);
1144b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong
1145b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mOffset += length + 4;
1146b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    } else {
114743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_LT(length, 65536);
114830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
1149b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        uint8_t x = length >> 8;
1150c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1151b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = length & 0xff;
1152c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1153c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, (const uint8_t *)buffer->data() + buffer->range_offset(), length);
1154b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mOffset += length + 2;
1155b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    }
115630ab66297501757d745b9ae10da61adcd891f497Andreas Huber
115730ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return old_offset;
115830ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
115930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
11607837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write(
1161674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        const void *ptr, size_t size, size_t nmemb) {
11627837c17063a4c50bc856ba59418516fdab731de7James Dong
11637837c17063a4c50bc856ba59418516fdab731de7James Dong    const size_t bytes = size * nmemb;
11647837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
11657b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
1166c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes;
11671acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        if (moovBoxSize > mEstimatedMoovBoxSize) {
11687b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // The reserved moov box at the beginning of the file
11697b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // is not big enough. Moov box should be written to
11707b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // the end of the file from now on, but not to the
11717b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // in-memory cache.
11727b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
11737b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // We write partial moov box that is in the memory to
11747b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // the file first.
1175c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            for (List<off64_t>::iterator it = mBoxes.begin();
11767837c17063a4c50bc856ba59418516fdab731de7James Dong                 it != mBoxes.end(); ++it) {
11777837c17063a4c50bc856ba59418516fdab731de7James Dong                (*it) += mOffset;
11787837c17063a4c50bc856ba59418516fdab731de7James Dong            }
1179674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong            lseek64(mFd, mOffset, SEEK_SET);
1180674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong            ::write(mFd, mMoovBoxBuffer, mMoovBoxBufferOffset);
11817b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            ::write(mFd, ptr, bytes);
11827837c17063a4c50bc856ba59418516fdab731de7James Dong            mOffset += (bytes + mMoovBoxBufferOffset);
11837b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
11847b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // All subsequent moov box content will be written
11857b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // to the end of the file.
11867837c17063a4c50bc856ba59418516fdab731de7James Dong            mWriteMoovBoxToMemory = false;
11877837c17063a4c50bc856ba59418516fdab731de7James Dong        } else {
11887837c17063a4c50bc856ba59418516fdab731de7James Dong            memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes);
11897837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset += bytes;
11907837c17063a4c50bc856ba59418516fdab731de7James Dong        }
11917837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
1192674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        ::write(mFd, ptr, size * nmemb);
11937837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset += bytes;
11947837c17063a4c50bc856ba59418516fdab731de7James Dong    }
11957837c17063a4c50bc856ba59418516fdab731de7James Dong    return bytes;
11967837c17063a4c50bc856ba59418516fdab731de7James Dong}
11977837c17063a4c50bc856ba59418516fdab731de7James Dong
1198e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::beginBox(uint32_t id) {
1199e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    mBoxes.push_back(mWriteMoovBoxToMemory?
1200e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            mMoovBoxBufferOffset: mOffset);
1201e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
1202e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0);
1203e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(id);
1204e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
1205e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
120620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) {
12070c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(fourcc), 4);
120820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12097837c17063a4c50bc856ba59418516fdab731de7James Dong    mBoxes.push_back(mWriteMoovBoxToMemory?
12107837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset: mOffset);
121120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
121220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeInt32(0);
121320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeFourcc(fourcc);
121420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
121520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
121620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() {
12170c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(!mBoxes.empty());
121820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1219c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t offset = *--mBoxes.end();
122020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mBoxes.erase(--mBoxes.end());
122120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12227837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
12237837c17063a4c50bc856ba59418516fdab731de7James Dong       int32_t x = htonl(mMoovBoxBufferOffset - offset);
12247837c17063a4c50bc856ba59418516fdab731de7James Dong       memcpy(mMoovBoxBuffer + offset, &x, 4);
12257837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
1226c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, offset, SEEK_SET);
12277837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mOffset - offset);
12287837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset -= 4;
1229c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mOffset, SEEK_SET);
12307837c17063a4c50bc856ba59418516fdab731de7James Dong    }
123120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
123220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
123320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) {
1234674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 1);
123520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
123620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
123720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) {
123820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htons(x);
1239674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 2);
124020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
124120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
124220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) {
124320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htonl(x);
1244674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 4);
124520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
124620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
124720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) {
124820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = hton64(x);
1249674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 8);
125020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
125120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
125220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) {
125320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t n = strlen(s);
1254674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(s, 1, n + 1);
125520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
125620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
125720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) {
12580c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(s), 4);
1259674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(s, 1, 4);
126020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
126120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
126207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
126307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/-DD.DDDD format
126407b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLatitude(int degreex10000) {
126507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    bool isNegative = (degreex10000 < 0);
126607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char sign = isNegative? '-': '+';
126707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
126807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the whole part
126907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char str[9];
127007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int wholePart = degreex10000 / 10000;
127107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (wholePart == 0) {
127207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 5, "%c%.2d.", sign, wholePart);
127307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    } else {
127407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 5, "%+.2d.", wholePart);
127507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
127607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
127707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the fractional part
127807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int fractionalPart = degreex10000 - (wholePart * 10000);
127907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (fractionalPart < 0) {
128007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        fractionalPart = -fractionalPart;
128107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
128207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    snprintf(&str[4], 5, "%.4d", fractionalPart);
128307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
128407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Do not write the null terminator
128507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    write(str, 1, 8);
128607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
128707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
128807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/- DDD.DDDD format
128907b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLongitude(int degreex10000) {
129007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    bool isNegative = (degreex10000 < 0);
129107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char sign = isNegative? '-': '+';
129207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
129307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the whole part
129407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char str[10];
129507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int wholePart = degreex10000 / 10000;
129607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (wholePart == 0) {
129707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 6, "%c%.3d.", sign, wholePart);
129807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    } else {
129907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 6, "%+.3d.", wholePart);
130007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
130107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
130207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the fractional part
130307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int fractionalPart = degreex10000 - (wholePart * 10000);
130407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (fractionalPart < 0) {
130507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        fractionalPart = -fractionalPart;
130607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
130707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    snprintf(&str[5], 5, "%.4d", fractionalPart);
130807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
130907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Do not write the null terminator
131007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    write(str, 1, 9);
131107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
131207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
131307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/*
131407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard.
131507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * latitudex10000 is latitude in degrees times 10000, and
131607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * longitudex10000 is longitude in degrees times 10000.
131707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the latitude is in [-90, +90], and
131807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the longitude is in [-180, +180]
131907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */
132007b1bb529a1ae76c46a71b01338c166f9490629dJames Dongstatus_t MPEG4Writer::setGeoData(int latitudex10000, int longitudex10000) {
132107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Is latitude or longitude out of range?
132207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (latitudex10000 < -900000 || latitudex10000 > 900000 ||
132307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        longitudex10000 < -1800000 || longitudex10000 > 1800000) {
132407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        return BAD_VALUE;
132507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
132607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
132707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mLatitudex10000 = latitudex10000;
132807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mLongitudex10000 = longitudex10000;
132907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mAreGeoTagsAvailable = true;
13307c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMoovExtraSize += 30;
133107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    return OK;
133207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
133307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
1334e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangstatus_t MPEG4Writer::setCaptureRate(float captureFps) {
1335e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    if (captureFps <= 0.0f) {
1336e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        return BAD_VALUE;
1337e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
1338e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
13397c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMetaKeys->setFloat(kMetaKey_CaptureFps, captureFps);
13407c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMoovExtraSize += sizeof(kMetaKey_CaptureFps) + 4 + 32;
13417c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
1342e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    return OK;
1343e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
1344e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
134520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) {
1346674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(data, 1, size);
134720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
134820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
134978a1a286f736888ae7af8860b2c424af0d978848James Dongbool MPEG4Writer::isFileStreamable() const {
135078a1a286f736888ae7af8860b2c424af0d978848James Dong    return mStreamableFile;
135178a1a286f736888ae7af8860b2c424af0d978848James Dong}
135278a1a286f736888ae7af8860b2c424af0d978848James Dong
1353d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() {
1354d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
1355d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileSizeLimitBytes == 0) {
1356d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
1357d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1358d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1359956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize);
1360d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
1361d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
1362d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes();
1363d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
13641f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
136577e8ae9967a078770416619e99ddb5b010def312James Dong    if (!mStreamableFile) {
136677e8ae9967a078770416619e99ddb5b010def312James Dong        // Add 1024 bytes as error tolerance
136777e8ae9967a078770416619e99ddb5b010def312James Dong        return nTotalBytesEstimate + 1024 >= mMaxFileSizeLimitBytes;
136877e8ae9967a078770416619e99ddb5b010def312James Dong    }
1369acd234bba9f048971d66890009eeff9a8db94be3James Dong    // Be conservative in the estimate: do not exceed 95% of
1370acd234bba9f048971d66890009eeff9a8db94be3James Dong    // the target file limit. For small target file size limit, though,
1371acd234bba9f048971d66890009eeff9a8db94be3James Dong    // this will not help.
1372acd234bba9f048971d66890009eeff9a8db94be3James Dong    return (nTotalBytesEstimate >= (95 * mMaxFileSizeLimitBytes) / 100);
1373d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
1374d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1375d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() {
1376d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
1377d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileDurationLimitUs == 0) {
1378d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
1379d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1380d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1381d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
1382d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
1383d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) {
1384d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            return true;
1385d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
1386d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1387d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return false;
1388d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
1389d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
139025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() {
139125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool allDone = true;
139225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
139325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber         it != mTracks.end(); ++it) {
139425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        if (!(*it)->reachedEOS()) {
139525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            allDone = false;
139625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            break;
139725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        }
139825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
139925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
140025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return allDone;
140125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
140225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
1403f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) {
1404a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGI("setStartTimestampUs: %" PRId64, timeUs);
140543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GE(timeUs, 0ll);
14063c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
1407065d1aff96818df54456053f1574aec8a234d0deJames Dong    if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) {
1408f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mStartTimestampUs = timeUs;
1409a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGI("Earliest track starting time: %" PRId64, mStartTimestampUs);
14103c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    }
14113c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
14123c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
1413f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() {
14143c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
14153c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    return mStartTimestampUs;
14163c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
14173c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
141858ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() {
141958ae9c530247668f8af36e30d228c716c226b3d4James Dong    Mutex::Autolock autolock(mLock);
142058ae9c530247668f8af36e30d228c716c226b3d4James Dong    return mTracks.size();
142158ae9c530247668f8af36e30d228c716c226b3d4James Dong}
142258ae9c530247668f8af36e30d228c716c226b3d4James Dong
142320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
142420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
142520111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track(
1426bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId)
142720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mOwner(owner),
142825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mMeta(source->getFormat()),
142920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSource(source),
143020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDone(false),
1431a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
1432a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mResumed(false),
1433eaae38445a340c4857c1c5569475879a728e63b7James Dong      mStarted(false),
1434bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong      mTrackId(trackId),
1435c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong      mTrackDurationUs(0),
1436956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      mEstimatedTrackSizeBytes(0),
1437be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong      mSamplesHaveSameSize(true),
1438c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mStszTableEntries(new ListTableEntries<uint32_t>(1000, 1)),
1439c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mStcoTableEntries(new ListTableEntries<uint32_t>(1000, 1)),
1440c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mCo64TableEntries(new ListTableEntries<off64_t>(1000, 1)),
1441c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mStscTableEntries(new ListTableEntries<uint32_t>(1000, 3)),
1442c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mStssTableEntries(new ListTableEntries<uint32_t>(1000, 1)),
1443c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mSttsTableEntries(new ListTableEntries<uint32_t>(1000, 2)),
1444c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mCttsTableEntries(new ListTableEntries<uint32_t>(1000, 2)),
144520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCodecSpecificData(NULL),
144625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mCodecSpecificDataSize(0),
1447548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber      mGotAllCodecSpecificData(false),
144813f6284305e4b27395a23db7882d670bdb1bcae1James Dong      mReachedEOS(false),
144913f6284305e4b27395a23db7882d670bdb1bcae1James Dong      mRotation(0) {
145019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    getCodecSpecificDataFromInputFormatIfPossible();
14518f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
14521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    const char *mime;
14531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mMeta->findCString(kKeyMIMEType, &mime);
14541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
14551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAudio = !strncasecmp(mime, "audio/", 6);
14561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
14571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong               !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC);
14581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1459c059860c73678a202bfa33062723e8f82fb779d9James Dong    setTimeScale();
1460c059860c73678a202bfa33062723e8f82fb779d9James Dong}
1461c059860c73678a202bfa33062723e8f82fb779d9James Dong
14621f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::updateTrackSizeEstimate() {
14631f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1464c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t stcoBoxCount = (mOwner->use32BitFileOffset()
1465c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                            ? mStcoTableEntries->count()
1466c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                            : mCo64TableEntries->count());
1467c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    int64_t stcoBoxSizeBytes = stcoBoxCount * 4;
1468c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mStszTableEntries->count() * 4);
14691f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
147078a1a286f736888ae7af8860b2c424af0d978848James Dong    mEstimatedTrackSizeBytes = mMdatSizeBytes;  // media data size
147178a1a286f736888ae7af8860b2c424af0d978848James Dong    if (!mOwner->isFileStreamable()) {
147278a1a286f736888ae7af8860b2c424af0d978848James Dong        // Reserved free space is not large enough to hold
147378a1a286f736888ae7af8860b2c424af0d978848James Dong        // all meta data and thus wasted.
1474c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mEstimatedTrackSizeBytes += mStscTableEntries->count() * 12 +  // stsc box size
1475c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mStssTableEntries->count() * 4 +   // stss box size
1476c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mSttsTableEntries->count() * 8 +   // stts box size
1477c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mCttsTableEntries->count() * 8 +   // ctts box size
147878a1a286f736888ae7af8860b2c424af0d978848James Dong                                    stcoBoxSizeBytes +           // stco box size
147978a1a286f736888ae7af8860b2c424af0d978848James Dong                                    stszBoxSizeBytes;            // stsz box size
148078a1a286f736888ae7af8860b2c424af0d978848James Dong    }
14811f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
14821f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
14831f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStscTableEntry(
14841f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        size_t chunkId, size_t sampleId) {
14851f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1486c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStscTableEntries->add(htonl(chunkId));
1487c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStscTableEntries->add(htonl(sampleId));
1488c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStscTableEntries->add(htonl(1));
14891f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
14901f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
14911f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) {
1492c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries->add(htonl(sampleId));
14931f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
14941f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
14951f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneSttsTableEntry(
149679761ab096f57c3027fad9556c2bc436672d614eJames Dong        size_t sampleCount, int32_t duration) {
14971f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
14985a217fba010e801c255503602bda4b86ac5a6ac9James Dong    if (duration == 0) {
1499377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        ALOGW("0-duration samples found: %zu", sampleCount);
15005a217fba010e801c255503602bda4b86ac5a6ac9James Dong    }
1501c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->add(htonl(sampleCount));
1502c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->add(htonl(duration));
15031f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
15041f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1505965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::addOneCttsTableEntry(
1506965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        size_t sampleCount, int32_t duration) {
1507965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
1508965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    if (mIsAudio) {
1509965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
1510965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
1511c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->add(htonl(sampleCount));
1512c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->add(htonl(duration));
1513965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong}
1514965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
1515c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongvoid MPEG4Writer::Track::addChunkOffset(off64_t offset) {
1516c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mOwner->use32BitFileOffset()) {
1517c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t value = offset;
1518c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStcoTableEntries->add(htonl(value));
1519c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    } else {
1520c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mCo64TableEntries->add(hton64(offset));
1521c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    }
15221f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
15231f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1524c059860c73678a202bfa33062723e8f82fb779d9James Dongvoid MPEG4Writer::Track::setTimeScale() {
15253856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setTimeScale");
1526c059860c73678a202bfa33062723e8f82fb779d9James Dong    // Default time scale
1527c059860c73678a202bfa33062723e8f82fb779d9James Dong    mTimeScale = 90000;
1528c059860c73678a202bfa33062723e8f82fb779d9James Dong
1529c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mIsAudio) {
1530c059860c73678a202bfa33062723e8f82fb779d9James Dong        // Use the sampling rate as the default time scale for audio track.
1531c059860c73678a202bfa33062723e8f82fb779d9James Dong        int32_t sampleRate;
1532c059860c73678a202bfa33062723e8f82fb779d9James Dong        bool success = mMeta->findInt32(kKeySampleRate, &sampleRate);
1533c059860c73678a202bfa33062723e8f82fb779d9James Dong        CHECK(success);
1534c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = sampleRate;
1535c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
1536c059860c73678a202bfa33062723e8f82fb779d9James Dong
1537c059860c73678a202bfa33062723e8f82fb779d9James Dong    // If someone would like to overwrite the timescale, use user-supplied value.
1538c059860c73678a202bfa33062723e8f82fb779d9James Dong    int32_t timeScale;
1539c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mMeta->findInt32(kKeyTimeScale, &timeScale)) {
1540c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = timeScale;
1541c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
1542c059860c73678a202bfa33062723e8f82fb779d9James Dong
154343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mTimeScale, 0);
154419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber}
154519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
154619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Hubervoid MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() {
154719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    const char *mime;
154819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
154919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
155019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
155119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        uint32_t type;
155219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        const void *data;
155319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        size_t size;
155419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        if (mMeta->findData(kKeyAVCC, &type, &data, &size)) {
155519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mCodecSpecificData = malloc(size);
155619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mCodecSpecificDataSize = size;
155719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            memcpy(mCodecSpecificData, data, size);
155819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mGotAllCodecSpecificData = true;
155919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        }
156019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
156119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
156219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        uint32_t type;
156319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        const void *data;
156419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        size_t size;
156519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        if (mMeta->findData(kKeyESDS, &type, &data, &size)) {
156619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            ESDS esds(data, size);
156719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            if (esds.getCodecSpecificInfo(&data, &size) == OK) {
156819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mCodecSpecificData = malloc(size);
156919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mCodecSpecificDataSize = size;
157019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                memcpy(mCodecSpecificData, data, size);
157119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mGotAllCodecSpecificData = true;
157219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            }
157319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        }
157419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
157520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
157620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
157720111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() {
157820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    stop();
157920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1580c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStszTableEntries;
1581c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStcoTableEntries;
1582c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mCo64TableEntries;
1583c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStscTableEntries;
1584c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mSttsTableEntries;
1585c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStssTableEntries;
1586c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mCttsTableEntries;
1587c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
1588c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStszTableEntries = NULL;
1589c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStcoTableEntries = NULL;
1590c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCo64TableEntries = NULL;
1591c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStscTableEntries = NULL;
1592c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries = NULL;
1593c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries = NULL;
1594c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries = NULL;
1595c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
159620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mCodecSpecificData != NULL) {
159720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        free(mCodecSpecificData);
159820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mCodecSpecificData = NULL;
159920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
160020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
160120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
160293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) {
16033856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("initTrackingProgressStatus");
160493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mPreviousTrackTimeUs = -1;
160593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackingProgressStatus = false;
160693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackEveryTimeDurationUs = 0;
160793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    {
160893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        int64_t timeUs;
160993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) {
1610a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGV("Receive request to track progress status for every %" PRId64 " us", timeUs);
161193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackEveryTimeDurationUs = timeUs;
161293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackingProgressStatus = true;
161393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
161493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
161593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
161693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
16171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong// static
16181c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid *MPEG4Writer::ThreadWrapper(void *me) {
16193856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("ThreadWrapper: %p", me);
16201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    MPEG4Writer *writer = static_cast<MPEG4Writer *>(me);
16211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    writer->threadFunc();
16221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return NULL;
16231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
16241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
16251c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::bufferChunk(const Chunk& chunk) {
16263856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("bufferChunk: %p", chunk.mTrack);
16271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Mutex::Autolock autolock(mLock);
16281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    CHECK_EQ(mDone, false);
16291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
16301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
16311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
16321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
16331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (chunk.mTrack == it->mTrack) {  // Found owner
16341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            it->mChunks.push_back(chunk);
16351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.signal();
16361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            return;
16371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
16381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
16391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
164043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK(!"Received a chunk for a unknown track");
16411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
16421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1643fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeChunkToFile(Chunk* chunk) {
1644a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("writeChunkToFile: %" PRId64 " from %s track",
16455410afcbb0af5d29d9f710a1c2978c500f9792dcPannag Sanketi        chunk->mTimeStampUs, chunk->mTrack->isAudio()? "audio": "video");
1646fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1647fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    int32_t isFirstSample = true;
1648fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    while (!chunk->mSamples.empty()) {
1649fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        List<MediaBuffer *>::iterator it = chunk->mSamples.begin();
1650fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1651fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        off64_t offset = chunk->mTrack->isAvc()
1652fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong                                ? addLengthPrefixedSample_l(*it)
1653fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong                                : addSample_l(*it);
1654fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1655fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        if (isFirstSample) {
1656fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            chunk->mTrack->addChunkOffset(offset);
1657fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            isFirstSample = false;
16581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
16591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
16601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it)->release();
16611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it) = NULL;
1662fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        chunk->mSamples.erase(it);
16631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1664fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    chunk->mSamples.clear();
16651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
16661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1667fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeAllChunks() {
16683856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("writeAllChunks");
16691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    size_t outstandingChunks = 0;
167070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    Chunk chunk;
167170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    while (findChunkToWrite(&chunk)) {
1672e9f6d0579603372fd2547e6c5ba6e114c6f8cba7James Dong        writeChunkToFile(&chunk);
167370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        ++outstandingChunks;
16741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
167570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
167670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    sendSessionSummary();
167770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
16781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mChunkInfos.clear();
1679377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    ALOGD("%zu chunks are written in the last batch", outstandingChunks);
16801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
16811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1682fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongbool MPEG4Writer::findChunkToWrite(Chunk *chunk) {
16833856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("findChunkToWrite");
16841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
16851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL;
16861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Track *track = NULL;
16871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
16881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
16891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (!it->mChunks.empty()) {
16901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            List<Chunk>::iterator chunkIt = it->mChunks.begin();
16911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (chunkIt->mTimeStampUs < minTimestampUs) {
16921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                minTimestampUs = chunkIt->mTimeStampUs;
16931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                track = it->mTrack;
16941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            }
16951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
16961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
16971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
16981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (track == NULL) {
16993856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("Nothing to be written after all");
1700fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        return false;
17011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
17021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (mIsFirstChunk) {
17041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsFirstChunk = false;
17051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1706fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
17071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
17081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
17091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (it->mTrack == track) {
1710fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            *chunk = *(it->mChunks.begin());
1711fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            it->mChunks.erase(it->mChunks.begin());
1712fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            CHECK_EQ(chunk->mTrack, track);
171370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
171470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            int64_t interChunkTimeUs =
171570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                chunk->mTimeStampUs - it->mPrevChunkTimestampUs;
171670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            if (interChunkTimeUs > it->mPrevChunkTimestampUs) {
171770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                it->mMaxInterChunkDurUs = interChunkTimeUs;
171870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            }
171970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
1720fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            return true;
17211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
17221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1723fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1724fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    return false;
17251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
17261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17271c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::threadFunc() {
17283856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("threadFunc");
17291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1730a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    prctl(PR_SET_NAME, (unsigned long)"MPEG4Writer", 0, 0, 0);
1731fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1732fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    Mutex::Autolock autoLock(mLock);
17331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    while (!mDone) {
1734fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        Chunk chunk;
1735fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        bool chunkFound = false;
1736fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1737fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        while (!mDone && !(chunkFound = findChunkToWrite(&chunk))) {
17381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.wait(mLock);
17391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
17401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1741de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // In real time recording mode, write without holding the lock in order
1742de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // to reduce the blocking time for media track threads.
1743de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // Otherwise, hold the lock until the existing chunks get written to the
1744de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // file.
1745fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        if (chunkFound) {
1746de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            if (mIsRealTimeRecording) {
1747de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui                mLock.unlock();
1748de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            }
1749fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            writeChunkToFile(&chunk);
1750de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            if (mIsRealTimeRecording) {
1751de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui                mLock.lock();
1752de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            }
1753fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        }
17541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1755fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1756fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    writeAllChunks();
17571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
17581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17591c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::startWriterThread() {
17603856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("startWriterThread");
17611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mDone = false;
17631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsFirstChunk = true;
1764e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    mDriftTimeUs = 0;
17651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<Track *>::iterator it = mTracks.begin();
17661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mTracks.end(); ++it) {
17671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        ChunkInfo info;
17681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        info.mTrack = *it;
176970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        info.mPrevChunkTimestampUs = 0;
177070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        info.mMaxInterChunkDurUs = 0;
17711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkInfos.push_back(info);
17721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
17731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_t attr;
17751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_init(&attr);
17761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
17771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_create(&mThread, &attr, ThreadWrapper, this);
17781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_destroy(&attr);
1779411ba422e3635d534928ffd81abf54f4f291c739James Dong    mWriterThreadStarted = true;
17801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return OK;
17811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
17821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17831f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
178493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) {
1785a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (!mDone && mPaused) {
1786a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mPaused = false;
1787a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mResumed = true;
1788a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
1789a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
179025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
179193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t startTimeUs;
179219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) {
179319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        startTimeUs = 0;
179419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
179570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    mStartTimeRealUs = startTimeUs;
179619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
179713f6284305e4b27395a23db7882d670bdb1bcae1James Dong    int32_t rotationDegrees;
179813f6284305e4b27395a23db7882d670bdb1bcae1James Dong    if (!mIsAudio && params && params->findInt32(kKeyRotation, &rotationDegrees)) {
179913f6284305e4b27395a23db7882d670bdb1bcae1James Dong        mRotation = rotationDegrees;
180013f6284305e4b27395a23db7882d670bdb1bcae1James Dong    }
180113f6284305e4b27395a23db7882d670bdb1bcae1James Dong
180293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    initTrackingProgressStatus(params);
180393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
1804f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    sp<MetaData> meta = new MetaData;
1805de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    if (mOwner->isRealTimeRecording() && mOwner->numTracks() > 1) {
1806a472613aec322e25891abf5c77bf3f7e3c244920James Dong        /*
1807a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * This extra delay of accepting incoming audio/video signals
1808a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * helps to align a/v start time at the beginning of a recording
1809a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * session, and it also helps eliminate the "recording" sound for
1810a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * camcorder applications.
1811a472613aec322e25891abf5c77bf3f7e3c244920James Dong         *
181286b7f47aa7482424cf8fd248f1315311919be3b0James Dong         * If client does not set the start time offset, we fall back to
181386b7f47aa7482424cf8fd248f1315311919be3b0James Dong         * use the default initial delay value.
1814a472613aec322e25891abf5c77bf3f7e3c244920James Dong         */
181586b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL;
181686b7f47aa7482424cf8fd248f1315311919be3b0James Dong        if (startTimeOffsetUs < 0) {  // Start time offset was not set
181786b7f47aa7482424cf8fd248f1315311919be3b0James Dong            startTimeOffsetUs = kInitialDelayTimeUs;
181886b7f47aa7482424cf8fd248f1315311919be3b0James Dong        }
181986b7f47aa7482424cf8fd248f1315311919be3b0James Dong        startTimeUs += startTimeOffsetUs;
1820a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGI("Start time offset: %" PRId64 " us", startTimeOffsetUs);
1821a472613aec322e25891abf5c77bf3f7e3c244920James Dong    }
1822a472613aec322e25891abf5c77bf3f7e3c244920James Dong
1823f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    meta->setInt64(kKeyTime, startTimeUs);
1824a472613aec322e25891abf5c77bf3f7e3c244920James Dong
1825f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    status_t err = mSource->start(meta.get());
182625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    if (err != OK) {
182725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        mDone = mReachedEOS = true;
182825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return err;
182925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
183020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
183120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_t attr;
183220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_init(&attr);
183320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
183420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
183520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = false;
1836eaae38445a340c4857c1c5569475879a728e63b7James Dong    mStarted = true;
1837c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs = 0;
183825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = false;
1839956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    mEstimatedTrackSizeBytes = 0;
18401f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mMdatSizeBytes = 0;
184143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mMaxChunkDurationUs = 0;
184220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
184325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    pthread_create(&mThread, &attr, ThreadWrapper, this);
184420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_destroy(&attr);
184525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
184625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
184720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
184820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
184937187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::pause() {
1850a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
185137187916a486504acaf83bea30147eb5fbf46ae5James Dong    return OK;
1852a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
1853a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
185437187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::stop() {
185572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGD("%s track stopping", mIsAudio? "Audio": "Video");
1856eaae38445a340c4857c1c5569475879a728e63b7James Dong    if (!mStarted) {
185729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Stop() called but track is not started");
1858eaae38445a340c4857c1c5569475879a728e63b7James Dong        return ERROR_END_OF_STREAM;
1859eaae38445a340c4857c1c5569475879a728e63b7James Dong    }
1860eaae38445a340c4857c1c5569475879a728e63b7James Dong
186120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mDone) {
186237187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
186320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
186420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = true;
186520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
186672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGD("%s track source stopping", mIsAudio? "Audio": "Video");
186772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mSource->stop();
186872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGD("%s track source stopped", mIsAudio? "Audio": "Video");
186972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
187020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *dummy;
187120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_join(mThread, &dummy);
1872377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    status_t err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy));
187337187916a486504acaf83bea30147eb5fbf46ae5James Dong
1874b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("%s track stopped", mIsAudio? "Audio": "Video");
187537187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
187620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
187720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
187825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() {
187925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return mReachedEOS;
188025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
188125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
188220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static
188320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) {
188420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = static_cast<Track *>(me);
188520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
188637187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = track->threadEntry();
1887377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    return (void *)(uintptr_t)err;
188820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
188920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
18903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic void getNalUnitType(uint8_t byte, uint8_t* type) {
18913856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("getNalUnitType: %d", byte);
18923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
18933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // nal_unit_type: 5-bit unsigned integer
18943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *type = (byte & 0x1F);
18953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
18963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
18973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t *findNextStartCode(
18983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length) {
18993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
1900a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("findNextStartCode: %p %zu", data, length);
19013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t bytesLeft = length;
19033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    while (bytesLeft > 4  &&
19043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            memcmp("\x00\x00\x00\x01", &data[length - bytesLeft], 4)) {
19053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        --bytesLeft;
19063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
19073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (bytesLeft <= 4) {
19083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        bytesLeft = 0; // Last parameter set
19093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
19103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return &data[length - bytesLeft];
19113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
19123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongconst uint8_t *MPEG4Writer::Track::parseParamSet(
19143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen) {
19153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19163856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("parseParamSet");
19173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    CHECK(type == kNalUnitTypeSeqParamSet ||
19183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong          type == kNalUnitTypePicParamSet);
19193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *nextStartCode = findNextStartCode(data, length);
19213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *paramSetLen = nextStartCode - data;
19223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (*paramSetLen == 0) {
192329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Param set is malformed, since its length is 0");
19243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return NULL;
19253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
19263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    AVCParamSet paramSet(*paramSetLen, data);
19283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (type == kNalUnitTypeSeqParamSet) {
19293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (*paramSetLen < 4) {
193029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Seq parameter set malformed");
19313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return NULL;
19323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
19333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mSeqParamSets.empty()) {
19343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc = data[1];
19353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileCompatible = data[2];
19363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mLevelIdc = data[3];
19373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
19383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (mProfileIdc != data[1] ||
19393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mProfileCompatible != data[2] ||
19403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mLevelIdc != data[3]) {
194129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("Inconsistent profile/level found in seq parameter sets");
19423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return NULL;
19433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
19443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
19453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mSeqParamSets.push_back(paramSet);
19463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    } else {
19473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mPicParamSets.push_back(paramSet);
19483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
19493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return nextStartCode;
19503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
19513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::copyAVCCodecSpecificData(
19533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
19543856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("copyAVCCodecSpecificData");
19553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 2 bytes for each of the parameter set length field
19573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // plus the 7 bytes for the header
19583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (size < 4 + 7) {
1959377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        ALOGE("Codec specific data length too short: %zu", size);
19603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return ERROR_MALFORMED;
19613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
19623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize = size;
19643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificData = malloc(size);
19653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    memcpy(mCodecSpecificData, data, size);
19663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
19673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
19683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::parseAVCCodecSpecificData(
19703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
19713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19723856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("parseAVCCodecSpecificData");
19733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data starts with a start code.
19743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // SPS and PPS are separated with start codes.
19753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Also, SPS must come before PPS
19763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t type = kNalUnitTypeSeqParamSet;
19773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotSps = false;
19783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotPps = false;
19793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *tmp = data;
19803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *nextStartCode = data;
19813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t bytesLeft = size;
19823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t paramSetLen = 0;
19833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize = 0;
19843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) {
19853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        getNalUnitType(*(tmp + 4), &type);
19863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (type == kNalUnitTypeSeqParamSet) {
19873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (gotPps) {
198829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("SPS must come before PPS");
19893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
19903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
19913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
19923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotSps = true;
19933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
19943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
19953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else if (type == kNalUnitTypePicParamSet) {
19963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
199729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("SPS must come before PPS");
19983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
19993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
20003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotPps) {
20013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotPps = true;
20023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
20033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
20043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
200529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Only SPS and PPS Nal units are expected");
20063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
20073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
20083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nextStartCode == NULL) {
20103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
20113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
20123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Move on to find the next parameter set
20143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        bytesLeft -= nextStartCode - tmp;
20153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        tmp = nextStartCode;
20163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mCodecSpecificDataSize += (2 + paramSetLen);
20173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
20183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
20203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of seq parameter sets
20213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nSeqParamSets = mSeqParamSets.size();
20223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets == 0) {
202329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Cound not find sequence parameter set");
20243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
20253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
20263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets > 0x1F) {
2028377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT            ALOGE("Too many seq parameter sets (%zu) found", nSeqParamSets);
20293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
20303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
20313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
20323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
20343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of pic parameter sets
20353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nPicParamSets = mPicParamSets.size();
20363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets == 0) {
203729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Cound not find picture parameter set");
20383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
20393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
20403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets > 0xFF) {
2041377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT            ALOGE("Too many pic parameter sets (%zd) found", nPicParamSets);
20423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
20433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
20443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
20451374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// FIXME:
20461374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// Add chromat_format_idc, bit depth values, etc for AVC/h264 high profile and above
20471374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// and remove #if 0
20481374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#if 0
20493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
20503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the profiles
20513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // These profiles requires additional parameter set extensions
20523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mProfileIdc == 100 || mProfileIdc == 110 ||
20533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc == 122 || mProfileIdc == 144) {
205429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Sorry, no support for profile_idc: %d!", mProfileIdc);
20553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return BAD_VALUE;
20563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
20573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
20581374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#endif
20593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
20603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
2061548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
206203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData(
206303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        const uint8_t *data, size_t size) {
2064548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
206503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (mCodecSpecificData != NULL) {
206629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Already have codec specific data");
206703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
206803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
206903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
20703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (size < 4) {
2071377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        ALOGE("Codec specific data length too short: %zu", size);
207203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
207303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
207403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
20753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data is in the form of AVCCodecSpecificData
20763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (memcmp("\x00\x00\x00\x01", data, 4)) {
20773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return copyAVCCodecSpecificData(data, size);
207803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
207903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
20803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (parseAVCCodecSpecificData(data, size) != OK) {
208103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
208203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
208303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
20843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // ISO 14496-15: AVC file format
20853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize += 7;  // 7 more bytes in the header
208603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    mCodecSpecificData = malloc(mCodecSpecificDataSize);
208703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    uint8_t *header = (uint8_t *)mCodecSpecificData;
20883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = 1;                     // version
20893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[1] = mProfileIdc;           // profile indication
20903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[2] = mProfileCompatible;    // profile compatibility
20913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[3] = mLevelIdc;
209203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
20933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne
2094b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (mOwner->useNalLengthFour()) {
2095b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        header[4] = 0xfc | 3;  // length size == 4 bytes
2096b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    } else {
2097b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        header[4] = 0xfc | 1;  // length size == 2 bytes
2098b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    }
209903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
21003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 3-bit '111' followed by 5-bit numSequenceParameterSets
21013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nSequenceParamSets = mSeqParamSets.size();
21023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[5] = 0xe0 | nSequenceParamSets;
21033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 6;
21043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mSeqParamSets.begin();
21053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mSeqParamSets.end(); ++it) {
21063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit sequence parameter set length
21073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t seqParamSetLength = it->mLength;
21083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = seqParamSetLength >> 8;
21093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = seqParamSetLength & 0xff;
21103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
21113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // SPS NAL unit (sequence parameter length bytes)
21123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, seqParamSetLength);
21133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + seqParamSetLength);
21143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
21153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
21163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 8-bit nPictureParameterSets
21173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nPictureParamSets = mPicParamSets.size();
21183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = nPictureParamSets;
21193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 1;
21203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mPicParamSets.begin();
21213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mPicParamSets.end(); ++it) {
21223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit picture parameter set length
21233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t picParamSetLength = it->mLength;
21243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = picParamSetLength >> 8;
21253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = picParamSetLength & 0xff;
21263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
21273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // PPS Nal unit (picture parameter set length bytes)
21283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, picParamSetLength);
21293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + picParamSetLength);
21303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
213103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
213203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    return OK;
213303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
213403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
2135872a481558350634a3fd5cb67939de288af00ecbJames Dong/*
2136872a481558350634a3fd5cb67939de288af00ecbJames Dong * Updates the drift time from the audio track so that
2137872a481558350634a3fd5cb67939de288af00ecbJames Dong * the video track can get the updated drift time information
2138872a481558350634a3fd5cb67939de288af00ecbJames Dong * from the file writer. The fluctuation of the drift time of the audio
2139872a481558350634a3fd5cb67939de288af00ecbJames Dong * encoding path is smoothed out with a simple filter by giving a larger
2140872a481558350634a3fd5cb67939de288af00ecbJames Dong * weight to more recently drift time. The filter coefficients, 0.5 and 0.5,
2141872a481558350634a3fd5cb67939de288af00ecbJames Dong * are heuristically determined.
2142872a481558350634a3fd5cb67939de288af00ecbJames Dong */
2143872a481558350634a3fd5cb67939de288af00ecbJames Dongvoid MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) {
2144872a481558350634a3fd5cb67939de288af00ecbJames Dong    int64_t driftTimeUs = 0;
2145872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) {
2146872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t prevDriftTimeUs = mOwner->getDriftTimeUs();
2147872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1;
2148872a481558350634a3fd5cb67939de288af00ecbJames Dong        mOwner->setDriftTimeUs(timeUs);
2149872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
2150872a481558350634a3fd5cb67939de288af00ecbJames Dong}
2151872a481558350634a3fd5cb67939de288af00ecbJames Dong
215237187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::threadEntry() {
215330ab66297501757d745b9ae10da61adcd891f497Andreas Huber    int32_t count = 0;
215413aec890216948b0c364f8f92792129d0335f506James Dong    const int64_t interleaveDurationUs = mOwner->interleaveDuration();
215543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    const bool hasMultipleTracks = (mOwner->numTracks() > 1);
215613aec890216948b0c364f8f92792129d0335f506James Dong    int64_t chunkTimestampUs = 0;
215713aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nChunks = 0;
215813aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nZeroLengthFrames = 0;
2159965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastTimestampUs = 0;      // Previous sample time stamp
2160965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastDurationUs = 0;       // Between the previous two samples
2161965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t currDurationTicks = 0;    // Timescale based ticks
2162965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastDurationTicks = 0;    // Timescale based ticks
2163965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int32_t sampleCount = 1;          // Sample count in the current stts table entry
2164000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    uint32_t previousSampleSize = 0;  // Size of the previous sample
2165a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    int64_t previousPausedDurationUs = 0;
2166965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t timestampUs = 0;
2167000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t cttsOffsetTimeUs = 0;
2168000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t currCttsOffsetTimeTicks = 0;   // Timescale based ticks
2169000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t lastCttsOffsetTimeTicks = -1;  // Timescale based ticks
217043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    int32_t cttsSampleCount = 0;           // Sample count in the current ctts table entry
2171c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t lastSamplesPerChunk = 0;
2172e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
2173a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    if (mIsAudio) {
2174a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong        prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0);
2175a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    } else {
2176a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong        prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0);
2177a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    }
2178de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui
2179de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    if (mOwner->isRealTimeRecording()) {
2180de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
2181de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    }
2182985f838934510983d8a887461e98dca60a6e858fJames Dong
2183d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong    sp<MetaData> meta_data;
218420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
218593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t err = OK;
218620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBuffer *buffer;
218711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih    const char *trackName = mIsAudio ? "Audio" : "Video";
218893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    while (!mDone && (err = mSource->read(&buffer)) == OK) {
218920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (buffer->range_length() == 0) {
219020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer->release();
219120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer = NULL;
219213aec890216948b0c364f8f92792129d0335f506James Dong            ++nZeroLengthFrames;
219320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            continue;
219420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
219520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2196a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // If the codec specific data has not been received yet, delay pause.
2197a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // After the codec specific data is received, discard what we received
2198a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // when the track is to be paused.
2199a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused && !mResumed) {
2200a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer->release();
2201a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer = NULL;
2202a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            continue;
2203a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
2204a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
220530ab66297501757d745b9ae10da61adcd891f497Andreas Huber        ++count;
220630ab66297501757d745b9ae10da61adcd891f497Andreas Huber
220703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        int32_t isCodecConfig;
220803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig)
220903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                && isCodecConfig) {
2210548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            CHECK(!mGotAllCodecSpecificData);
2211548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
22121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (mIsAvc) {
221303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                status_t err = makeAVCCodecSpecificData(
221403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        (const uint8_t *)buffer->data()
221503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                            + buffer->range_offset(),
221603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        buffer->range_length());
221743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                CHECK_EQ((status_t)OK, err);
22181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            } else if (mIsMPEG4) {
221903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificDataSize = buffer->range_length();
222003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificData = malloc(mCodecSpecificDataSize);
222103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                memcpy(mCodecSpecificData,
222203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        (const uint8_t *)buffer->data()
222303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                            + buffer->range_offset(),
222403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                       buffer->range_length());
222530ab66297501757d745b9ae10da61adcd891f497Andreas Huber            }
222630ab66297501757d745b9ae10da61adcd891f497Andreas Huber
222730ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer->release();
222830ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer = NULL;
222930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
2230548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            mGotAllCodecSpecificData = true;
223130ab66297501757d745b9ae10da61adcd891f497Andreas Huber            continue;
2232a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
2233a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
2234d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // Make a deep copy of the MediaBuffer and Metadata and release
2235d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // the original as soon as we can
2236d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        MediaBuffer *copy = new MediaBuffer(buffer->range_length());
2237d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(),
2238d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong                buffer->range_length());
2239d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        copy->set_range(0, buffer->range_length());
2240d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data = new MetaData(*buffer->meta_data().get());
2241d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer->release();
2242d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer = NULL;
2243d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
22441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (mIsAvc) StripStartcode(copy);
2245e136c3bb38e88315bf8797a464ebf2c788296b22James Dong
2246b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        size_t sampleSize = copy->range_length();
2247b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        if (mIsAvc) {
2248b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            if (mOwner->useNalLengthFour()) {
2249b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                sampleSize += 4;
2250b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            } else {
2251b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                sampleSize += 2;
2252b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            }
2253b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        }
2254050b28a593350047845a45a14cc5026221ac1620James Dong
2255d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        // Max file size or duration handling
22561f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mMdatSizeBytes += sampleSize;
22571f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        updateTrackSizeEstimate();
22581f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
2259d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileSizeLimit()) {
2260d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
2261d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
2262d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
2263d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileDurationLimit()) {
2264d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
2265d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
2266d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
2267d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
2268050b28a593350047845a45a14cc5026221ac1620James Dong
2269d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        int32_t isSync = false;
2270d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data->findInt32(kKeyIsSyncFrame, &isSync);
2271d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        CHECK(meta_data->findInt64(kKeyTime, &timestampUs));
2272d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
2273d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong////////////////////////////////////////////////////////////////////////////////
2274c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        if (mStszTableEntries->count() == 0) {
227570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            mFirstSampleTimeRealUs = systemTime() / 1000;
2276f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mStartTimestampUs = timestampUs;
2277f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mOwner->setStartTimestampUs(mStartTimestampUs);
22788428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            previousPausedDurationUs = mStartTimestampUs;
22793c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        }
228048c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber
2281a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mResumed) {
22828428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs;
228311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(durExcludingEarlierPausesUs >= 0ll, "for %s track", trackName)) {
228411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
228511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                return ERROR_MALFORMED;
228611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
228711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
22888428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs;
228911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(pausedDurationUs >= lastDurationUs, "for %s track", trackName)) {
229011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
229111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                return ERROR_MALFORMED;
229211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
229311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
22948428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            previousPausedDurationUs += pausedDurationUs - lastDurationUs;
2295a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mResumed = false;
2296a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
2297a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
2298a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        timestampUs -= previousPausedDurationUs;
229911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) {
230011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            copy->release();
230111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            return ERROR_MALFORMED;
230211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        }
230311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
2304000e18370baae60ffd9f25b509501dd8c26deabfJames Dong        if (!mIsAudio) {
2305965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            /*
2306965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             * Composition time: timestampUs
2307965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             * Decoding time: decodingTimeUs
2308000e18370baae60ffd9f25b509501dd8c26deabfJames Dong             * Composition time offset = composition time - decoding time
2309965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             */
2310965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            int64_t decodingTimeUs;
2311965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs));
2312965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            decodingTimeUs -= previousPausedDurationUs;
2313000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            cttsOffsetTimeUs =
2314000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs;
231511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(cttsOffsetTimeUs >= 0ll, "for %s track", trackName)) {
231611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
231711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                return ERROR_MALFORMED;
231811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
231911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
2320965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            timestampUs = decodingTimeUs;
2321a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGV("decoding time: %" PRId64 " and ctts offset time: %" PRId64,
2322000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                timestampUs, cttsOffsetTimeUs);
2323000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2324000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            // Update ctts box table if necessary
2325000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            currCttsOffsetTimeTicks =
2326000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    (cttsOffsetTimeUs * mTimeScale + 500000LL) / 1000000LL;
232711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(currCttsOffsetTimeTicks <= 0x0FFFFFFFFLL, "for %s track", trackName)) {
232811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
232911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                return ERROR_MALFORMED;
233011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
233111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
2332c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() == 0) {
233343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // Force the first ctts table entry to have one single entry
233443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // so that we can do adjustment for the initial track start
233543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // time offset easily in writeCttsBox().
233643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks;
233743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                addOneCttsTableEntry(1, currCttsOffsetTimeTicks);
233843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                cttsSampleCount = 0;      // No sample in ctts box is pending
233943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            } else {
234043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                if (currCttsOffsetTimeTicks != lastCttsOffsetTimeTicks) {
234143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
234243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks;
234343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    cttsSampleCount = 1;  // One sample in ctts box is pending
234443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                } else {
234543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    ++cttsSampleCount;
234643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                }
234743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            }
2348000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2349000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            // Update ctts time offset range
2350c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() == 0) {
2351000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2352000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2353000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            } else {
2354000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                if (currCttsOffsetTimeTicks > mMaxCttsOffsetTimeUs) {
2355000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2356000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                } else if (currCttsOffsetTimeTicks < mMinCttsOffsetTimeUs) {
2357000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2358000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                }
2359000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            }
2360000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2361965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        }
2362872a481558350634a3fd5cb67939de288af00ecbJames Dong
2363de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        if (mOwner->isRealTimeRecording()) {
2364872a481558350634a3fd5cb67939de288af00ecbJames Dong            if (mIsAudio) {
2365872a481558350634a3fd5cb67939de288af00ecbJames Dong                updateDriftTime(meta_data);
2366e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            }
2367e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        }
2368872a481558350634a3fd5cb67939de288af00ecbJames Dong
236911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) {
237011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            copy->release();
237111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            return ERROR_MALFORMED;
237211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        }
237311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
2374a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("%s media time stamp: %" PRId64 " and previous paused duration %" PRId64,
237511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                trackName, timestampUs, previousPausedDurationUs);
2376c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong        if (timestampUs > mTrackDurationUs) {
2377c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong            mTrackDurationUs = timestampUs;
23783b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber        }
23793b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber
23805a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // We need to use the time scale based ticks, rather than the
23815a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // timestamp itself to determine whether we have to use a new
23825a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // stts entry, since we may have rounding errors.
23835a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // The calculation is intended to reduce the accumulated
23845a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // rounding errors.
23855a217fba010e801c255503602bda4b86ac5a6ac9James Dong        currDurationTicks =
23865a217fba010e801c255503602bda4b86ac5a6ac9James Dong            ((timestampUs * mTimeScale + 500000LL) / 1000000LL -
23875a217fba010e801c255503602bda4b86ac5a6ac9James Dong                (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL);
2388c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        if (currDurationTicks < 0ll) {
2389a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGE("timestampUs %" PRId64 " < lastTimestampUs %" PRId64 " for %s track",
239011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                timestampUs, lastTimestampUs, trackName);
239111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            copy->release();
2392c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            return UNKNOWN_ERROR;
23938c460498c028888c533ab442be12b6d4b669b965James Dong        }
23948c460498c028888c533ab442be12b6d4b669b965James Dong
239585fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // if the duration is different for this sample, see if it is close enough to the previous
239685fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // duration that we can fudge it and use the same value, to avoid filling the stts table
239785fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // with lots of near-identical entries.
239885fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // "close enough" here means that the current duration needs to be adjusted by less
239985fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // than 0.1 milliseconds
240085fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        if (lastDurationTicks && (currDurationTicks != lastDurationTicks)) {
240185fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen            int64_t deltaUs = ((lastDurationTicks - currDurationTicks) * 1000000LL
240285fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                    + (mTimeScale / 2)) / mTimeScale;
240385fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen            if (deltaUs > -100 && deltaUs < 100) {
240485fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                // use previous ticks, and adjust timestamp as if it was actually that number
240585fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                // of ticks
240685fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                currDurationTicks = lastDurationTicks;
240785fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                timestampUs += deltaUs;
240885fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen            }
240985fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        }
241085fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen
2411c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStszTableEntries->add(htonl(sampleSize));
2412c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        if (mStszTableEntries->count() > 2) {
2413c059860c73678a202bfa33062723e8f82fb779d9James Dong
2414a472613aec322e25891abf5c77bf3f7e3c244920James Dong            // Force the first sample to have its own stts entry so that
2415a472613aec322e25891abf5c77bf3f7e3c244920James Dong            // we can adjust its value later to maintain the A/V sync.
2416c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() == 3 || currDurationTicks != lastDurationTicks) {
241779761ab096f57c3027fad9556c2bc436672d614eJames Dong                addOneSttsTableEntry(sampleCount, lastDurationTicks);
2418be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                sampleCount = 1;
2419be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            } else {
2420be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                ++sampleCount;
2421be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
2422965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2423be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
2424be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        if (mSamplesHaveSameSize) {
2425c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() >= 2 && previousSampleSize != sampleSize) {
2426be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mSamplesHaveSameSize = false;
2427be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
24288644c14618d30d9e57a69df40ed939986ebf02c4James Dong            previousSampleSize = sampleSize;
2429be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
2430a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("%s timestampUs/lastTimestampUs: %" PRId64 "/%" PRId64,
243111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                trackName, timestampUs, lastTimestampUs);
24328644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastDurationUs = timestampUs - lastTimestampUs;
2433c059860c73678a202bfa33062723e8f82fb779d9James Dong        lastDurationTicks = currDurationTicks;
24348644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastTimestampUs = timestampUs;
243520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2436d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        if (isSync != 0) {
2437c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            addOneStssTableEntry(mStszTableEntries->count());
2438d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        }
2439d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
244093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (mTrackingProgressStatus) {
244193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            if (mPreviousTrackTimeUs <= 0) {
244293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong                mPreviousTrackTimeUs = mStartTimestampUs;
244393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            }
2444faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong            trackProgressStatus(timestampUs);
244593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
244643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong        if (!hasMultipleTracks) {
2447c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t offset = mIsAvc? mOwner->addLengthPrefixedSample_l(copy)
244858ae9c530247668f8af36e30d228c716c226b3d4James Dong                                 : mOwner->addSample_l(copy);
2449c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
2450c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t count = (mOwner->use32BitFileOffset()
2451c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        ? mStcoTableEntries->count()
2452c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        : mCo64TableEntries->count());
2453c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
2454c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (count == 0) {
24551f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                addChunkOffset(offset);
245658ae9c530247668f8af36e30d228c716c226b3d4James Dong            }
245758ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy->release();
245858ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy = NULL;
245958ae9c530247668f8af36e30d228c716c226b3d4James Dong            continue;
246058ae9c530247668f8af36e30d228c716c226b3d4James Dong        }
246113aec890216948b0c364f8f92792129d0335f506James Dong
246213aec890216948b0c364f8f92792129d0335f506James Dong        mChunkSamples.push_back(copy);
246313aec890216948b0c364f8f92792129d0335f506James Dong        if (interleaveDurationUs == 0) {
24641f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            addOneStscTableEntry(++nChunks, 1);
24651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            bufferChunk(timestampUs);
246613aec890216948b0c364f8f92792129d0335f506James Dong        } else {
246713aec890216948b0c364f8f92792129d0335f506James Dong            if (chunkTimestampUs == 0) {
246813aec890216948b0c364f8f92792129d0335f506James Dong                chunkTimestampUs = timestampUs;
246913aec890216948b0c364f8f92792129d0335f506James Dong            } else {
247043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                int64_t chunkDurationUs = timestampUs - chunkTimestampUs;
247143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                if (chunkDurationUs > interleaveDurationUs) {
247243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    if (chunkDurationUs > mMaxChunkDurationUs) {
247343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                        mMaxChunkDurationUs = chunkDurationUs;
247443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    }
247513aec890216948b0c364f8f92792129d0335f506James Dong                    ++nChunks;
247613aec890216948b0c364f8f92792129d0335f506James Dong                    if (nChunks == 1 ||  // First chunk
2477c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        lastSamplesPerChunk != mChunkSamples.size()) {
2478c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        lastSamplesPerChunk = mChunkSamples.size();
2479c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        addOneStscTableEntry(nChunks, lastSamplesPerChunk);
248013aec890216948b0c364f8f92792129d0335f506James Dong                    }
24811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                    bufferChunk(timestampUs);
248213aec890216948b0c364f8f92792129d0335f506James Dong                    chunkTimestampUs = timestampUs;
248313aec890216948b0c364f8f92792129d0335f506James Dong                }
248413aec890216948b0c364f8f92792129d0335f506James Dong            }
248513aec890216948b0c364f8f92792129d0335f506James Dong        }
248613aec890216948b0c364f8f92792129d0335f506James Dong
248720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
248825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
248945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    if (isTrackMalFormed()) {
2490690f546b0ee548dbfe997df36418e5302ec2d786James Dong        err = ERROR_MALFORMED;
2491f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong    }
249245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
2493bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    mOwner->trackProgressStatus(mTrackId, -1, err);
2494be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
249513aec890216948b0c364f8f92792129d0335f506James Dong    // Last chunk
249643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    if (!hasMultipleTracks) {
2497c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        addOneStscTableEntry(1, mStszTableEntries->count());
249858ae9c530247668f8af36e30d228c716c226b3d4James Dong    } else if (!mChunkSamples.empty()) {
24991f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        addOneStscTableEntry(++nChunks, mChunkSamples.size());
25001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        bufferChunk(timestampUs);
250113aec890216948b0c364f8f92792129d0335f506James Dong    }
250213aec890216948b0c364f8f92792129d0335f506James Dong
2503be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // We don't really know how long the last frame lasts, since
2504be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // there is no frame time after it, just repeat the previous
2505be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // frame's duration.
2506c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mStszTableEntries->count() == 1) {
25078f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        lastDurationUs = 0;  // A single sample's duration
250879761ab096f57c3027fad9556c2bc436672d614eJames Dong        lastDurationTicks = 0;
2509be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    } else {
2510be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        ++sampleCount;  // Count for the last sample
2511be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    }
2512a472613aec322e25891abf5c77bf3f7e3c244920James Dong
2513c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mStszTableEntries->count() <= 2) {
251479761ab096f57c3027fad9556c2bc436672d614eJames Dong        addOneSttsTableEntry(1, lastDurationTicks);
2515a472613aec322e25891abf5c77bf3f7e3c244920James Dong        if (sampleCount - 1 > 0) {
251679761ab096f57c3027fad9556c2bc436672d614eJames Dong            addOneSttsTableEntry(sampleCount - 1, lastDurationTicks);
2517a472613aec322e25891abf5c77bf3f7e3c244920James Dong        }
2518a472613aec322e25891abf5c77bf3f7e3c244920James Dong    } else {
251979761ab096f57c3027fad9556c2bc436672d614eJames Dong        addOneSttsTableEntry(sampleCount, lastDurationTicks);
2520a472613aec322e25891abf5c77bf3f7e3c244920James Dong    }
2521a472613aec322e25891abf5c77bf3f7e3c244920James Dong
252243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    // The last ctts box may not have been written yet, and this
252343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    // is to make sure that we write out the last ctts box.
252443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    if (currCttsOffsetTimeTicks == lastCttsOffsetTimeTicks) {
252543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        if (cttsSampleCount > 0) {
252643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
252743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        }
252843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    }
252943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong
2530c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs += lastDurationUs;
253125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = true;
253243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
253343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    sendTrackSummary(hasMultipleTracks);
253443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
2535df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s",
253611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            count, nZeroLengthFrames, mStszTableEntries->count(), trackName);
2537872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (mIsAudio) {
2538a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGI("Audio track drift time: %" PRId64 " us", mOwner->getDriftTimeUs());
2539872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
2540365a963142093a1cd8efdcea76b5f65096a5b115James Dong
254137187916a486504acaf83bea30147eb5fbf46ae5James Dong    if (err == ERROR_END_OF_STREAM) {
254237187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
254337187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
254437187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
2545365a963142093a1cd8efdcea76b5f65096a5b115James Dong}
2546365a963142093a1cd8efdcea76b5f65096a5b115James Dong
254745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dongbool MPEG4Writer::Track::isTrackMalFormed() const {
2548c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mStszTableEntries->count() == 0) {                      // no samples written
254929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("The number of recorded samples is 0");
255045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
255145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
255245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
2553c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (!mIsAudio && mStssTableEntries->count() == 0) {  // no sync frames for video
255429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("There are no sync frames for video track");
255545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
255645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
255745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
255845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    if (OK != checkCodecSpecificData()) {         // no codec specific data
255945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
256045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
256145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
256245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    return false;
256345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong}
256445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
256543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dongvoid MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) {
256607ec01904613a0bac32caaa8444b4690998faed7James Dong
256707ec01904613a0bac32caaa8444b4690998faed7James Dong    // Send track summary only if test mode is enabled.
256807ec01904613a0bac32caaa8444b4690998faed7James Dong    if (!isTestModeEnabled()) {
256907ec01904613a0bac32caaa8444b4690998faed7James Dong        return;
257007ec01904613a0bac32caaa8444b4690998faed7James Dong    }
257107ec01904613a0bac32caaa8444b4690998faed7James Dong
257243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    int trackNum = (mTrackId << 28);
257343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
257443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
257543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_TYPE,
257643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mIsAudio? 0: 1);
257743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
257843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
257943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_DURATION_MS,
258043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mTrackDurationUs / 1000);
258143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
258243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
258343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES,
2584c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    mStszTableEntries->count());
258543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
258686b7f47aa7482424cf8fd248f1315311919be3b0James Dong    {
258786b7f47aa7482424cf8fd248f1315311919be3b0James Dong        // The system delay time excluding the requested initial delay that
258886b7f47aa7482424cf8fd248f1315311919be3b0James Dong        // is used to eliminate the recording sound.
258986b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL;
259086b7f47aa7482424cf8fd248f1315311919be3b0James Dong        if (startTimeOffsetUs < 0) {  // Start time offset was not set
259186b7f47aa7482424cf8fd248f1315311919be3b0James Dong            startTimeOffsetUs = kInitialDelayTimeUs;
259286b7f47aa7482424cf8fd248f1315311919be3b0James Dong        }
259386b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t initialDelayUs =
259486b7f47aa7482424cf8fd248f1315311919be3b0James Dong            mFirstSampleTimeRealUs - mStartTimeRealUs - startTimeOffsetUs;
259586b7f47aa7482424cf8fd248f1315311919be3b0James Dong
259686b7f47aa7482424cf8fd248f1315311919be3b0James Dong        mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
259770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS,
259870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    (initialDelayUs) / 1000);
259986b7f47aa7482424cf8fd248f1315311919be3b0James Dong    }
260070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
260107ec01904613a0bac32caaa8444b4690998faed7James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
260207ec01904613a0bac32caaa8444b4690998faed7James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES,
260307ec01904613a0bac32caaa8444b4690998faed7James Dong                    mMdatSizeBytes / 1024);
260407ec01904613a0bac32caaa8444b4690998faed7James Dong
260543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    if (hasMultipleTracks) {
260643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong        mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
260743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS,
260843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mMaxChunkDurationUs / 1000);
260970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
261070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
261170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        if (mStartTimestampUs != moovStartTimeUs) {
261270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            int64_t startTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
261370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
261470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS,
261570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    startTimeOffsetUs / 1000);
261670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        }
261743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    }
261843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong}
261943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
2620faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) {
2621a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("trackProgressStatus: %" PRId64 " us", timeUs);
2622c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
2623215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    if (mTrackEveryTimeDurationUs > 0 &&
2624215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) {
2625a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("Fire time tracking progress status at %" PRId64 " us", timeUs);
2626bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err);
262793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        mPreviousTrackTimeUs = timeUs;
262893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
262993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
263093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
2631faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::trackProgressStatus(
2632bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        size_t trackId, int64_t timeUs, status_t err) {
2633faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    Mutex::Autolock lock(mLock);
2634bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    int32_t trackNum = (trackId << 28);
2635faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
2636faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Error notification
2637faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Do not consider ERROR_END_OF_STREAM an error
2638faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (err != OK && err != ERROR_END_OF_STREAM) {
2639bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_ERROR,
2640bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL,
2641faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
2642faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        return;
2643faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
2644faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
2645faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (timeUs == -1) {
2646faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send completion notification
2647bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
2648bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS,
2649faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
2650faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    } else {
2651faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send progress status
2652bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
2653bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME,
2654faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               timeUs / 1000);
2655faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
2656faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong}
2657faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
2658d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dongvoid MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) {
2659a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("setDriftTimeUs: %" PRId64 " us", driftTimeUs);
2660e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
2661d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong    mDriftTimeUs = driftTimeUs;
2662e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
2663e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
2664e259531ce59ab1f31de5a23124b22536f6a5a767James Dongint64_t MPEG4Writer::getDriftTimeUs() {
2665a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("getDriftTimeUs: %" PRId64 " us", mDriftTimeUs);
2666e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
2667e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    return mDriftTimeUs;
2668e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
2669e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
2670de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghuibool MPEG4Writer::isRealTimeRecording() const {
2671de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    return mIsRealTimeRecording;
2672de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui}
2673de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui
2674b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dongbool MPEG4Writer::useNalLengthFour() {
2675b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    return mUse4ByteNalLength;
2676b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong}
2677b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong
26781c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::Track::bufferChunk(int64_t timestampUs) {
26793856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("bufferChunk");
26801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
26811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Chunk chunk(this, timestampUs, mChunkSamples);
26821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mOwner->bufferChunk(chunk);
268313aec890216948b0c364f8f92792129d0335f506James Dong    mChunkSamples.clear();
268420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
268520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
26863b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const {
2687c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    return mTrackDurationUs;
268820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
268920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2690d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const {
2691d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return mEstimatedTrackSizeBytes;
2692d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
2693d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
2694690f546b0ee548dbfe997df36418e5302ec2d786James Dongstatus_t MPEG4Writer::Track::checkCodecSpecificData() const {
2695690f546b0ee548dbfe997df36418e5302ec2d786James Dong    const char *mime;
2696690f546b0ee548dbfe997df36418e5302ec2d786James Dong    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
2697690f546b0ee548dbfe997df36418e5302ec2d786James Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) ||
2698690f546b0ee548dbfe997df36418e5302ec2d786James Dong        !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) ||
2699690f546b0ee548dbfe997df36418e5302ec2d786James Dong        !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
2700690f546b0ee548dbfe997df36418e5302ec2d786James Dong        if (!mCodecSpecificData ||
2701690f546b0ee548dbfe997df36418e5302ec2d786James Dong            mCodecSpecificDataSize <= 0) {
270229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Missing codec specific data");
2703690f546b0ee548dbfe997df36418e5302ec2d786James Dong            return ERROR_MALFORMED;
2704690f546b0ee548dbfe997df36418e5302ec2d786James Dong        }
2705690f546b0ee548dbfe997df36418e5302ec2d786James Dong    } else {
2706690f546b0ee548dbfe997df36418e5302ec2d786James Dong        if (mCodecSpecificData ||
2707690f546b0ee548dbfe997df36418e5302ec2d786James Dong            mCodecSpecificDataSize > 0) {
270829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Unexepected codec specific data found");
2709690f546b0ee548dbfe997df36418e5302ec2d786James Dong            return ERROR_MALFORMED;
2710690f546b0ee548dbfe997df36418e5302ec2d786James Dong        }
2711690f546b0ee548dbfe997df36418e5302ec2d786James Dong    }
2712690f546b0ee548dbfe997df36418e5302ec2d786James Dong    return OK;
2713690f546b0ee548dbfe997df36418e5302ec2d786James Dong}
2714690f546b0ee548dbfe997df36418e5302ec2d786James Dong
2715b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeTrackHeader(bool use32BitOffset) {
271620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
27173856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("%s track time scale: %d",
27181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsAudio? "Audio": "Video", mTimeScale);
27198f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
2720efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    uint32_t now = getMpeg4Time();
2721b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("trak");
2722b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeTkhdBox(now);
2723b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->beginBox("mdia");
2724b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            writeMdhdBox(now);
2725b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            writeHdlrBox();
2726b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            mOwner->beginBox("minf");
2727b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                if (mIsAudio) {
2728b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                    writeSmhdBox();
2729b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                } else {
2730b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                    writeVmhdBox();
2731b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                }
2732b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                writeDinfBox();
2733b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                writeStblBox(use32BitOffset);
2734b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            mOwner->endBox();  // minf
2735b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->endBox();  // mdia
2736b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // trak
2737b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2738b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2739b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStblBox(bool use32BitOffset) {
2740b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stbl");
2741b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsd");
2742b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);               // version=0, flags=0
2743b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);               // entry count
2744b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mIsAudio) {
2745b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeAudioFourCCBox();
2746b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
2747b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeVideoFourCCBox();
2748b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2749b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsd
2750b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeSttsBox();
2751965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    writeCttsBox();
2752b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!mIsAudio) {
2753b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeStssBox();
2754b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2755b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStszBox();
2756b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStscBox();
2757b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStcoBox(use32BitOffset);
2758b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stbl
2759b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2760b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2761b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVideoFourCCBox() {
2762b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    const char *mime;
2763b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    bool success = mMeta->findCString(kKeyMIMEType, &mime);
2764b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
27658b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    const char *fourcc = getFourCCForMime(mime);
27668b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (fourcc == NULL) {
276729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Unknown mime type '%s'.", mime);
2768b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        CHECK(!"should not be here, unknown mime type.");
2769b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2770b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
27718b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    mOwner->beginBox(fourcc);        // video format
2772b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2773b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2774b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(1);           // data ref index
2775b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // predefined
2776b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2777b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
2778b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
2779b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
2780b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2781b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t width, height;
2782b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = mMeta->findInt32(kKeyWidth, &width);
2783b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = success && mMeta->findInt32(kKeyHeight, &height);
2784b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
2785b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2786b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(width);
2787b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(height);
2788b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x480000);    // horiz resolution
2789b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x480000);    // vert resolution
2790b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2791b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(1);           // frame count
2792c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo    mOwner->writeInt8(0);            // compressor string length
2793c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo    mOwner->write("                               ", 31);
2794b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x18);        // depth
2795b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(-1);          // predefined
2796b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
279743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_LT(23 + mCodecSpecificDataSize, 128);
2798b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2799b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
2800b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeMp4vEsdsBox();
2801b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
2802b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeD263Box();
2803b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
2804b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeAvccBox();
2805b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2806b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2807b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writePaspBox();
2808b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // mp4v, s263 or avc1
2809b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2810b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2811b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAudioFourCCBox() {
2812b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    const char *mime;
2813b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    bool success = mMeta->findCString(kKeyMIMEType, &mime);
2814b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
28158b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    const char *fourcc = getFourCCForMime(mime);
28168b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (fourcc == NULL) {
281729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Unknown mime type '%s'.", mime);
2818b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        CHECK(!"should not be here, unknown mime type.");
2819b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2820b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2821b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox(fourcc);        // audio format
2822b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2823b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2824b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x1);         // data ref index
2825b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2826b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2827b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t nChannels;
2828b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels));
2829b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(nChannels);   // channel count
2830b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(16);          // sample size
2831b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // predefined
2832b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2833b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2834b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t samplerate;
2835b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = mMeta->findInt32(kKeySampleRate, &samplerate);
2836b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
2837b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(samplerate << 16);
2838b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
2839b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeMp4aEsdsBox();
2840b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) ||
2841b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong               !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
2842b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeDamrBox();
2843b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2844b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2845b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2846b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2847b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4aEsdsBox() {
2848b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("esds");
2849b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
285043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mCodecSpecificDataSize, 0);
2851b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2852b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Make sure all sizes encode to a single byte.
285343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_LT(mCodecSpecificDataSize + 23, 128);
2854b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2855b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);     // version=0, flags=0
2856b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x03);   // ES_DescrTag
2857b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(23 + mCodecSpecificDataSize);
2858b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x0000);// ES_ID
2859b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x00);
2860b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2861b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x04);   // DecoderConfigDescrTag
2862b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(15 + mCodecSpecificDataSize);
2863b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x40);   // objectTypeIndication ISO/IEC 14492-2
2864b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x15);   // streamType AudioStream
2865b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2866b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x03);  // XXX
2867b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x00);   // buffer size 24-bit
2868ebada74ec20c6bd46e81d2f4c160ac176c10784dDaniel Bonnevier    int32_t bitRate;
2869ebada74ec20c6bd46e81d2f4c160ac176c10784dDaniel Bonnevier    bool success = mMeta->findInt32(kKeyBitRate, &bitRate);
2870ebada74ec20c6bd46e81d2f4c160ac176c10784dDaniel Bonnevier    mOwner->writeInt32(success ? bitRate : 96000); // max bit rate
2871ebada74ec20c6bd46e81d2f4c160ac176c10784dDaniel Bonnevier    mOwner->writeInt32(success ? bitRate : 96000); // avg bit rate
2872b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2873b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x05);   // DecoderSpecificInfoTag
2874b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(mCodecSpecificDataSize);
2875b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
2876b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2877b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData2[] = {
2878b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x06,  // SLConfigDescriptorTag
2879b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x01,
2880b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x02
2881b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
2882b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData2, sizeof(kData2));
2883b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2884b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // esds
2885b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2886b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2887b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4vEsdsBox() {
2888b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
288943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mCodecSpecificDataSize, 0);
2890b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("esds");
2891b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2892b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);    // version=0, flags=0
2893b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2894b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x03);  // ES_DescrTag
2895b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(23 + mCodecSpecificDataSize);
2896b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x0000);  // ES_ID
2897b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x1f);
2898b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2899b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x04);  // DecoderConfigDescrTag
2900b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(15 + mCodecSpecificDataSize);
2901b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x20);  // objectTypeIndication ISO/IEC 14492-2
2902b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x11);  // streamType VisualStream
2903b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2904b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData[] = {
2905b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x01, 0x77, 0x00,
2906b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x00, 0x03, 0xe8, 0x00,
2907b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x00, 0x03, 0xe8, 0x00
2908b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
2909b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData, sizeof(kData));
2910b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2911b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x05);  // DecoderSpecificInfoTag
2912b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2913b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(mCodecSpecificDataSize);
2914b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
2915b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2916b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData2[] = {
2917b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x06,  // SLConfigDescriptorTag
2918b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x01,
2919b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x02
2920b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
2921b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData2, sizeof(kData2));
2922b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2923b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // esds
2924b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2925b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2926efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeTkhdBox(uint32_t now) {
2927b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("tkhd");
2928b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Flags = 7 to indicate that the track is enabled, and
2929b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // part of the presentation
2930b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x07);          // version=0, flags=7
2931b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // creation time
2932b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // modification time
2933219f195159f93d627af2b243732e3f9020511a46James Dong    mOwner->writeInt32(mTrackId);      // track id starts with 1
2934b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
29358f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t trakDurationUs = getDurationUs();
2936b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t mvhdTimeScale = mOwner->getTimeScale();
2937b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t tkhdDuration =
2938b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
2939b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(tkhdDuration);  // in mvhd timescale
2940b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
2941b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
2942b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // layer
2943b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // alternate group
2944b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(mIsAudio ? 0x100 : 0);  // volume
2945b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // reserved
2946b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2947b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCompositionMatrix(mRotation);       // matrix
294820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2949b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mIsAudio) {
2950b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(0);
2951b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(0);
2952b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
2953b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        int32_t width, height;
2954b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        bool success = mMeta->findInt32(kKeyWidth, &width);
2955b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        success = success && mMeta->findInt32(kKeyHeight, &height);
2956b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        CHECK(success);
2957b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2958b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(width << 16);   // 32-bit fixed-point value
2959b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(height << 16);  // 32-bit fixed-point value
2960b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2961b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // tkhd
2962b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2963b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2964b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVmhdBox() {
2965b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("vmhd");
2966b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x01);        // version=0, flags=1
2967b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // graphics mode
2968b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // opcolor
2969b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);
2970b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);
2971b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2972b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2973b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2974b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeSmhdBox() {
2975b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("smhd");
2976b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // version=0, flags=0
2977b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // balance
2978b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2979b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2980b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2981b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2982b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeHdlrBox() {
2983b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("hdlr");
2984b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // version=0, flags=0
2985b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // component type: should be mhlr
2986b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeFourcc(mIsAudio ? "soun" : "vide");  // component subtype
2987b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
2988b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
2989b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
2990b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Removing "r" for the name string just makes the string 4 byte aligned
2991b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle");  // name
2992b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2993b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2994b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2995efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeMdhdBox(uint32_t now) {
2996b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int64_t trakDurationUs = getDurationUs();
2997b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("mdhd");
2998b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // version=0, flags=0
2999b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // creation time
3000b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // modification time
3001b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(mTimeScale);    // media timescale
3002b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6;
3003b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(mdhdDuration);  // use media timescale
3004b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Language follows the three letter standard ISO-639-2/T
3005b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // 'e', 'n', 'g' for "English", for instance.
3006b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Each character is packed as the difference between its ASCII value and 0x60.
3007b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // For "English", these are 00101, 01110, 00111.
3008b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // XXX: Where is the padding bit located: 0x15C7?
3009b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // language code
3010b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // predefined
3011b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3012b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3013b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3014b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDamrBox() {
3015b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // 3gpp2 Spec AMRSampleEntry fields
3016b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("damr");
3017b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCString("   ");  // vendor: 4 bytes
3018b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);         // decoder version
3019b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x83FF);   // mode set: all enabled
3020b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);         // mode change period
3021b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(1);         // frames per sample
3022b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3023b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3024b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3025b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeUrlBox() {
3026b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // The table index here refers to the sample description index
3027b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // in the sample table entries.
3028b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("url ");
3029b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);  // version=0, flags=1 (self-contained)
3030b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // url
3031b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3032b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3033b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDrefBox() {
3034b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("dref");
3035b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3036b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);  // entry count (either url or urn)
3037b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeUrlBox();
3038b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // dref
3039b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3040b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3041b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDinfBox() {
3042b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("dinf");
3043b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeDrefBox();
3044b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // dinf
3045b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3046b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3047b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAvccBox() {
3048b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
304943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GE(mCodecSpecificDataSize, 5);
3050b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3051b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Patch avcc's lengthSize field to match the number
3052b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // of bytes we use to indicate the size of a nal unit.
3053b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    uint8_t *ptr = (uint8_t *)mCodecSpecificData;
3054b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    ptr[4] = (ptr[4] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1);
3055b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("avcC");
3056b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
3057b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // avcC
3058b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3059b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3060b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeD263Box() {
3061b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("d263");
3062b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // vendor
3063b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);   // decoder version
3064b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(10);  // level: 10
3065b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);   // profile: 0
3066b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // d263
3067b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3068b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3069b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong// This is useful if the pixel is not square
3070b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writePaspBox() {
3071b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("pasp");
3072b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1 << 16);  // hspacing
3073b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1 << 16);  // vspacing
3074b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // pasp
3075b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3076b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3077000e18370baae60ffd9f25b509501dd8c26deabfJames Dongint32_t MPEG4Writer::Track::getStartTimeOffsetScaledTime() const {
3078a472613aec322e25891abf5c77bf3f7e3c244920James Dong    int64_t trackStartTimeOffsetUs = 0;
3079b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
3080b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mStartTimestampUs != moovStartTimeUs) {
308143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_GT(mStartTimestampUs, moovStartTimeUs);
3082b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        trackStartTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
3083b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3084000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    return (trackStartTimeOffsetUs *  mTimeScale + 500000LL) / 1000000LL;
3085000e18370baae60ffd9f25b509501dd8c26deabfJames Dong}
3086000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
3087000e18370baae60ffd9f25b509501dd8c26deabfJames Dongvoid MPEG4Writer::Track::writeSttsBox() {
3088000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->beginBox("stts");
3089000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3090c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t duration;
3091c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    CHECK(mSttsTableEntries->get(duration, 1));
3092c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    duration = htonl(duration);  // Back to host byte order
3093c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime()), 1);
3094c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->write(mOwner);
3095b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stts
3096b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
309720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3098965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::writeCttsBox() {
3099965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    if (mIsAudio) {  // ctts is not for audio
3100965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
3101965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
3102965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
3103000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    // There is no B frame at all
3104000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    if (mMinCttsOffsetTimeUs == mMaxCttsOffsetTimeUs) {
3105000e18370baae60ffd9f25b509501dd8c26deabfJames Dong        return;
3106000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    }
3107000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
3108965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    // Do not write ctts box when there is no need to have it.
3109c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mCttsTableEntries->count() == 0) {
3110965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
3111965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
3112965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
3113a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("ctts box has %d entries with range [%" PRId64 ", %" PRId64 "]",
3114c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mCttsTableEntries->count(), mMinCttsOffsetTimeUs, mMaxCttsOffsetTimeUs);
3115965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
3116965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mOwner->beginBox("ctts");
3117000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3118c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t duration;
3119c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    CHECK(mCttsTableEntries->get(duration, 1));
3120c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    duration = htonl(duration);  // Back host byte order
3121c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime() - mMinCttsOffsetTimeUs), 1);
3122c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->write(mOwner);
3123965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mOwner->endBox();  // ctts
3124965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong}
3125965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
3126b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStssBox() {
3127b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stss");
3128b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3129c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries->write(mOwner);
3130b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stss
3131b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
313225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
3133b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStszBox() {
3134b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsz");
3135b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3136c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mOwner->writeInt32(0);
3137c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStszTableEntries->write(mOwner);
3138b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsz
3139b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
314020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3141b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStscBox() {
3142b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsc");
3143b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3144c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStscTableEntries->write(mOwner);
3145b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsc
3146b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
314720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3148b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) {
3149b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox(use32BitOffset? "stco": "co64");
3150b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3151c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (use32BitOffset) {
3152c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStcoTableEntries->write(mOwner);
3153c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    } else {
3154c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mCo64TableEntries->write(mOwner);
3155b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3156b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stco or co64
315720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
315820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
315907b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeUdtaBox() {
316007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    beginBox("udta");
316107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeGeoDataBox();
316207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    endBox();
316307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
316407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
3165e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeHdlr() {
3166e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("hdlr");
3167e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Version, Flags
3168e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Predefined
3169e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeFourcc("mdta");
3170e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Reserved[0]
3171e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Reserved[1]
3172e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Reserved[2]
3173e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt8(0);  // Name (empty)
3174e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox();
3175e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3176e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3177e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeKeys() {
3178e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    size_t count = mMetaKeys->countEntries();
3179e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3180e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("keys");
3181e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0);     // Version, Flags
3182e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(count); // Entry_count
3183e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    for (size_t i = 0; i < count; i++) {
3184e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        AMessage::Type type;
3185e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        const char *key = mMetaKeys->getEntryNameAt(i, &type);
3186e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        size_t n = strlen(key);
3187e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        writeInt32(n + 8);
3188e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        writeFourcc("mdta");
3189e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        write(key, n); // write without the \0
3190e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
3191e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox();
3192e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3193e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3194e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeIlst() {
3195e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    size_t count = mMetaKeys->countEntries();
3196e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3197e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("ilst");
3198e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    for (size_t i = 0; i < count; i++) {
3199e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        beginBox(i + 1); // key id (1-based)
3200e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        beginBox("data");
3201e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        AMessage::Type type;
3202e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        const char *key = mMetaKeys->getEntryNameAt(i, &type);
3203e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        switch (type) {
32047c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            case AMessage::kTypeString:
32057c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            {
32067c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                AString val;
32077c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                CHECK(mMetaKeys->findString(key, &val));
32087c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(1); // type = UTF8
32097c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0); // default country/language
32107c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                write(val.c_str(), strlen(val.c_str())); // write without \0
32117c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                break;
32127c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            }
32137c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
3214e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            case AMessage::kTypeFloat:
3215e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            {
3216e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                float val;
3217e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                CHECK(mMetaKeys->findFloat(key, &val));
32187c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(23); // type = float32
32197c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0);  // default country/language
3220e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                writeInt32(*reinterpret_cast<int32_t *>(&val));
3221e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                break;
3222e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            }
3223e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3224e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            case AMessage::kTypeInt32:
3225e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            {
3226e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                int32_t val;
3227e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                CHECK(mMetaKeys->findInt32(key, &val));
32287c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(67); // type = signed int32
32297c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0);  // default country/language
3230e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                writeInt32(val);
3231e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                break;
3232e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            }
3233e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3234e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            default:
3235e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            {
3236e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                ALOGW("Unsupported key type, writing 0 instead");
32377c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(77); // type = unsigned int32
32387c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0);  // default country/language
3239e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                writeInt32(0);
3240e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                break;
3241e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            }
3242e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        }
3243e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        endBox(); // data
3244e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        endBox(); // key id
3245e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
3246e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox(); // ilst
3247e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3248e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3249e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeMetaBox() {
3250e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    size_t count = mMetaKeys->countEntries();
3251e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    if (count == 0) {
3252e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        return;
3253e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
3254e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3255e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("meta");
3256e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeHdlr();
3257e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeKeys();
3258e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeIlst();
3259e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox();
3260e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3261e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
326207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/*
326307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard.
326407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */
326507b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeGeoDataBox() {
326607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    beginBox("\xA9xyz");
326707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    /*
326807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * For historical reasons, any user data start
326907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * with "\0xA9", must be followed by its assoicated
327007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * language code.
3271432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong     * 0x0012: text string length
3272432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong     * 0x15c7: lang (locale) code: en
327307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     */
327407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeInt32(0x001215c7);
327507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeLatitude(mLatitudex10000);
327607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeLongitude(mLongitudex10000);
327707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeInt8(0x2F);
327807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    endBox();
327907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
328007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
328120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
3282